Рисовать на веб-камеру с помощью OpenCV - PullRequest
7 голосов
/ 30 марта 2011

Я хочу рисовать / рисовать на экране веб-камеры, используя 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;
                }
        }

Ответы [ 3 ]

2 голосов
/ 30 марта 2011

Нарисуйте в отдельном изображении, а затем cvAdd (), что к видеоизображению непосредственно перед его отображением

1 голос
/ 31 марта 2011

Я не буду вдаваться во все детали, почему ваш подход плох, но имейте в виду, что создание 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;
}
0 голосов
/ 31 марта 2011

У вас обычно будут проблемы с добавлением изображений (они в конечном итоге будут насыщаться), поэтому я думаю, именно поэтому вы начинаете все сначала.Я вижу, у вас есть цветные изображения ... если вы используете более мощные вещи, такие как OpenGL, для своего рисунка, вы можете использовать наложение для своих рисунков.В противном случае проверьте это:

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

...