Ask Your Question
0

Showing a rectangle on the courser and cutting out

asked 2018-03-23 07:50:38 -0600

quina gravatar image

Hi there,

I am pretty new to programming and especially to C++. I want to write a program that does the following:

  1. Scans a specified folder for images; the first one is opened and displayed.
  2. The user has a rectangle of specified size over the courser and can "place" this rectangle anywhere he wants on that image by clicking. He can place as many rectangles as he wishes.
  3. If all the rectangles are placed, pressing a button (e.g. space) cuts all the parts of the image that are within those rectangles and saves them seperately in a specified folder (so that we have x image files for the respective x rectangles). The next image is loaded and we go back to step 2.

As you can see in the code below, my program currently shows one image that is passed in the command line and logs the position of mouse clicks inside the image window (becuase I will need the mouse position).

I am currently trying to draw a rectangle around the courser that moves with it, however, all the documenatries I read use the rectangle()-function, which I cannot find. I only have the cvRectangle()-function, and this one does not accept my image of type Mat. I found in a post on Stack Overflow that said I need to convert it to IplImage, but it does not like that either. Here (http://answers.opencv.org/question/62...) it says that the function has been removed and that i have to use Imgproc.rectangle(), but my program does not know Imgproc() (already tried to include the headerfile with that name and imgcodecs).

Another question would be how to make the rectangle move with the coursor and placing it not until the button is clicked. Since I am rather new to programming, I am not sure where the code for this would go. If I place it inside my CallBackFunc(), it does not know img. If I place it inside my main(), it cannot access x, y, ... I will probably have to pass img to the CallBackFunc, but everything in proper time. :)

I won't be able to check here every day, so I'll probably be unable to reply until monday. Thanks a lot for answers, though, it's much appreciated! Have a good weekend!

#include "stdafx.h"
#include "opencv2\core\core.hpp"
#include "opencv2\highgui\highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;


void CallBackFunc(int event, int x, int y, int flags, void* userdata)
{
    if (event == EVENT_LBUTTONDOWN)
    {
        cout << "Left button of the mouse is clicked - position (" << x << ", " << y << ")" << endl;
    }
    else if (event == EVENT_RBUTTONDOWN)
    {
        cout << "Right button of the mouse is clicked - position (" << x << ", " << y << ")" << endl;
    }
    else if (event == EVENT_MBUTTONDOWN)
    {
        cout << "Middle button of the mouse is clicked - position (" << x << ", " << y << ")" << endl;
    }
    //else if (event == EVENT_MOUSEMOVE)
    //{
    //  cout << "Mouse move over the window - position (" << x << ...
(more)
edit retag flag offensive close merge delete

Comments

you clearly have a documentation problem.

Imgproc.rectangle() is from java, cvRectangle() and IplImage are from C, none of it useful here.

here are the docs , just type "rectangle" into the search bar, and see ?

(on the other hand, you've come quite far !)

berak gravatar imageberak ( 2018-03-23 08:03:12 -0600 )edit

3: that would mean, not only drawing things, but keeping track of those.

berak gravatar imageberak ( 2018-03-23 08:20:48 -0600 )edit

Wow, this is weird. I could have sworn Visual Studio did not find rectangle() before - now I can use it without a problem. Maybe I hadn't inculded imgproc earlier when I tried. Anyway, when I use it in my main() now, it draws the rectangle, thanks!

Using it in my callback-function does not work, though, but I'll reply on your answer for that. :)

quina gravatar imagequina ( 2018-03-23 10:42:25 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2018-03-23 08:13:02 -0600

berak gravatar image

updated 2018-03-23 10:56:56 -0600

and here is, how to get your image Mat into the callback function:

in main, pass (the address of) your image to the callback:

setMouseCallback("Display window", CallBackFunc, &image);

inside the callback function, unwrap it:

void CallBackFunc(int event, int x, int y, int flags, void* userdata)
{
    Mat& image = *((Mat*)userdata); // 1st cast, then deref.
    if (event == EVENT_LBUTTONDOWN) // or rather, buttonup ?
    {
        cout << "Left button of the mouse is clicked - position (" << x << ", " << y << ")" << endl;
        rectangle(image, ? ? ? ?); // your task !
        imshow("Display window", image); // update our image.

    }
}

you should use the opencv headers like this:

#include "opencv2/core.hpp"  // forward slashes, please, and no subfolder
#include "opencv2/highgui.hpp"

you also need the imgproc header (for any of the drawing calls):

#include "opencv2/imgproc.hpp"
edit flag offensive delete link more

Comments

1

Thanks so much for your continued assistance!

As mentioned above, rectangle now works when used in main(). However, when using it like this, no rectangle is drawn:

void CallBackFunc(int event, int x, int y, int flags, void (*userdata))
{
    Mat& image = *((Mat*)userdata); // 1st cast, then deref.

    if (event == EVENT_LBUTTONDOWN)
    {
        cout << "Left button of the mouse is clicked - position (" << x << ", " << y << ")" << endl;
        rectangle(image, Point(x, y), Point(x + 100, y + 200), Scalar(0, 55, 255), +1, 4);
    }
[...]

In the main(), I now pass &image instead of NULL, like you suggested. Also, I don't really understand the line that casts and dereferences. If the function gets the address of image, why can't I just do image = *userdata?

quina gravatar imagequina ( 2018-03-23 10:47:40 -0600 )edit

userdata is a void* pointer, it has no type to point to, only an address

berak gravatar imageberak ( 2018-03-23 10:50:27 -0600 )edit

I suppose it has to do with the function pointer of the callback function? Because when doing it like this, VS tells me that it "has to be a pointer to a complete object type", whatever this means.

What exactly does the Mat& image = part do? If &image gives me the address of image, how can we do this here when image has not even been declared in the context of the callback function yet? Or what exactly does Mat& img = mean?

Thanks in advance!

quina gravatar imagequina ( 2018-03-23 10:54:02 -0600 )edit

yea, pointers and references are confusing, and that the same symbol is reused for 2 different situations, does not make it any better, but that's more a general C / c++ problem. (you should want to read a book here, no ?)

Mat &image = imread(...)  makes a *reference* to it (it does not copy the Mat header)

some_func(Mat *m) {}
some_func(&image); <-- that's a pointer to a Mat, an address.

and apologies for my sloppyness here: you'll also need an imshow()l in the callback, see updated answer.

berak gravatar imageberak ( 2018-03-23 10:57:18 -0600 )edit

Thank you so much, updating the image did it!

quina gravatar imagequina ( 2018-03-23 11:01:18 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-03-23 07:50:38 -0600

Seen: 336 times

Last updated: Mar 23 '18