OpenCV 마우스 이벤트 처리하기

프로그래밍/opencv 2013. 2. 14. 11:11

OpenCV에서 마우스를 사용하는 방법입니다. (mouse event handling)

1. 예제 코드

2. 예제 코드 다운로드

3. 실행 예




1. 예제 코드


아래 예는 opencv에서 마우스를 처리하기 위해 필요한 모든 정보를 포함하고 있습니다.


///////////////////////////////////////////////////////////////////////

// OpenCV Mouse event handling example.

// Written by darkpgmr (http://darkpgmr.tistory.com), 2013


#include "stdafx.h"

#include "windows.h"

#include <iostream>

#include "use_opencv.h"


using namespace std;

using namespace cv;


class SampleClass

{

public:

        void HandleEvent(int evt, int x, int y, int flags);

};


void SampleClass::HandleEvent(int evt, int x, int y, int flags)

{

        if( evt == CV_EVENT_LBUTTONDOWN )

        {

                cout << "CV_EVENT_LBUTTONDOWN: ";

                cout << "x=" << x << ", y=" << y << endl;

        }

        else if( evt == CV_EVENT_LBUTTONUP )

        {

                cout << "CV_EVENT_LBUTTONUP: ";

                cout << "x=" << x << ", y=" << y << endl;

        }

        else if( evt == CV_EVENT_MOUSEMOVE )

        {

//                cout << "CV_EVENT_MOUSEMOVE: ";

//                cout << "x=" << x << ", y=" << y << endl;

        }

        else if( evt == CV_EVENT_RBUTTONDOWN )

        {

                cout << "CV_EVENT_RBUTTONDOWN: ";

                cout << "x=" << x << ", y=" << y << endl;

        }

        else if( evt == CV_EVENT_RBUTTONUP )

        {

                cout << "CV_EVENT_RBUTTONUP: ";

                cout << "x=" << x << ", y=" << y << endl;

        }

        else if( evt == CV_EVENT_MBUTTONDOWN )

        {

                cout << "CV_EVENT_MBUTTONDOWN: ";

                cout << "x=" << x << ", y=" << y << endl;

        }

        else if( evt == CV_EVENT_MBUTTONUP )

        {

                cout << "CV_EVENT_MBUTTONUP: ";

                cout << "x=" << x << ", y=" << y << endl;

        }

        else if( evt == CV_EVENT_LBUTTONDBLCLK )

        {

                cout << "CV_EVENT_LBUTTONDBLCLK: ";

                cout << "x=" << x << ", y=" << y << endl;

        }

        else if( evt == CV_EVENT_RBUTTONDBLCLK )

        {

                cout << "CV_EVENT_RBUTTONDBLCLK: ";

                cout << "x=" << x << ", y=" << y << endl;

        }


        if(flags&CV_EVENT_FLAG_LBUTTON)

        {

                cout << "\tCV_EVENT_FLAG_LBUTTON" << endl;

        }

        if(flags&CV_EVENT_FLAG_RBUTTON )

        {

                cout << "\tCV_EVENT_FLAG_RBUTTON" << endl;

        }

        if(flags&CV_EVENT_FLAG_MBUTTON )

        {

                cout << "\tCV_EVENT_FLAG_MBUTTON" << endl;

        }

        if(flags&CV_EVENT_FLAG_CTRLKEY )

        {

                cout << "\tCV_EVENT_FLAG_CTRLKEY" << endl;

        }

        if(flags&CV_EVENT_FLAG_SHIFTKEY )

        {

                cout << "\tCV_EVENT_FLAG_SHIFTKEY" << endl;

        }

        if(flags&CV_EVENT_FLAG_ALTKEY )

        {

                cout << "\tCV_EVENT_FLAG_ALTKEY" << endl;

        }

}


void onMouse( int evt, int x, int y, int flags, void* param )

{

        SampleClass *p = (SampleClass *)param;

        p->HandleEvent(evt, x, y, flags);

}


void proc_video(VideoCapture *vc)

{

        SampleClass tmp;


        namedWindow("mousekeyboard");


        // event handler 등록

    setMouseCallback( "mousekeyboard", onMouse, &tmp );


        Mat frame;

        while(1)

        {

                *vc >> frame;

                if(frame.empty()) break;

                imshow("mousekeyboard", frame);

                char ch = waitKey(10);

                if( ch == 27 ) break;        // ESC Key

        }

}


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

{

        //select image source

        char data_src;

        cout << "1. camera input (640 x 480)\n"

                 << "2. camera input (320 x 240)\n"

                 << "3. video file input\n"

                 << endl

                 << "select video source[1-3]: ";

        cin >> data_src;


        VideoCapture *vc = NULL;

        if(data_src=='1')

        {

                //camera (vga)

                vc = new VideoCapture(0);

                if (!vc->isOpened())

                {

                        cout << "can't open camera" << endl;

                        return 0;

                }

                vc->set(CV_CAP_PROP_FRAME_WIDTH, 640);

                vc->set(CV_CAP_PROP_FRAME_HEIGHT, 480);

        }

        else if(data_src=='2')

        {

                //camera (qvga)

                vc = new VideoCapture(0);

                if (!vc->isOpened())

                {

                        cout << "can't open camera" << endl;

                        return 0;

                }

                vc->set(CV_CAP_PROP_FRAME_WIDTH, 320);

                vc->set(CV_CAP_PROP_FRAME_HEIGHT, 240);

        }

        else if(data_src=='3')

        {

                //video (avi)

                OPENFILENAME ofn;

                char szFile[MAX_PATH] = "";

                ZeroMemory(&ofn, sizeof(OPENFILENAME));

                ofn.lStructSize = sizeof(OPENFILENAME);

                ofn.hwndOwner = NULL;

                ofn.lpstrFile = szFile;

                ofn.nMaxFile = sizeof(szFile);

                ofn.lpstrFilter = _T("Avi Files(*.avi)\0*.avi\0All Files (*.*)\0*.*\0");

                ofn.nFilterIndex = 1;

                ofn.lpstrFileTitle = NULL;

                ofn.nMaxFileTitle = 0;

                ofn.lpstrInitialDir = NULL;

                ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

                if(::GetOpenFileName(&ofn)==false) return 0;


                vc = new VideoCapture(ofn.lpstrFile);

                if (!vc->isOpened())

                {

                        cout << "can't open video file" << endl;

                        return 0;

                }

        }

        if(vc) proc_video(vc);


        if(vc) delete vc;


        destroyAllWindows();


        return 0;

}




onMouse는 마우스 이벤트를 처리하기 위한 callback 함수로서 함수명은 어떻게 지어도 관계없습니다. onMouse의 인자중 flags는 마우스 이벤트가 발생할 당시의 다른 마우스 버튼들의 상태 및 주요 키보드(shift, ctrl, alt) 상태를 알려줍니다. 마우스 이벤트를 사용하기 위해서는 setMouseCallback 함수를 사용해서 opencv의 namedWindow에 이벤트 핸들러를 등록해 주어야 합니다.


참고사항: 키보드만으로는 이벤트가 발생하지 않습니다. 마우스 이벤트가 발생할 때 부수적으로 주요 키보드 값을 참조할 수 있을 뿐입니다. 일반적인 키보드 이벤트도 같이 처리하고 싶으면 win32(or MFC) 키보드 메시지 처리를 해 주어야 합니다.


2. 예제코드 다운로드

OpenCVMouseEvent.cpp


이 예제코드에는 마우스 이벤트 처리 뿐만 아니라 opencv에서 카메라 연결하기, avi 파일 읽어들이는 예제를 포함하고 있습니다. 제가 간단한 opencv 프로그램을 짤 때 주로 사용하는 틀로서 다른 분들에게도 유용할 것으로 생각됩니다.


3. 예제코드 실행 예





by 다크 프로그래머