Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

How to use Callback to draw a rectangle in a video?

Hi, I'm trying to select a rectangle in a video, but when I run my code nothing shows up; this is the code I'm using:

cv::Mat frame;
const char* src_window = "Select ROI";

int drag = 0, select_flag = 0;

cv::Point point1, point2;    
bool callback = false;
void mouseHandler(int event, int x, int y, int flags, void* param);

int main(int argc, char** argv) {

cv::VideoCapture cap;

if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
        cap.open(argc == 2 ? argv[1][0] - '0' : 0);
else if( argc == 2 )
    cap.open(argv[1]);

if( !cap.isOpened() )
{
    std::cout << "Could not initialize capturing...\n";
    return 0;
}

cap >> frame;

cv::namedWindow(src_window,CV_WINDOW_AUTOSIZE);
//cv::imshow(src_window,frame);
//cv::setMouseCallback(src_window,mouseHandler,0);

for (;;) {
    cap >> frame;
    if( frame.empty() )
            break;

    if (callback == false) {
        cv::setMouseCallback(src_window,mouseHandler,0);
    }
    else {
    cv::imshow(src_window,frame);
    }
}
    cv::waitKey(0);
    return 0;
}

void mouseHandler(int event, int x, int y, int flags, void* param)
{
if (event == CV_EVENT_LBUTTONDOWN && !drag && !select_flag)
{
    /* left button clicked. ROI selection begins */
    point1 = cv::Point(x, y);
    drag = 1;
}

if (event == CV_EVENT_MOUSEMOVE && drag && !select_flag)
{
    /* mouse dragged. ROI being selected */
    cv::Mat img1 = frame.clone();
    point2 = cv::Point(x, y);
    cv::rectangle(img1, point1, point2, CV_RGB(255, 0, 0), 3, 8, 0);
    cv::imshow(src_window, img1);
}

if (event == CV_EVENT_LBUTTONUP && drag && !select_flag)
{
    cv::Mat img2 = frame.clone();
    point2 = cv::Point(x, y);
    drag = 0;
    select_flag = 1;
    cv::imshow(src_window, img2);
    callback = true;
}
}

I don't know what can I be doing wrong. Thanks for your help.

click to hide/show revision 2
fixed first program, something left to do

How to use Callback to draw a rectangle in a video?

Hi, I'm trying to select a rectangle in a video, but when I run my code nothing shows up; this is the code I'm using:

cv::Mat frame;
const char* src_window = "Select ROI";

int drag = 0, select_flag = 0;

cv::Point point1, point2;    
bool callback = false;
void mouseHandler(int event, int x, int y, int flags, void* param);

int main(int argc, char** argv) {

cv::VideoCapture cap;

if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
        cap.open(argc == 2 ? argv[1][0] - '0' : 0);
else if( argc == 2 )
    cap.open(argv[1]);

if( !cap.isOpened() )
{
    std::cout << "Could not initialize capturing...\n";
    return 0;
}

cap >> frame;

cv::namedWindow(src_window,CV_WINDOW_AUTOSIZE);
//cv::imshow(src_window,frame);
//cv::setMouseCallback(src_window,mouseHandler,0);

for (;;) {
    cap >> frame;
    if( frame.empty() )
            break;

    if (callback == false) {
        cv::setMouseCallback(src_window,mouseHandler,0);
    }
    else {
    cv::imshow(src_window,frame);
    }
}
    cv::waitKey(0);
    return 0;
}

void mouseHandler(int event, int x, int y, int flags, void* param)
{
if (event == CV_EVENT_LBUTTONDOWN && !drag && !select_flag)
{
    /* left button clicked. ROI selection begins */
    point1 = cv::Point(x, y);
    drag = 1;
}

if (event == CV_EVENT_MOUSEMOVE && drag && !select_flag)
{
    /* mouse dragged. ROI being selected */
    cv::Mat img1 = frame.clone();
    point2 = cv::Point(x, y);
    cv::rectangle(img1, point1, point2, CV_RGB(255, 0, 0), 3, 8, 0);
    cv::imshow(src_window, img1);
}

if (event == CV_EVENT_LBUTTONUP && drag && !select_flag)
{
    cv::Mat img2 = frame.clone();
    point2 = cv::Point(x, y);
    drag = 0;
    select_flag = 1;
    cv::imshow(src_window, img2);
    callback = true;
}
}

I don't know what can I be doing wrong. Thanks for your help.

UPDATE: Thanks to Vladislav Vinogradov now I can stream the video, but when I run the program it shows the first frame and stays like that until I click on the image, then starts the streaming, how can I modify this part so the streaming occurs since the beginning?

cap >> frame;

cv::namedWindow(src_window,CV_WINDOW_AUTOSIZE);
cv::imshow(src_window,frame);
//cv::setMouseCallback(src_window,mouseHandler,0);

for (;;) {
    if (callback) {
        cap >> frame;
        if( frame.empty() )
                break;
        cv::imshow(src_window,frame);
    }
    else {
        cap >> frame;
        cv::setMouseCallback(src_window,mouseHandler,0);
    }
    cv::waitKey(5);
}

How to use Callback to draw a rectangle in a video?

Hi, I'm trying to select a rectangle in a video, but when I run my code nothing shows up; this is the code I'm using:

cv::Mat frame;
const char* src_window = "Select ROI";

int drag = 0, select_flag = 0;

cv::Point point1, point2;    
bool callback = false;
void mouseHandler(int event, int x, int y, int flags, void* param);

int main(int argc, char** argv) {

cv::VideoCapture cap;

if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
        cap.open(argc == 2 ? argv[1][0] - '0' : 0);
else if( argc == 2 )
    cap.open(argv[1]);

if( !cap.isOpened() )
{
    std::cout << "Could not initialize capturing...\n";
    return 0;
}

cap >> frame;

cv::namedWindow(src_window,CV_WINDOW_AUTOSIZE);
//cv::imshow(src_window,frame);
//cv::setMouseCallback(src_window,mouseHandler,0);

for (;;) {
    cap >> frame;
    if( frame.empty() )
            break;

    if (callback == false) {
        cv::setMouseCallback(src_window,mouseHandler,0);
    }
    else {
    cv::imshow(src_window,frame);
    }
}
    cv::waitKey(0);
    return 0;
}

void mouseHandler(int event, int x, int y, int flags, void* param)
{
if (event == CV_EVENT_LBUTTONDOWN && !drag && !select_flag)
{
    /* left button clicked. ROI selection begins */
    point1 = cv::Point(x, y);
    drag = 1;
}

if (event == CV_EVENT_MOUSEMOVE && drag && !select_flag)
{
    /* mouse dragged. ROI being selected */
    cv::Mat img1 = frame.clone();
    point2 = cv::Point(x, y);
    cv::rectangle(img1, point1, point2, CV_RGB(255, 0, 0), 3, 8, 0);
    cv::imshow(src_window, img1);
}

if (event == CV_EVENT_LBUTTONUP && drag && !select_flag)
{
    cv::Mat img2 = frame.clone();
    point2 = cv::Point(x, y);
    drag = 0;
    select_flag = 1;
    cv::imshow(src_window, img2);
    callback = true;
}
}

I don't know what can I be doing wrong. Thanks for your help.

UPDATE: Thanks to Vladislav Vinogradov now I can stream the video, but when I run the program it shows the first frame and stays like that until I click on the image, then starts the streaming, how can I modify this part so the streaming occurs since the beginning?

cap >> frame;

cv::namedWindow(src_window,CV_WINDOW_AUTOSIZE);
cv::imshow(src_window,frame);
//cv::setMouseCallback(src_window,mouseHandler,0);

for (;;) {
    if (callback) {
        cap >> frame;
        if( frame.empty() )
                break;
        cv::imshow(src_window,frame);
    }
    else {
        cap >> frame;
        cv::setMouseCallback(src_window,mouseHandler,0);
    }
    cv::waitKey(5);
}