2012-06-04 6 views
5

프로그램이 실행될 때 비디오가 첫 번째 프레임이 이미지로 찍히고 사용자가 이미지에 직사각형을 그릴 수 있습니다. 사용자는 직사각형을 확인하기 위해 이미지를 오른쪽 클릭해야합니다. 마우스를 오른쪽 버튼으로 클릭하면 이미지가 사라지고 비디오가 그려진 사각형으로 재생되기 시작합니다.비디오의 사각형에서 마우스로 ROI 설정

사각형을 완벽하게 그릴 수는 있지만 해당 사각형을 ROI로 설정할 수 없습니다.

내가하고 싶은 것은 ROI (Region of Interest)로 설정하여 해당 ROI에서 일부 이미지 처리를하는 것입니다. ROI로 그릴 직사각형을 설정할 수 없습니다.

Visual Studio 2010에서 OpenCV를 사용하고 있습니다. 나중에이 프로그램을 QT 제작자에게 통합하려고합니다.

도움을 주시면 감사하겠습니다.

미리 감사드립니다.

#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

당신이, 당신이 투자 수익 (ROI)로 사각형을 설정 할 수없는 말을 무슨 뜻 수행 할 때 오류 코드를 얻을? 코드가 컴파일됩니까? –

+0

참으로 정적 이미지를 왼쪽 클릭했을 때 오류가 발생했습니다. –

답변

18

당신은 거의 있었다 다음과 같이

내 전체 코드입니다. 하나의 문제 : case CV_EVENT_RBUTTONUPbreak이 필요하고 default 경우에도 break을 추가합니다.

다음 코드는 ROI를 설정하고 간단한 회색조 처리를 수행 한 다음 처리 된 ROI를 원본 이미지로 다시 복사합니다.

테스트 목적으로 파일을로드하는 대신 내 카메라를 사용하도록 코드를 변경했습니다.

출력 :

enter image description here

코드 :

#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 대단히 감사합니다. 너는 나에게 맞았다. 나는 무엇을 원 했는가. 감사합니다. –

+0

이제 ROI를 두 개 이상 입력하는 코드를 편집하려고합니다. 내 코드는 알고있는 ROI 만 허용합니다. 어떤 생각을 어떻게 할 수 있습니까? –

+0

지금은 아니지만 직접 시도하십시오. 문제가 생기면 새로운 질문을하고 트위터에 나에게 알리므로 그 문제를 살펴볼 수 있습니다. 행운을 빕니다. – karlphillip

관련 문제