2012-06-04 8 views
5

Ho un video, quando il programma viene eseguito il primo fotogramma del video viene preso come immagine e l'utente può disegnare un rettangolo sull'immagine, dopo che il rettangolo è stato disegnato, l'utente deve fare clic con il tasto destro sull'immagine per confermare il rettangolo. Quando il mouse fa clic destro sull'immagine scompare e il video inizia a giocare con il rettangolo disegnato su di esso.Impostazione ROI con il mouse da un rettangolo su un video

Sono in grado di disegnare perfettamente il rettangolo ma non posso impostare quel rettangolo come ROI.

Quello che voglio fare è impostare quel rettangolo come Regione di interesse (ROI) per fare un po 'di elaborazione delle immagini su quella ROI. Non riesco a impostare il rettangolo che disegno come ROI.

Sto usando OpenCV con Visual Studio 2010. In seguito proverò ad integrare questo programma in QT creator.

Qualsiasi aiuto sarebbe apprezzato.

Grazie in anticipo.

Il mio codice completo è il seguente:

#include <stdlib.h> 
#include <stdio.h> 
#include <math.h> 
#include <string.h> 
#include<opencv2\opencv.hpp> 
#include <opencv2\highgui\highgui.hpp> 
#include <opencv/highgui.h> 
#include <opencv/cxcore.h> 
#include <opencv\cvaux.h> 

using namespace cv; 
using namespace std; 
void my_mouse_callback(int event, int x, int y, int flags, void* param); 
bool destroy=false; 
CvRect box; 
IplImage* image; 
IplImage* frame2; 
bool drawing_box = false; 

void draw_box(IplImage* img, CvRect rect) 
{ 
cvRectangle(img, cvPoint(box.x, box.y), cvPoint(box.x+box.width,box.y+box.height), 
      cvScalar(0,0,255) ,2); 

CvRect rect2=cvRect(box.x,box.y,box.width,box.height); 
//cvSetImageROI(image, rect2); //here I wanted to set the drawn rect as ROI 
} 

// Implement mouse callback 
void my_mouse_callback(int event, int x, int y, int flags, void* param){ 
IplImage* image = (IplImage*) param; 

switch(event){ 
    case CV_EVENT_MOUSEMOVE: 
     if(drawing_box) 
     { 
      box.width = x-box.x; 
      box.height = y-box.y; 
     } 
     break; 

    case CV_EVENT_LBUTTONDOWN: 
     drawing_box = true; 
     box = cvRect(x, y, 0, 0); 
     break; 

    case CV_EVENT_LBUTTONUP: 
     drawing_box = false; 
     if(box.width < 0) 
     { 
      box.x += box.width; 
      box.width *= -1; 
     } 
     if(box.height < 0) 
     { 
      box.y += box.height; 
      box.height *= -1; 
     } 
     draw_box(image, box); 
     break; 
    case CV_EVENT_RBUTTONUP: 
     destroy=true; 
    } 
} 

int main() 
{ 
    const char* name = "Box Example"; 
    cvNamedWindow(name); 

    box = cvRect(0,0,1,1); 

    CvCapture* capture = cvCreateFileCapture("C:\\video.mp4"); 
    image = cvQueryFrame(capture); 

    IplImage* temp = cvCloneImage(image); 
// Set up the callback 
    cvSetMouseCallback(name, my_mouse_callback, (void*) image); 


//IplImage *img2 = cvCreateImage(cvGetSize(temp),temp->depth,temp->nChannels); 

//cvNot(temp,temp); 
    /* copy subimage */ 
    //cvCopy(temp, temp, NULL); 

    // Main loop 
    while(1) 
{ 
    if(destroy) {cvDestroyWindow(name); break;} 
    cvCopyImage(image, temp); 
    if(drawing_box) 
     draw_box(temp, box); 
    cvMoveWindow(name, 200, 100); 
    cvShowImage(name, temp); 

    if(cvWaitKey(15)==27) 
     break; 
} 

//cvReleaseImage(&image); 
    cvReleaseImage(&temp); 
cvDestroyWindow(name); 

cvNamedWindow("Example2", CV_WINDOW_AUTOSIZE); 
    cvMoveWindow("Example2", 150, 150); 


    while(1) 
    { 
frame2 = cvQueryFrame(capture); 
draw_box(frame2,box); 
    if(!frame2) break; 
     cvShowImage("Example2", frame2); 
     char c = cvWaitKey(33); 
    if(c == 27) break; 
    } 
cvReleaseCapture(&capture); 
cvDestroyWindow("Example2"); 
    return 0; 
} 
+0

Quando si dice non si riesce a impostare il rettangolo come ROI, vuoi dire che si ottiene un codice di errore? Il codice viene compilato? –

+0

sì Ho ricevuto un errore quando ho fatto clic con il pulsante sinistro del mouse sull'immagine statica. Ha compilato correttamente anche se –

risposta

18

Si erano quasi arrivati. Un problema però: case CV_EVENT_RBUTTONUP ha bisogno di break e aggiungerei anche uno break nel caso default.

Il codice seguente imposta la ROI, esegue una semplice elaborazione in scala di grigi su di essa e quindi copia la ROI elaborata nuovamente sull'immagine originale.

A scopo di test, ho modificato il codice per utilizzare la macchina fotografica anziché caricare un file.

uscita:

enter image description here

Codice:

#include <stdlib.h> 
#include <stdio.h> 
#include <math.h> 
#include <string.h> 

#include <cv.h> 
#include <highgui.h> 

using namespace cv; 
using namespace std; 

void my_mouse_callback(int event, int x, int y, int flags, void* param); 

bool destroy=false; 
CvRect box; 
bool drawing_box = false; 

void draw_box(IplImage* img, CvRect rect) 
{ 
    cvRectangle(img, cvPoint(box.x, box.y), cvPoint(box.x+box.width,box.y+box.height), 
       cvScalar(0,0,255) ,2); 

    CvRect rect2=cvRect(box.x,box.y,box.width,box.height); 
    //cvSetImageROI(image, rect2); //here I wanted to set the drawn rect as ROI 
} 

// Implement mouse callback 
void my_mouse_callback(int event, int x, int y, int flags, void* param) 
{ 
    IplImage* frame = (IplImage*) param; 

    switch(event) 
    { 
     case CV_EVENT_MOUSEMOVE: 
     { 
      if(drawing_box) 
      { 
       box.width = x-box.x; 
       box.height = y-box.y; 
      } 
     } 
     break; 

     case CV_EVENT_LBUTTONDOWN: 
     { 
      drawing_box = true; 
      box = cvRect(x, y, 0, 0); 
     } 
     break; 

     case CV_EVENT_LBUTTONUP: 
     { 
      drawing_box = false; 
      if(box.width < 0) 
      { 
       box.x += box.width; 
       box.width *= -1; 
      } 

      if(box.height < 0) 
      { 
       box.y += box.height; 
       box.height *= -1; 
      } 

      draw_box(frame, box); 
     } 
     break; 

     case CV_EVENT_RBUTTONUP: 
     { 
      destroy=true; 
     } 
     break; 

     default: 
     break; 
    } 
} 

int main() 
{ 
    const char* name = "Box Example"; 
    cvNamedWindow(name); 
    box = cvRect(0,0,1,1); 

    CvCapture* capture = cvCaptureFromCAM(0); 
    if (!capture) 
    { 
    printf("!!! Failed cvCaptureFromCAM\n"); 
    return 1; 
    } 

    IplImage* image = cvQueryFrame(capture); 
    if (!image) 
    { 
    printf("!!! Failed cvQueryFrame #1\n"); 
    return 2; 
    } 

    IplImage* temp = cvCloneImage(image); 

    // Set up the callback 
    cvSetMouseCallback(name, my_mouse_callback, (void*) image); 

    // Main loop 
    while(1) 
    { 
    if (destroy) 
    { 
     cvDestroyWindow(name); break; 
    } 
    cvCopyImage(image, temp); 

    if (drawing_box) 
     draw_box(temp, box); 

    cvMoveWindow(name, 200, 100); 
    cvShowImage(name, temp); 

    if (cvWaitKey(15) == 27) 
     break; 
    } 

    cvReleaseImage(&temp); 
    cvDestroyWindow(name); 

    cvNamedWindow("Example2", CV_WINDOW_AUTOSIZE); 
    cvMoveWindow("Example2", 150, 150); 

    // Retrieve a single frame from the device and set the ROI 
    IplImage* vid_frame = cvQueryFrame(capture); 
    if (!vid_frame) 
    { 
    printf("!!! Failed cvQueryFrame #2\n"); 
    return 2; 
    } 

    cvSetImageROI(vid_frame, box); 

    // Allocate space for a single-channel ROI (to store grayscale frames) 
    IplImage* gray_roi = cvCreateImage(cvSize(box.width, box.height), IPL_DEPTH_8U, 1); 
    IplImage* rgb_roi = cvCreateImage(cvSize(box.width, box.height), IPL_DEPTH_8U, 3); 

    while(1) 
    { 
    if (!vid_frame) 
    { 
     vid_frame = cvQueryFrame(capture); 
     if (!vid_frame) 
     { 
      printf("!!! Failed cvQueryFrame #3\n"); 
      break; 
     } 
    } 

    draw_box(vid_frame, box); 

    // Set ROI and perform some processing (in this case, converting the ROI to grayscale) 
    cvSetImageROI(vid_frame, box); 
    cvCvtColor(vid_frame, gray_roi, CV_BGR2GRAY); 
     //cvShowImage("Example2", gray_roi); 

    /* At this point gray_roi has the size of thei ROI and contains the processed image. 
    * For fun, we copy the processed image back to the original image and display it on the screen! 
    */ 
    cvCvtColor(gray_roi, rgb_roi, CV_GRAY2BGR); 

    // As the ROI is still set, cvCopy is affected by it 
    cvCopy(rgb_roi, vid_frame, NULL); 

    // Now reset the ROI so cvShowImage displays the full image 
    cvResetImageROI(vid_frame); 
    cvShowImage("Example2", vid_frame); 

    char c = cvWaitKey(33); 
    if(c == 27) break; 

    vid_frame = NULL; 
    } 
    cvSaveImage("processed.jpg", vid_frame); 

    cvReleaseImage(&gray_roi); 
    cvReleaseImage(&rgb_roi); 
    cvReleaseCapture(&capture); 
    cvDestroyWindow("Example2"); 

    return 0; 
} 
+1

** karlphillip grazie mille. Mi hai capito bene Cosa era quello che volevo. ancora grazie mille :) –

+0

Ora sto cercando di modificare il codice per inserire più di 1 ROI. Il mio codice accetta solo un ROI come sai. Qualche idea su come posso farlo? –

+0

Non al momento, ma vai avanti e provalo tu stesso. Se riscontri problemi, torna indietro e fai una nuova domanda e avvisami su Twitter, così posso dare un'occhiata a questo. In bocca al lupo. – karlphillip

Problemi correlati