2011-03-30 20 views
7

Quiero dibujar/pintar en la pantalla de una cámara web usando OpenCV. Como estoy leyendo desde una cámara, los marcos cambian constantemente, así que estoy tratando de encontrar una manera de guardar o guardar el dibujo en el cuadro actual y usarlo para el siguiente fotograma. El código siguiente le permite dibujar en la pantalla pero cuando obtiene el siguiente cuadro, el dibujo se va y comienza de nuevo.Dibujar en la cámara web usando OpenCV

Podría alguien ayudarme ... Gracias.

  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; 
       } 
     } 
+0

relacionados con mis intereses. ¿Puede publicar en un comentario aquí qué documentación/tutoriales estaba usando? Me gustaría empezar por mí mismo en OpenCV. Gracias – sdadffdfd

+0

Es importante para nosotros que revise las preguntas y acepte la respuesta que resuelve su problema. – karlphillip

Respuesta

2

Dibuje en una imagen separada y luego cvAdd() que la imagen de vídeo inmediatamente antes dispalying que

0

Por lo general, tendrá problemas de adición de imágenes (que eventualmente se sature), así que supongo que es por eso empiezas de nuevo Veo que tienes imágenes en color ... si usas elementos más potentes como OpenGL para tu dibujo, puedes usar la superposición para tus dibujos. De lo contrario, mira esto:

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

1

no voy a entrar en todos los detalles de por qué su enfoque es mala, pero tenga en cuenta que la creación de 2 fotogramas adicionales para el dibujo es un poco demasiado.

Es importante que se dé cuenta de que todo esto cosas rizado se está haciendo en el mismo hilo utilizado para capturar nuevos marcos. Esto significa que exactamente? Significa que el código adicional que está agregando dentro del bucle ralentizará el proceso de capturar y mostrar nuevos fotogramas. En otras palabras, se está saboteando bajando la velocidad de cuadro de su aplicación. Si no te importa, está bien. Si lo haces, mi consejo para ti es que apiles los cuadros capturados en un búfer y lees otro hilo, los procesas y los muestras.

Ok, entonces usted REALMENTE desea dibujar sobre la ventana que muestra los cuadros capturados. Bueno, lo obvio que no puedes hacer (y lo has descubierto tú mismo) es que el dibujo no se puede hacer en el marco capturado porque el marco se reemplaza con datos nuevos en cada ciclo. Entonces, ¿Qué haces? Usted crea un segundo marco para hacer el dibujo. Llamémoslo drawing_frame.

La única cosa que va a estar en el drawing_frame son los círculos que aparecen cuando se mueve el ratón sobre la ventana, cuando se hace clic en el LBUTTON del ratón (un clic 2ª interruptores entre ON/OFF).

Después se produce el dibujo del círculo, la drawing_frame se superpone en la parte superior sobre el bastidor capturada por la cámara. Este proceso es un poco costoso en la CPU, y como lo estamos haciendo en el hilo principal de la aplicación, también reducirá la velocidad de cuadros.

Sugiero encarecidamente que todos los interesados ​​en agreguen/fusionen/superpongan marcos transparentes con OpenCV eche un vistazo a Transparent image overlays in OpenCV.

Por cierto, estoy usando cvCaptureFromCAM(-1) porque estoy en Linux. Probablemente deberías cambiar eso para lo que funcione para ti. Según su publicación, es 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

@Aziz Por favor, revise las respuestas y acepte la que resolvió su problema. – karlphillip

Cuestiones relacionadas