【问题标题】:How to draw a line on frame from live video feed in opencv c++如何在opencv c ++中从实时视频源中画一条线
【发布时间】:2019-06-11 09:16:46
【问题描述】:

我想在 c++ 中的 opencv 框架上画一条线。为此,我在下面使用setMouseCallback(winName, onMouse, NULL); 的代码。在下面的代码中,我使用的是图像:

Mat src;
const char* winName = "Image";
int start_x = 0;
int start_y = 0;
bool run_once = false;

void onMouse(int event, int x, int y, int f, void*) 
{

    if (cv::EVENT_LBUTTONDOWN)
    {
        if (f == 1)
        {
            if (run_once == false)
            {
                start_x = x;
                start_y = y;
                cout << "start x,y is : " << x << y << endl;
                run_once = true;

            }
        }
        if (f == 3)
        {
            cout << "start x,y is : " << start_x << start_y << endl;
            int end_x = x;
            int end_y = y;
            cout << "end x,y  is : " << end_x << end_y << endl;
            cv::line(src, cv::Point(start_x, start_y), cv::Point(end_x, end_y), Scalar(255), 2, 8, 0);
            imshow(winName, src);
            run_once = false;
        }


    }
}

int main()
{
    src = imread(<img path>, 1);

    namedWindow(winName, WINDOW_NORMAL);
    setMouseCallback(winName, onMouse, NULL);
    imshow(winName, src);
    while(1)
    {


    }

}

使用上面的代码,如果我在框架上使用鼠标左键单击,它会记录start_x start_y。我将鼠标向左/向右拖动,然后单击鼠标右键,它会记录 end_x end_y 并简单地画一条线并显示它。这工作正常,但我想在实时视频帧中实现此功能。

我在实时视频帧中面临的问题是,在实时视频源中,我们不断在while(1) 循环中显示帧,因此在下一帧中删除了绘制的线

void onMouse(int event, int x, int y, int f, void*)
{
   /*
    * SAME AS ABOVE
    */
}

int main(int, char**)
{
    VideoCapture cap(1); // open the default camera
    if (!cap.isOpened())  // check if we succeeded
        return -1;
    namedWindow(winName, WINDOW_NORMAL);
    setMouseCallback(winName, onMouse, NULL);


    for (;;)
    {

        cap >> src; // get a new frame from camera
        imshow(winName, src);
        if (waitKey(30) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

在上面的代码中,我们有 onMouse 函数,我们使用 imshow 来显示在框架上绘制的线条,但我们在 while(1) 循环中也有 imshow,因此绘制的线条没有显示。

无论如何我可以在实时视频馈送帧上画线。请帮忙。谢谢

【问题讨论】:

  • 您可以在另一个Mat 对象中绘制而不是直接在src 上绘制,例如lines,然后使用imshow(winName, src + lines)。这样,src 将在切换到新框架时发生变化,但 lines 保持不变
  • @Sunreef 你能举个例子吗。我想我明白了,但需要更多参考。谢谢

标签: c++ opencv line


【解决方案1】:

正如@Sunreef 建议的那样,您可以创建单独的cv::Mat 以仅保留带有线条的图片并显示src 与此图片组合

// #0 NEW - add declaration of lines here so this Mat is visible in both onMouse and main scope
cv::Mat src, lines;

void onMouse(int event, int x, int y, int f, void*)
{        
    if (f == 3)
    {
        cout << "start x,y is : " << start_x << start_y << endl;
        int end_x = x;
        int end_y = y;
        cout << "end x,y  is : " << end_x << end_y << endl;

        // #1 NEW - draw line into lines instead of src
        cv::line(lines, cv::Point(start_x, start_y), cv::Point(end_x, end_y), Scalar(255), 2, 8, 0);

        // #2 NEW - remove unnecessary imshow here

        run_once = false;
     }
}

int main(int, char**)
{
    for (;;)
    {
        cap >> src; 

        // #3 NEW - init lines once, to be the same size, same type as src filled with zeros
        if(lines.empty()) lines = cv::Mat::zeros(src.size(), src.type());

        // #4 NEW - show lines combined with lines            
        imshow(winName, lines + src);

        if (waitKey(30) >= 0) break;
    }
    return 0;
}

这种方式只有lines 图像在onMouse (#1) 中更新。无需在onMouse 事件(#2)中显示它,因为它无论如何都会在主循环(#4)中显示。但在您实际显示线条之前,您将它们覆盖(添加)到src 图像。唯一棘手的部分是在知道src 的大小和类型后立即初始化lines(#3)。并且记得先声明lines(#0),这样图片就可以全局可见,就像src一样。

我还建议熟悉:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-10
    • 2015-05-27
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-09
    相关资源
    最近更新 更多