使用OpenCV在网络摄像头上绘制
我想使用OpenCV在网络摄像头屏幕上绘制/绘制。 由于我是从凸轮读取的,所以这些帧不断变化,所以我试图找出一种方法来保存或保存当前帧上的图形,并将其用于下一帧。 下面的代码允许你在屏幕上绘图,但是当它到达下一帧时,绘图消失并重新开始。
有人可以帮助我...谢谢。
CvCapture *input;
input = cvCaptureFromCAM( 0 );
cvSetMouseCallback("Demo",&on_mouse, 0);
for(;;)
{
frame = cvQueryFrame(input);
if(!image)
{
image = cvCreateImage( cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);
screenBuffer = cvCreateImage( cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);
}
cvCopy(frame, image, 0);
if(drawing) //drawing is a global variable
{
cvCircle(image, cvPoint(last_x,last_y), 10,CV_RGB(red,green,blue), -1, CV_AA, 0);
cvCopy(image, screenBuffer, 0);
}
cvShowImage( "Demo", screenBuffer );
}
void on_mouse( int event, int x, int y, int flags, void* param )
{
last_x = x;
last_y = y;
if(event==CV_EVENT_LBUTTONDOWN)
{
drawing = 1;
}
}
我不会详细介绍为什么你的方法不好,但请记住为绘图创建2个额外的框架有点太过分了。
您意识到所有这些奇怪的东西都是在用于捕捉新帧的相同线程上完成的,这一点很重要。 这意味着什么? 这意味着您在循环内添加的额外代码会减慢捕获和显示新帧的过程 。 换句话说, 你正在通过降低应用程序的帧率来破坏自己 。 如果你不在乎,没关系。 如果你这样做,我的提示是你将捕获的帧堆叠到一个缓冲区中,并让另一个线程读取,处理并显示它们。
好的,所以你真的想画一个显示捕获帧的窗口。 那么, 你不能做的显而易见的事情(你自己也发现了这一点)是因为在每个循环中用新数据取代了框架,所以不能在捕获的框架上绘制图形。 所以你会怎么做? 您创建第二个框架来完成绘图。 我们称之为drawing_frame。
在drawing_frame上唯一的东西是当鼠标移动到窗口上时点击鼠标的LBUTTON(第二个点击在ON / OFF之间切换)时将出现的圆圈。
在发生圆圈绘制后, drawing_frame覆盖在相机捕获的框架的顶部 。 这个过程在CPU上有点贵,而且由于我们在应用程序的主线程中这样做,它也会降低帧率。
我强烈建议大家有兴趣使用OpenCV添加/合并/叠加透明帧,以查看OpenCV中的透明图像叠加层。
顺便说一句 ,我使用cvCaptureFromCAM(-1)
因为我在Linux上。 你可能应该改变为适合你的任何东西。 根据你的帖子,它是cvCaptureFromCAM(0)
。
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
int drawing = 0;
int last_x = 0;
int last_y = 0;
void on_mouse(int event, int x, int y, int flags, void* param)
{
last_x = x;
last_y = y;
if (event == CV_EVENT_LBUTTONDOWN)
{
// switches between On and Off
if (drawing)
drawing = 0;
else
drawing = 1;
}
}
int main()
{
CvCapture* capture = NULL;
if ((capture = cvCaptureFromCAM(-1)) == NULL)
{
fprintf(stderr, "ERROR: capture is NULL n");
return -1;
}
cvNamedWindow("mywindow", CV_WINDOW_AUTOSIZE);
cvQueryFrame(capture); // Sometimes needed to get correct data
cvSetMouseCallback("mywindow",&on_mouse, 0);
IplImage* frame = NULL;
IplImage* drawing_frame = NULL;
while (1)
{
if ((frame = cvQueryFrame(capture)) == NULL)
{
fprintf( stderr, "ERROR: cvQueryFrame failedn");
break;
}
if (frame == NULL)
{
fprintf( stderr, "WARNING: cvQueryFrame returned NULL, sleeping..n");
usleep(100000);
continue;
}
if (!drawing_frame) // This frame is created only once
{
drawing_frame = cvCreateImage(cvSize(frame->width, frame->height), frame->depth, frame->nChannels);
cvZero(drawing_frame);
}
if (drawing)
{
cvCircle(drawing_frame, cvPoint(last_x,last_y), 10,CV_RGB(0, 255, 0), -1, CV_AA, 0);
// For overlaying (copying transparent images) in OpenCV
// http://www.aishack.in/2010/07/transparent-image-overlays-in-opencv/
for (int x = 0; x < frame->width; x++)
{
for (int y = 0; y < frame->height; y++)
{
CvScalar source = cvGet2D(frame, y, x);
CvScalar over = cvGet2D(drawing_frame, y, x);
CvScalar merged;
CvScalar S = { 1,1,1,1 };
CvScalar D = { 1,1,1,1 };
for(int i = 0; i < 4; i++)
merged.val[i] = (S.val[i] * source.val[i] + D.val[i] * over.val[i]);
cvSet2D(frame, y, x, merged);
}
}
}
cvShowImage("mywindow", frame);
int key = cvWaitKey(10);
if (key == 113) // q was pressed on the keyboard
break;
}
cvReleaseImage(&frame);
cvReleaseImage(&drawing_frame);
cvReleaseCapture(&capture);
cvDestroyWindow("mywindow");
return 0;
}
你通常会有添加图像的问题(它们最终会饱和),所以我想这就是你重新开始的原因。 我看到你有彩色图像......如果你使用像OpenGL这样更强大的东西来绘制图画,你可以使用叠加图来绘制图画。 否则检查一下:
http://aishack.in/tutorials/transparent-image-overlays-in-opencv/
链接地址: http://www.djcxy.com/p/6031.html