Draw a webcam using OpenCV

I want to draw / draw on a webcam screen using OpenCV. Since I am reading from the camera, the frames are constantly changing, so I am trying to find a way to save or save the drawing on the current frame and use it for the next frame. The code below allows you to draw on the screen, but when it receives the next frame, the picture disappears and starts.

Can someone please help me ... Thanks.

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; } } 
+7
source share
3 answers

Draw a separate image and then cvAdd () so that the video image immediately before it is distributed

+2
source

I will not understand all the details why your approach is bad, but keep in mind that creating two additional frames for drawing is a little too much.

It is important that you understand that all this strange substance is executed in the same stream that is used to capture new frames. Does that mean exactly? This means that the extra code that you add inside the loop will slow down the process of capturing and displaying new frames . In other words, you sabotage yourself by reducing the frame rate of your application. If you do not care, everything is fine. If you do this, my advice to you is that you add the captured frames to the buffer and read, process and show them another stream.

Okay, so you REALLY want to draw a window that displays captured frames. Well, the obvious thing that you cannot do (and you yourself discovered it) is that the picture cannot be drawn on the captured frame, because it is replaced with new data in each cycle. So what are you doing? You create a second frame for drawing. Let me call it draw_frame.

The only thing that will be in drawing_frame is the circles that will appear when the mouse moves around the window when the mouse LBUTTON is clicked (second click toggles between on / off).

After drawing a circle, the drawing_frame is superimposed on top of the frame captured by the camera . This process is a bit expensive on the processor, and since we do this in the main application thread, it will also reduce the frame rate.

I highly recommend to anyone interested in adding / merging / blending transparent frames with OpenCV, see Transparent image blending in OpenCV .

By the way, I am using cvCaptureFromCAM(-1) becouse I am on Linux. You should probably change this to everything that works for you. According to your post, this is 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 failed\n"); 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; } 
+1
source

You usually have problems adding images (they will eventually get enough), so I think that’s why you are starting over. I see that you have color images ... if you use more powerful material, such as OpenGL for your drawing, you can use overlay for your drawings. Otherwise check this:

http://aishack.in/tutorials/transparent-image-overlays-in-opencv/

0
source

All Articles