Ask Your Question
2

setMouseCallback multiples rectangles

asked 2018-12-18 08:51:12 -0600

cherault gravatar image

Dear all,

I am trying to show various fixed rectangles within a video flow, using the mouse. The fixed rectangle is set as follow within the onMouse function::

void onMouse(int event, int x, int y, int flags, void* param)
{
   Rect rec = Rect(x, y, 100, 150);

   if(event == EVENT_LBUTTONDOWN)
   {
       counter++;
   }
}

So, when I move the mouse, I see the "rec" moving until I click down the left button. When a click is detected, I would like to show the ROI build within the main frame, and build outside the main frame my ROI through:

        roi1 = frame(rec);
        imshow("Roi1", roi1);

The problem is that the ROI is frozen and doesn't show the real time roi frame. I need also to repeat the operation 3 times.

Could you help me to solve this problem ?

Thanks for your help and support.

Regards,

Christophe

edit retag flag offensive close merge delete

Comments

Have you try selectROI ?

LBerger gravatar imageLBerger ( 2018-12-18 08:57:34 -0600 )edit

Yes, thank you for the proposal. The problem with the selectRoi is that I need to use it during the video flow. Unfortunately, this function doesn't work properly if I start the video without passing through the first frame (fixed image). I could use the selectRoi if and only if it works within the while loop.

Do you have some idea for that ?

Regards,

cherault gravatar imagecherault ( 2018-12-18 09:07:53 -0600 )edit
1

@cherault, maybe you should rethink the whole workflow here,

the "human selection" mode is something entirely artificial, and probably only there to simplify the sample.

in the real world, you would get your initial Rects from e.g. some object detection, and there might be no human interaction at all.

The problem is that the ROI is frozen and doesn't show the real time roi frame

that's for a reason. it's next to impossible to mark a (tight enough) fitting bbox on moving video ;)

what are you trying to achieve with the tracking, in general ? what is your "use-case" ?

berak gravatar imageberak ( 2018-12-18 09:53:29 -0600 )edit

Hello Berak, Thanks for your answer as LBerger. I understand what you wrote, and I don't really need the trackers to achieve my goal, but sometimes, real world is not enough ! ;-)

Seriously, I will try to explain my need:

I have an active video flow (640x480px). Within this flow, I will use the mouse to activate a square or rectangle which is defined (for example 100x150px). The mouse permit to activate (click left button down), move (left button down + move) and defined the final position (left button up). I just need to repeat this operation 3 times, and show the 3 squares on screen (active video flow), once it's done.

Do you think it's possible to realize this ?

Regards,

cherault gravatar imagecherault ( 2018-12-19 00:25:40 -0600 )edit
1

@cherault see the code on other question i think it will be helpful

sturkmen gravatar imagesturkmen ( 2018-12-19 01:31:32 -0600 )edit

@sturkmen, morning ;) wrong link above ?

@cherault, again there is selectROIs (note the plural !). and sure it would be possible to write something similar on your own.

also, your previous examples were using video files, so no problem to stop it for a moment.

I just need to repeat this operation 3 times

how do you know about those numbers ? it might vary, no ?

I will use the mouse to activate a square or rectangle which is defined (for example 100x150px).

i probably misunderstand the purpose of your program (and you're still a bit unclear here), but if it's for tracking, a fixed roi size won't work nicely.

berak gravatar imageberak ( 2018-12-19 01:42:10 -0600 )edit

Hello Sturkmen and Berak, thanks for your informations. Is the selectRois works...perfect ! I will try it again. For the number (x3) it's just my need, and yes, it might vary, but now, I want just 3 "rois" represented by rectangles or squares defined in the code. Show them within the frames.

So, thanks to you. I will try to do something "smart", and go back to you if needed.

Regards, and have a good day.

cherault gravatar imagecherault ( 2018-12-19 01:49:10 -0600 )edit

To be clear, I just want to draw, with a mouse, 3 formated squares within a video frame. I though it was a simple task, but it's not ! :-)

cherault gravatar imagecherault ( 2018-12-19 02:11:58 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
2

answered 2018-12-19 15:11:45 -0600

another example

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

bool selectObject = false;
Rect selection;
Point origin;
Mat image;

vector<Rect> selections;

static void onMouse(int event, int x, int y, int, void*)
{
    switch (event)
    {
    case EVENT_LBUTTONDOWN:
        origin = Point(x, y);
        selectObject = true;
        break;
    case EVENT_LBUTTONUP:
    {
        selectObject = false;
        selections.push_back(selection);
        break;
    }
    }

    if (selectObject)
    {
        selection.x = MIN(x, origin.x);
        selection.y = MIN(y, origin.y);
        selection.width = std::abs(x - origin.x) + 1;
        selection.height = std::abs(y - origin.y) + 1;
        selection &= Rect(0, 0, image.cols, image.rows);
    }
}

int main(int argc, char** argv)
{
    VideoCapture cap(0);
    namedWindow("Demo");
    setMouseCallback("Demo", onMouse);

    while (true)
    {
        cap >> image;

        for(int i=0; i < selections.size(); i++)
        {
            rectangle(image, selections[i], Scalar(0, 255, 0), 2);
        }

        if (selectObject && selection.width > 0 && selection.height > 0)
        {
            rectangle(image, selection, Scalar(0, 0, 255), 2);
        }
        imshow("Demo", image);
        char key = waitKey(1);

        if (key == 27)
            break;

        if (key == 'c') // clear selections
        {
            selections.clear();
        }
    }


    return 0;
}
edit flag offensive delete link more

Comments

Hello Sturkmen, Thank you for your proposal but I found the solution yesterday, and it's pretty close to yours. But one more time thank you so much for your help and support. Have a good day !

cherault gravatar imagecherault ( 2018-12-20 03:09:44 -0600 )edit

Hello Strukmen,

I modified your code to show the selection moving the mouse, and set the selection with fixed size. But I want to show for each selection.size() a specific "roi" based on the Rect "selection". The problem is: selecting for example 3 rois, I have the same images on them ! I am based on the coordinates of each Rect "selection, but it doesn't work. How can I do that properly ?

Thanks for all.

Regards,

cherault gravatar imagecherault ( 2018-12-20 04:33:47 -0600 )edit

Please forget my last question. The problem is solved. Thank you for your help and support to all of you ! Regards,

cherault gravatar imagecherault ( 2018-12-20 06:21:09 -0600 )edit
2

answered 2018-12-19 02:11:32 -0600

LBerger gravatar image

updated 2018-12-19 02:24:11 -0600

selectROIS blocks video so May be you could try this

struct ParamRect {
    int rctEnCours;
    vector<Rect> r;
    int index = 0;
    Mat img;
    Mat result;
    int evt = 0;
    String nomFenetre;
};

void DefRectangle(int event, int x, int y, int flags, void *userData)
{
    ParamRect *pgc = (ParamRect*)userData;
    if (pgc->img.empty())
        return;
    pgc->evt = event;
    if ((flags&EVENT_FLAG_LBUTTON) != 0 && (flags & EVENT_FLAG_CTRLKEY) == 0)
    {
        if (pgc->rctEnCours == 0)
        {
            pgc->r[pgc->index].x = x;
            pgc->r[pgc->index].y = y;
            pgc->r[pgc->index].width = 0;
            pgc->r[pgc->index].height = 0;
            pgc->rctEnCours = 1;
        }
        else if (pgc->rctEnCours == 1)
        {
            Point tl = pgc->r[pgc->index].tl(), br = pgc->r[pgc->index].br();
            if (x != pgc->r[pgc->index].x)
            {
                if (x < pgc->r[pgc->index].x)
                {
                    pgc->r[pgc->index].x = x;
                    pgc->r[pgc->index].width = br.x - x - 1;
                }
                else
                    pgc->r[pgc->index].width = x - tl.x - 1;

            }
            if (y != pgc->r[pgc->index].y)
            {
                if (y < pgc->r[pgc->index].y)
                {
                    pgc->r[pgc->index].y = y;
                    pgc->r[pgc->index].height = br.y - y - 1;
                }
                else
                    pgc->r[pgc->index].height = y - tl.y - 1;

            }
            if (pgc->r[pgc->index].br().x > pgc->img.size().width)
            {
                pgc->r[pgc->index].width = pgc->img.size().width - pgc->r[pgc->index].x;
            }
            if (pgc->r[pgc->index].br().y > pgc->img.size().height)
            {
                pgc->r[pgc->index].height = pgc->img.size().height - pgc->r[pgc->index].y;
            }
        }
    }
    else 
        if (event == EVENT_LBUTTONUP && pgc->rctEnCours == 1)
        {
            pgc->rctEnCours = 0;
        }
    Mat img = pgc->img.clone();
    rectangle(img, pgc->r[pgc->index], Scalar(pgc->index * 64, 255 - pgc->index * 64, 0), 2);
    imshow(pgc->nomFenetre, img);
}


int main(int argc, char** argv)
{
    ParamRect pgc;
    pgc.rctEnCours = 0;
    pgc.nomFenetre = "Video";
    pgc.r = vector<Rect>(3);
    namedWindow(pgc.nomFenetre);
    setMouseCallback(pgc.nomFenetre, DefRectangle, &pgc);
    VideoCapture vv(CAP_MSMF);
    if (!vv.isOpened())
    {
        exit(0);
    }
    int code = 0;
    Mat img;
    namedWindow(pgc.nomFenetre);
    std::vector< Rect > r;
    while (code != 27)
    {
        vv >> pgc.img;
        code = waitKey(10);
        if (code >= 48 && code <= 51)
            pgc.index = code - 48;
        if (pgc.evt == 0)
        {
            Mat img = pgc.img.clone();
            for (int i = 0; i < pgc.r.size();i++)
            {
                if (pgc.r[i].area() > 0)
                {
                    rectangle(img, pgc.r[i], Scalar(i*64, 255-i*64, 0), 2);
                }
            }
            imshow(pgc.nomFenetre, img);

        }
        else
            pgc.evt = 0;
    }
    exit(0);
edit flag offensive delete link more

Comments

Thank you Laurent. I tried it but it doesn't work as I want. But, I will do some tests based on your solution. Thanks again for your help and support.

Regards,

cherault gravatar imagecherault ( 2018-12-19 02:21:54 -0600 )edit

Thanks for your update and work. I appreciate a lot !

cherault gravatar imagecherault ( 2018-12-19 03:24:48 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-12-18 08:51:12 -0600

Seen: 365 times

Last updated: Dec 19 '18