我想在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来显示框架上绘制的线条,但我们在imshow
循环中也有while(1)
,因此未显示绘制的线条
无论如何,我可以在实时视频供稿框架上画线。请帮忙。谢谢
答案 0 :(得分: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
图像中。唯一棘手的部分是一旦知道lines
(#3)的大小和类型就初始化src
。并且请记住先声明lines
(#0),以便图像像src一样在全局可见。
我还建议您熟悉:
operator+
的作用