簡體   English   中英

使用OpenCV在網絡攝像頭上繪圖

[英]Draw on webcam using 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;
                }
        }

繪制成一個單獨的圖像,然后在顯示之前立即將cvAdd()添加到視頻圖像中

我不會詳細說明為什么你的方法很糟糕,但請記住,為繪圖創建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 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;
}

你通常會遇到添加圖像的問題(它們最終會飽和),所以我想這就是你重新開始的原因。 我看到你有彩色圖像...如果你為你的繪圖使用更強大的東西,比如OpenGL,你可以使用疊加層來繪制圖紙。 否則請查看:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM