Я не буду вдаваться во все детали, почему ваш подход плох, но имейте в виду, что создание 2 дополнительных рамок для рисования - это слишком много.
Важно, чтобы вы поняли, что все это странный материал выполняется в том же потоке, который используется для захвата новых кадров.Это значит что именно?Это означает, что дополнительный код, который вы добавляете в цикл, замедлит процесс захвата и отображения новых кадров .Другими словами, вы саботируете себя, снижая частоту кадров вашего приложения.Если вам все равно, все в порядке.Если вы это сделаете, мой совет для вас, что вы укладываете захваченные кадры в буфер и имеете другой поток для чтения, обработки и отображения.
Хорошо, так что вы REALLY хотите рисовать поверхокно, которое отображает захваченные кадры.Что ж, очевидная вещь , которую вы не можете сделать (и вы обнаружили это самостоятельно), состоит в том, что рисование не может быть выполнено на захваченном кадре, поскольку кадр заменяется новыми данными в каждом цикле.Ну так что ты делаешь?Вы создаете 2-й кадр, чтобы сделать рисунок.Давайте назовем это drawing_frame .
Единственное, что будет на drawing_frame - это круги, которые появятся, когда мышь перемещается над окном, когда LBUTTONщелчка мыши (второй щелчок переключается между ВКЛ / ВЫКЛ).
После того, как происходит рисование круга, Drawing_frame накладывается сверху на кадр, захваченныйкамера .Этот процесс стоит немного дороже на процессоре, и так как мы делаем это в основном потоке приложения, он также уменьшит частоту кадров.
Я настоятельно рекомендую всем, кто заинтересован в добавлении / объединении/ оверлей прозрачных рамок с 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 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;
}