1. 키보드 이벤트 처리
i 또는 I 키를 누르면 영상의 색상이 반전되는 예제
void keyboard() {
Mat img = imread("lenna.bmp");
if (img.empty()) {
cerr << "Image load failed!" << endl;
return;
}
namedWindow("img");
imshow("img", img);
while (true) {
int keycode = waitKey();
// 매개변수인 밀리초 단위로 대기하고 delay<=0 이면 무한히 기다림. 반환값은 눌려진 키 값
if (keycode == 'i' || keycode == 'I')
{
img = ~img;
imshow("img", img);
}
else if( keycode == 27 || keycode=='q'|| keycode == 'Q')
{
break;
}
}
}
2. 마우스 이벤트 처리 (+키보드 이벤트 처리)
구현한 기능
1) 마우스 왼쪽 클릭한 채로 드래그 하면 노란 직선 그리기
2) c 또는 C키 입력시 영상에서 지금까지 그린 도형 없애기
3) ctrl키를 누른채로 마우스 왼쪽을 클릭해 드래그 하면 파란색 사각형 그리기
4) f 버튼을 누르면 3)을 내부 안채운 버전 또는 채운 버전으로 토글 가능
// OpenCV는 영상 출력 창에서 발생하는 마우스 이벤트를 사용자에게 전달하는 기능을 제공하는데 이를 위해선
// 먼저 마우스 콜백 함수를 등록하고 마우스 콜백 함수에 마우스 이벤트를 처리하는 코드를 추가해야 함
// 콜백 함수 내에서 사용할 변수는 전역으로 선언
Mat img;
Point ptOld;
Point ptNew;
int toggleFill=1;
void on_mouse(int event, int x, int y, int flags, void*);
void mouse() {
img = imread("lenna.bmp");
if (img.empty()) {
cerr << "Image load failed!" << endl;
return;
}
namedWindow("img");
// 마우스 콜백 함수를 등록하는 함수
//void setMouseCallback(const String & winname, MouseCallback onMouse, void* userdata = 0);
//winname : 이벤트 처리를 할 창의 이름, onMouse : 마우스콜백 함수 이름, userdata : 콜백함수에 전달한 데이터의 포인터로 전달할 값이 없으면 비움
setMouseCallback("img", on_mouse);
imshow("img", img);
while (true) {
int keycode = waitKey();
if (keycode == 'c' || keycode == 'C')
{
img = imread("lenna.bmp");
imshow("img", img);
}
// f키가 눌리는 경우 toggleFill 변수를 -1 또는 1로 토글시킴
else if (keycode == 'f' || keycode == 'F')
{
toggleFill = toggleFill > -1 ? -1 : 1;
}
else if (keycode == 27 || keycode == 'q' || keycode == 'Q')
{
break;
}
}
}
// 마우스 콜백 함수는 마우스 이벤트가 발생할 때 호출되는 함수로 형식은
// typedef void (*MouseCallback)(int event, int x, int y, int flags, void* userdata);
// 매개변수 event 는 MouseEventTypes로 정의된 enum 중 하나가 전달됨
// 매개변수 x, y는 마우스 이벤트가 발생한 위치의 x, y 좌표
// 매개변수 flags 는 마우스 이벤트가 발생할 때의 마우스 또는 키보드의 상태 정보를 담고 있는데,
// MouseEventFlags enum의 논리합 조합이 전달됨. 두 가지 이상 상태가 동시에 일어났으면 OR 비트연산(|)의 값이 전달되는 것.
// void* 타입의 마지막 매개변수는 콜백함수 등록시 설정한 사용자 데이터의 포인터로, 설정하지 않았다면 항상 0(NULL)이 전달됨
void on_mouse(int event, int x, int y, int flags, void*) {
// 디버깅을 위해 매개변수로 들어온 flags 출력
cout << "flags: " << flags << endl;
switch (event) {
// 좌클릭이 되는 순간 ptOld에 좌표 저장
case EVENT_LBUTTONDOWN:
ptOld = Point(x, y);
//cout << "EVENT_LBUTTONDOWN: " << x << ", " << y << endl;
break;
// 좌측버튼에서 손이 떼지는 순간 ptOld부터 ptNew까지 사각형을 그리고
// ptNew는 다시 0,0으로 바꿈
// rectangle() 함수의 5번째 인자인 toggleFill은 키보드 이벤트에 의해 1 또는 -1로 토글됨
case EVENT_LBUTTONUP:
//cout << "EVENT_LBUTTONDOWN: " << x << ", " << y << endl;
if (ptNew.x != 0 && ptNew.y != 0) {
rectangle(img, ptOld, ptNew, Scalar(255, 0, 0), toggleFill);
imshow("img", img);
ptNew = Point(0, 0);
}
break;
case EVENT_MOUSEMOVE:
// Ctrl이 눌린상태 + 좌측버튼이 눌린상태로 마우스가 움직이는 경우 ptNEW변수에 좌표 갱신
if (flags == (EVENT_FLAG_LBUTTON | EVENT_FLAG_CTRLKEY)) {
ptNew = Point(x, y);
}
// 좌측버튼이 눌린채로 마우스를 움직이는 경우 현재 Point까지 직선을 그림
// 단 Ctrl이 눌린 상태라면 이 분기로 들어오지 않음
else if (flags & EVENT_FLAG_LBUTTON) {
line(img, ptOld, Point(x, y), Scalar(0, 255, 255), 2);
imshow("img", img);
ptOld = Point(x, y);
}
break;
default:
break;
}
}
MouseEventTypes
MouseEventFlags
디버깅을 위해 출력한 flags를 보면 왼쪽 버튼이 눌려있을 땐 1, Ctrl 키가 눌려있을 땐 8, 왼쪽 버튼이 눌려있고 동시에 Crtl 키가 눌려있을 땐 논리합 조합(OR 비트연산 값)인 9가 들어오는 것을 확인할 수 있다.
'OpenCV' 카테고리의 다른 글
OpenCV ] 데이터 파일 입출력 (0) | 2022.08.18 |
---|---|
OpenCV ] 트랙바 (슬라이더 컨트롤) 사용하기 (0) | 2022.08.18 |
OpenCV , C++ ] 도형 그리기 + 문자열 출력 (0) | 2022.08.16 |
OpenCV , C++ ] 카메라와 동영상 파일 다루기 (0) | 2022.08.16 |
OpenCV ] Image Watch 사용하기 (0) | 2022.08.09 |