2011-04-10 7 views
1

저는 라이브 카메라를 표시하기 위해 OpenCV로 놀았습니다. 제가 다음에하고 싶은 것은 마우스로 그 위에 선을 그어야했습니다. 누구든지이 작업을 수행하는 방법을 알고 있습니까? 지금까지 내가 무엇을 가지고 :마우스를 사용하여 OpenCV를 사용하여 비디오에 선을 그립니다.

#include "stdafx.h" 
#include <stdio.h> 
#include "cv.h" 
#include "highgui.h" 

int main(int argc, char **argv) 
{ 
CvCapture *capture = 0; 
IplImage *frame = 0; 
int  key = 0; 

/* initialize camera */ 
capture = cvCaptureFromCAM(0); 

/* always check */ 
if (!capture) { 
    fprintf(stderr, "Cannot open initialize webcam!\n"); 
    return 1; 
} 

/* create a window for the video */ 
cvNamedWindow("Testing", CV_WINDOW_AUTOSIZE); 

while(key != 'q') { 
    /* get a frame */ 
    frame = cvQueryFrame(capture); 

    /* always check */ 
    if(!frame) break; 

    /* display current frame */ 
    cvShowImage("result", frame); 

    /* exit if user press 'q' */ 
    key = cvWaitKey(1); 

} 

/* free memory */ 
cvDestroyWindow("result"); 
cvReleaseCapture(&capture); 

return 0; 
} 

사람이 나에게 라이브 비디오에 선을 그리거나 사람이 어떤 조언 알고 있다면, 나는 그것을 대단히 감사하겠습니다 도움이 될 수 있다면! 감사!

+0

가능한 중복 (http://stackoverflow.com/questions/5490655/draw 스트림입니다 -on-webcam-using-opencv) – karlphillip

+0

http://stackoverflow.com/questions/5490655/draw-on-webcam-using-opencv/5493633#5493633에서 내 대답을 확인하십시오. 어떻게 작업하는지 보여주는 소스 코드가 있습니다. 당신이 찾고있는. – karlphillip

답변

0

동영상을 그리는 것이 무엇을 의미하는지 명확하게해야합니다.
하나의 옵션은 검정색/빈 "마스크"이미지에서 마우스 위치를 처리하고이 이미지를 표시하기 전에이 이미지를 각 비디오 프레임에 "적용"하는 것입니다.

0

마우스 이벤트를 캡처하려면 콜백을 만들어야합니다. 이 콜백은 특정 명명 된 윈도우에 연결됩니다. cvSetMouseCallback에 대한 문서는 꽤 좋습니다. 콜백 함수는 현재 위치와 버튼 클릭 정보를 알 수 있습니다. 거기에서 마우스 클릭시 점을 캡처하고 cvLine으로 점을 사용하여 프레임에 그릴 수 있습니다.

+0

그는 점수를 매기는 것을 원하지 않습니다. 그는 마우스에 무승부를 갖기를 원합니다. 그가 묻는 것 이외의 답입니다. – sotiraw

+0

cvSetMouseCallback 호출은 클릭과 이동을 처리합니다. CV_EVENT_MOUSEMOVE 이벤트를 모니터링하면 클릭하지 않고 마우스를 움직여 화면에 그릴 수 있습니다. – Ryan

0

도움이된다면, 여기에 여러 크기의 비디오에 사각형을 그리는 내 코드는 [OpenCV의 사용 웹캠 그리기]의

#include "stdafx.h" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 
#include <stdlib.h> 
#include <stdio.h> 
#include <iostream> 
#define SSTR(x) dynamic_cast< std::ostringstream & >((std::ostringstream() << std::dec << x)).str() 

using namespace std; 
using namespace cv; 

Rect box; //global structures needed for drawing 
bool drawing_box = false; 
struct mousecallbackstruct{ 
    Mat* src; 
    Mat* overlay; 
    string windowname; 
}; 

Mat srcoverlay,smallsrcoverlay; //an overlay must be created for each window you want to draw on 

void onMouse(int event, int x, int y, int flags, void* param) //it seems the only way to use this is by keeping different globals for different windows - meaning you have to set up all thise ahead of time, and keep track of it and not mix/match windows/frames!! horrible design here. 
{ 
    cout << event; 
    mousecallbackstruct mousestruct; 
    mousestruct = *((mousecallbackstruct*)param); 
    Mat* srcp = mousestruct.src; 
    Mat* overlayp = mousestruct.overlay;      // yeah, yeah, i use 7 lines where I could use 3, so sue me 
    Mat src = *srcp; 
    Mat overlay = *overlayp; 

    if(!src.data){ 
     cout << "your void * cast didn't work :(\n"; 
     return; 
    } 
    switch(event){ 
     case CV_EVENT_MOUSEMOVE: 
      if(drawing_box){ 
       box.width = x-box.x; 
       box.height = y-box.y; 
      } 
      break; 

     case CV_EVENT_LBUTTONDOWN: //start drawing 
      drawing_box = true; 
      box = cvRect(x, y, 0, 0); 
      break; 
     case CV_EVENT_LBUTTONDBLCLK: //double click to clear 
      drawing_box = false; 
      overlay.setTo(cv::Scalar::all(0)); //clear it 
      break; 
     case CV_EVENT_LBUTTONUP: //draw what we created with Lbuttondown 
      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; 
      } 
      rectangle(overlay, Point(box.x, box.y), Point(box.x+box.width,box.y+box.height),CV_RGB(100,200,100),4); //draw rectangle. You can change this to line or circle or whatever. Maybe with the Right mouse button. 
      break; 
    } 
} 


void iimshow(mousecallbackstruct* mystructp){ //this is where we add the text/drawing created in the mouse handler to the actual image (since mouse handler events do not coincide with the drawing events) 

    mousecallbackstruct mystruct = *mystructp; //custom struct made for the mouse callback - very handy for other functions too 
    Mat overlay, src; 
    Mat* srcp = mystruct.src; 
    Mat* overlayp = mystruct.overlay; 
    src = *srcp;        // yeah, yeah, i use 9 lines where I could use 3, so sue me 
    overlay = *overlayp; 
    string name = mystruct.windowname; 
    Mat added,imageROI; 

    try{ 
     //cout << "tch:" << overlay.rows << "," << src.rows << ";" << overlay.cols << "," << src.cols << ";" << src.channels() << "," << overlay.channels() <<"," << src.type() << "," << overlay.type() << "\n"; 
     if(overlay.data && overlay.rows == src.rows && overlay.cols == src.cols && overlay.channels() == src.channels()){ //basic error checking 
      add(src,overlay,added); 
     }else{ 
      //try to resize it 
      imageROI= overlay(Rect(0,0,src.cols,src.rows)); 
      add(src,imageROI,added); 
     } 

     imshow(name,added);// the actual draw moment 

    }catch(...){ //if resize didn't work then this should catch it and you can see what didn't match up 
     cout << "Error. Mismatch:" << overlay.rows << "," << src.rows << ";" << overlay.cols << "," << src.cols << ";" << src.channels() << "," << overlay.channels() <<"," << src.type() << "," << overlay.type() << "\n"; 
     imshow(name + "overlay",overlay); 
     imshow(name+"source",src); 
    } 
} 

int _tmain(int argc, _TCHAR* argv[]){ 

    VideoCapture cap(0); // open the default camera 
    if(!cap.isOpened()) { // check if we succeeded 
     cout << "NO camera found \n"; 
     return -1; 
    } 

    Mat src,smallsrc,overlay; 
    cap >> src; //grab 1 frame to build our preliminary Mats and overlays 

    srcoverlay.create(src.rows,src.cols,src.type()); //create overlays 
    smallsrcoverlay.create(src.rows,src.cols,src.type()); 
    srcoverlay.setTo(cv::Scalar::all(0)); //clear it 
    smallsrcoverlay.setTo(cv::Scalar::all(0)); //clear it 

    namedWindow("smallsrc", CV_WINDOW_AUTOSIZE); 
    namedWindow("source", CV_WINDOW_AUTOSIZE); //these must be created early for the setmousecallback, AND you have to know what Mats will be using them and not switch them around :(
    moveWindow("smallsrc",1000,100); //create a small original capture off to the side of screen 

    ////////////// for each window/mat that uses a mouse handler, you must create one of these structures for it and pass it into the mouse handler, and add a global mat for overlays (at top of code) 
    mousecallbackstruct srcmousestruct,smallsrcmousestruct; //these get passed into the mouse callback function. Hopefully they update their contents automatically for the callback? :(
    srcmousestruct.overlay = &srcoverlay; //fill our custom struct 
    srcmousestruct.src = &src; 
    srcmousestruct.windowname = "source"; 

    smallsrcmousestruct.overlay = &smallsrcoverlay; //the small window 
    smallsrcmousestruct.src = &smallsrc; 
    smallsrcmousestruct.windowname = "smallsrc"; 

    setMouseCallback(smallsrcmousestruct.windowname, onMouse, (void*)&smallsrcmousestruct); //the actual 'set mouse callback' call 
    setMouseCallback(srcmousestruct.windowname, onMouse, (void*)&srcmousestruct); 

    for(;;){ //main loop 
     /// Load an image 
     cap >> src; 

     if(!src.data) 
     { return -1; } 

     resize(src,smallsrc,Size(),.5,.5); //smaller scale window of original 

     overlay = *srcmousestruct.overlay; 
     src = *srcmousestruct.src; 

     iimshow(&srcmousestruct); //my imshow replacement. uses structs 
     iimshow(&smallsrcmousestruct); 

     if(waitKey(30) == 27) cin.get(); //esc pauses 
    } 
    cin.get(); 
    return 0; 
} 
관련 문제