키보드 이벤트 처리

키보드 입력 대기
int waitKey(int delay =0);
  • delay : 밀리초 단위 대기시간 delay가 0 이하일 경우 무한히 기다림
  • 반환값 : 눌린 키 값이 아스키코드로 반환하고 만약 키가 눌리지 않으면 -1
  • 화살표키, 함수키 등의 특수 키에 대한 이벤트 처리를 수행하기 위해서는 waitKeyEx()함수를 사용해야 함

마우스 이벤트 처리

  • 마우스 이벤트 처리를 위한 콜백 함수 등록
void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata =0);
  • winname : 창 이름
  • userdata : 콜백 함수에 전달할 사용자 지정 데이터(optional)
  • onMouse : 마우스 콜백 함수 이름 / 아래와 같은 형식의 함수를 정의하고 해당 함수 이름을 지정
typedef void (*MouseCallback)(int event, int x, int y, int flags, void* userdata);
  • event : 마우스 이벤트 종류. MouseEventsTypes 상수
  • x,y : 마우스 이벤트 발생 좌표
  • flags : 마우스 이벤트 플래그. MouseEventsflags 상수
  • userdata : setMouseCallback() 함수에서 지정한 사용자 지정 데이터

image

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

using namespace std;
using namespace cv;

Mat src;
Point ptOld;
void on_mouse(int event, int x, int y, int flags, void*);

int main(void)
{
	src = imread("lenna.bmp");

	if (src.empty()) {
		cerr << "Image load failed!" << endl;
		return -1;
	}
	
	namedWindow("src");
	setMouseCallback("src", on_mouse); // 마우스 이벤트 처리를 위한 콜백 함수

	imshow("src", src);
	waitKey();
}

void on_mouse(int event, int x, int y, int flags, void*)
{
	switch (event) { // 특정 이벤트에서만 특정 활동을 할 수 있게 switch문이나 if문을 사용
	case EVENT_LBUTTONDOWN: // 왼쪽 마우스를 눌렀을 때 해당 마우스의 좌표를 출력
		ptOld = Point(x, y); // 마우스 왼쪽 버튼이 눌렸을때 ptOld 초기화
		cout << "EVENT_LBUTTONDOWN: " << x << ", " << y << endl;
		break;
	case EVENT_LBUTTONUP: // 왼쪽 마우스를 떼었을 때 해당 마우스의 좌표를 출력
		cout << "EVENT_LBUTTONUP: " << x << ", " << y << endl;
		break;
	case EVENT_MOUSEMOVE:
		if (flags & EVENT_FLAG_LBUTTON) { 
		// flags == EVENT_FLAG_LBUTTON 보다는 flags & EVENT_FLAG_LBUTTON 로 bit가 설정되어있는지 확인하는 것이 적절한 코드 작성 방법
		// flags == EVENT_FLAG_LBUTTON 를 설정했을 때는 ctrl(MouseEventFlags 에서 8)을 누른상태에서 왼쪽 버튼을 누르면 코드가 실행되지 않음
        // 1 == 9(8+1) 가 성립되지 않으므로     
        
			//cout << "EVENT_MOUSEMOVE: " << x << ", " << y << endl;
			//circle(src, Point(x, y), 2, Scalar(0, 255, 255), -1, LINE_AA);
			
			line(src, ptOld, Point(x, y), Scalar(0, 255, 255), 3, LINE_AA);
			// 마우스가 움직이면 circle 함수보다는 line 함수를 이용해서 맨 처음 포인트부터 현재 포인트까지 선을 그어야 중간에 끊임이 없음
			
			ptOld = Point(x, y); // ptOld 현재 포인트로 다시 업데이트
			imshow("src", src);
		}
		break;
	default:
		break;
	}
}

트랙바

  • 영상 출력 창에 부착되어, 프로그램 동작 중에 사용자가 지정된 범위 안의 값을 선택할 수 있는 GUI
  • 슬라이더 컨트롤 형태
트랙바 생성 함수
int createTrackbar(const String& trackbarname, const String& winname, int* value, int count, TrackbarCallback onChange = 0, void * userdata = 0)
  • trackbarname : 트랙바 이름
  • winname : 트랙바를 생성할 창 이름
  • value : 트랙바 위치 값을 받을 정수형 변수의 주소
  • count : 트랙바 최대 위치 (최소 위치는 항상 0)

image

  • onChange : 트랙바 위치가 변경될 때마다 호출되게 만들 콜백 함수 이름(함수의 포인터), 만약 Null을 지정하면 콜백 함수는 호출되지 않고 value로 지정한 변수 값만 갱신됨
typedef void (*TrackbarCallback)(int pos, void * userdata);
  • userdata : 트랙바 콜백 함수에 전달할 사용자 데이터의 포인터 (Optional)
  • 반환값 : 정상 동작하면 1, 실패하면 0
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

void on_level_change(int pos, void* userdata);

int main(void)
{
	Mat img = Mat::zeros(400, 400, CV_8UC1);
	// main 함수에 있는 어떤 영상 데이터를 mouse 콜백 함수나 trackbar 콜백 함수에 전달하려면 img를 전역 변수형식으로 선언하거나 userdata 형태 타입인 void 포인터 형식으로 주소값을 전달해야 함

	namedWindow("image");
	createTrackbar("level", "image", 0, 16, on_level_change, (void*)&img);

	imshow("image", img);
	waitKey();
}

void on_level_change(int pos, void* userdata)
{
	Mat img = *(Mat*)userdata;

	img.setTo(pos * 16);
	imshow("image", img);
}