[OpenCV] 키보드, 마우스 이벤트 처리

[OpenCV] 키보드, 마우스 이벤트 처리

이번 글에서는 키보드와 마우스 이벤트를 처리하는 방법을 알아보겠습니다.

키보드 이벤트 처리는 이전 글에도 많이 나왔던 waitKey 함수를 사용하면 됩니다.

/**
@return 입력된 키
@param delay 키 입력을 기다릴 시간(밀리세컨드), 입력된 값이 0보다 작거나 같으면 무한대로 기다립니다.
 */
int waitKey(int delay = 0);

 waitKey의 반환으로 입력된 키에 대한 아스키 코드 값을 반환합니다.
아래 코드는 키 ‘a’, ‘b’를 입력 했을 때 각 키에 대해 출력을 하는 프로그램 입니다.

#include <iostream>
#include "opencv2/opencv.hpp"

#ifdef _DEBUG
#pragma comment(lib, "opencv_world440d.lib")
#else
#pragma comment(lib, "opencv_world440.lib")
#endif

using namespace std;
using namespace cv;

int main()
{
	Mat img(512, 512, CV_8UC3, Scalar(255,255,255));
	if (img.empty())
	{
		cerr << "image open error" << endl;
		return -1;
	}
	imshow("img", img);
	int iKey = waitKey();
	if (iKey == 'a')
		cout << "\'a\' Key Input" << endl;
	else if (iKey == 'b') 
		cout << "\'b\' Key Input" << endl;

	system("pause");
	return 0;
}

마우스 이벤트 처리는 setMouseCallback 함수를 사용하면 됩니다.

/** 
@param 마우스 이벤트에 대한 윈도우 이름winname Name of the window.
@param onMouse 마우스 이벤트 콜백 함수
@param userdata 콜백 함수에 전달할 사용자 데이터
 */
void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);

2번째 인자를 보면 cv::MouseCallback 타입으로 되어 있습니다. 정의를 보면 아래와 같습니다.

/**
@param event 마우스 이벤트 타입
@param x 마우스 이벤트 x좌표
@param y 마우스 이벤트 y좌표
@param flags 마우스 이벤트 플래그
@param userdata 사용자 데이터
 */
typedef void (*MouseCallback)(int event, int x, int y, int flags, void* userdata);

이것과 동일한 함수를 정의하여 2번째 인자에 입력하시면 됩니다.
첫번째 인자 event와 4번째 인자 flags는 MouseEventTypes와 MouseEventFlags를 참고하시면 됩니다.

//! Mouse Events see cv::MouseCallback
enum MouseEventTypes {
	EVENT_MOUSEMOVE      = 0, //!< indicates that the mouse pointer has moved over the window.
    EVENT_LBUTTONDOWN    = 1, //!< indicates that the left mouse button is pressed.
    EVENT_RBUTTONDOWN    = 2, //!< indicates that the right mouse button is pressed.
    EVENT_MBUTTONDOWN    = 3, //!< indicates that the middle mouse button is pressed.
    EVENT_LBUTTONUP      = 4, //!< indicates that left mouse button is released.
    EVENT_RBUTTONUP      = 5, //!< indicates that right mouse button is released.
    EVENT_MBUTTONUP      = 6, //!< indicates that middle mouse button is released.
    EVENT_LBUTTONDBLCLK  = 7, //!< indicates that left mouse button is double clicked.
    EVENT_RBUTTONDBLCLK  = 8, //!< indicates that right mouse button is double clicked.
    EVENT_MBUTTONDBLCLK  = 9, //!< indicates that middle mouse button is double clicked.
    EVENT_MOUSEWHEEL     = 10,//!< positive and negative values mean forward and backward scrolling, respectively.
    EVENT_MOUSEHWHEEL    = 11 //!< positive and negative values mean right and left scrolling, respectively.
};

//! Mouse Event Flags see cv::MouseCallback
enum MouseEventFlags {
	EVENT_FLAG_LBUTTON   = 1, //!< indicates that the left mouse button is down.
    EVENT_FLAG_RBUTTON   = 2, //!< indicates that the right mouse button is down.
    EVENT_FLAG_MBUTTON   = 4, //!< indicates that the middle mouse button is down.
    EVENT_FLAG_CTRLKEY   = 8, //!< indicates that CTRL Key is pressed.
    EVENT_FLAG_SHIFTKEY  = 16,//!< indicates that SHIFT Key is pressed.
    EVENT_FLAG_ALTKEY    = 32 //!< indicates that ALT Key is pressed.
};

샘플 코드는 아래와 같습니다.

#include <iostream>
#include "opencv2/opencv.hpp"

#ifdef _DEBUG
#pragma comment(lib, "opencv_world440d.lib")
#else
#pragma comment(lib, "opencv_world440.lib")
#endif

using namespace std;
using namespace cv;

void on_MouseEvent(int event, int x, int y, int flags, void* userdata)
{
	String sEvent = "";
	if (event == EVENT_MOUSEMOVE)
		sEvent = "EVENT_MOUSEMOVE";
	else if (event == EVENT_LBUTTONDOWN)
		sEvent = "EVENT_LBUTTONDOWN";
	else if (event == EVENT_RBUTTONDOWN)
		sEvent = "EVENT_RBUTTONDOWN";
	else if (event == EVENT_MBUTTONDOWN)
		sEvent = "EVENT_MBUTTONDOWN";
	else if (event == EVENT_LBUTTONUP)
		sEvent = "EVENT_LBUTTONUP";
	else if (event == EVENT_RBUTTONUP)
		sEvent = "EVENT_RBUTTONUP";
	else if (event == EVENT_MBUTTONUP)
		sEvent = "EVENT_MBUTTONUP";
	else if (event == EVENT_LBUTTONDBLCLK)
		sEvent = "EVENT_LBUTTONDBLCLK";
	else if (event == EVENT_RBUTTONDBLCLK)
		sEvent = "EVENT_RBUTTONDBLCLK";
	else if (event == EVENT_MBUTTONDBLCLK)
		sEvent = "EVENT_MBUTTONDBLCLK";
	else if (event == EVENT_MOUSEWHEEL)
		sEvent = "EVENT_MOUSEWHEEL";
	else if (event == EVENT_MOUSEHWHEEL)
		sEvent = "EVENT_MOUSEHWHEEL";

	String sPos = "";
	sPos = format("x: %d, y: %d", x, y);

	cout << sEvent << ", " << sPos << endl;
}

int main()
{
	Mat img(512, 512, CV_8UC3, Scalar(255,255,255));
	if (img.empty())
	{
		cerr << "image open error" << endl;
		return -1;
	}
	imshow("img", img);
	setMouseCallback("img", on_MouseEvent);

	int iKey = waitKey();
	if (iKey == 'a')
		cout << "\'a\' Key Input" << endl;
	else if (iKey == 'b')
		cout << "\'b\' Key Input" << endl;

	system("pause");
	return 0;
}

실행 결과는 아래와 같습니다.