[OpenCV] 이벤트 처리 - Week6_2

Ogu·2023년 10월 7일
0
post-thumbnail

이벤트 처리


키보드 이벤트 처리

waitKey() : 키 입력을 확인하기 위해 사용하는 함수

💡 int waitKey(int delay = 0);

  • delay : 키 입력을 기다릴 시간(밀리초 단위), delay≤0 이면 무한히 기다림
  • 반환값 : 눌러진 키 값, 지정한 시간 동안 키가 눌리지 않았으면 -1 반환
  • delay에 해당하는 밀리초 시간동안 키 입력을 기다리다가 키 입력이 있으면 해당 키의 아스키코드 값 반환
  • 지정한 시간 동안 키 입력이 없으면 -1 반환
  • 함수 인자를 지정하지 않거나 0 또는 음수 설정 → 키 입력이 있을 때까지 무한히 기다리고 키보드를 누르면 눌린 키의 아스키 코드를 반환하면서 함수 종료
waitKey()를 사용해 특정 키가 입력될 때마다 영상을 반전시켜 보여주는 예
    #include "opencv2/opencv.hpp"
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    int main(void)
    {
        Mat img = imread("lenna.bmp");
    
        if (img.empty()) {
            cerr << "Image load failed!" << endl;
            return -1;
        }
    
        namedWindow("img");
        imshow("img", img);
    
        while (true) {
            int keycode = waitKey();
    
            if (keycode == 'i' || keycode == 'I') {
                img = ~img;
                imshow("img", img);
            }
            else if (keycode == 27 || keycode == 'q' || keycode == 'Q') {
                break;
            }
        }
    
        return 0;
    }

waitKey()를 사용해 특정 키가 입력될 때마다 영상을 반전시켜 보여주는 예

  #include "opencv2/opencv.hpp"
  #include <iostream>
  
  using namespace cv;
  using namespace std;
  
  int main(void)
  {
      Mat img = imread("lenna.bmp");
  
      if (img.empty()) {
          cerr << "Image load failed!" << endl;
          return -1;
      }
  
      namedWindow("img");
      imshow("img", img);
  
      while (true) {
          int keycode = waitKey();
  
          if (keycode == 'i' || keycode == 'I') {
              img = ~img;
              imshow("img", img);
          }
          else if (keycode == 27 || keycode == 'q' || keycode == 'Q') {
              break;
          }
      }
  
      return 0;
  }

윈도우에서 특수 키 처리
f1, f2, …, f12, ←, → 등으 ㅣ특수 키 입력은 waitKey()로 불가능
waitKeyEx() 함수 사용
int waktKeyEx(int delay = 0);



마우스 이벤트 처리

setMouseCallback() : 키 입력을 확인하기 위해 사용하는 함수

OpenCV에 의해 만들어진 창에서 마우스 클릭에 반응하거나 마우스를 드래그하여 영상에 그림을 그리는 등의 동작을 수행할 수 있음

→ 우선 마우스 콜백 함수를 등록하고, 마우스 콜백 함수에 마우스 이벤트를 처리하는 코드 추가

💡 setMouseCallback(const String& winname, MouseCallback onMouse, void& userdata = 0);

• winname마우스 이벤트 처리를 할 창의 이름
• onMouse마우스 이벤트 처리를 위한 콜백 함수 이름
• userdata콜백 함수에 전달할 사용자 데이터의 포인터

setMouseCallback() 함수는 winname 창에서 마우스 이벤트가 발생하면, onMouse로 등록된 콜백 함수가 자동으로 호출됨. userdata에는 사용자가 마우스 콜백 함수에 전달하고 싶은 데이터를 void* 형식으로 전달

MouseCallback() : 마우스 이벤트를 처리하는 코드 추가

💡 typedef void (*MouseCallback)(int event, int x, int y, int flags, void* userdata);

• eventMouseEventTypes로 정의된 열거형 상수중 하나 전달
• x마우스 이벤트가 발생한 위치의 x좌표
• y마우스 이벤트가 발생한 위치의 y좌표
• flags마우스 이벤트가 발생할 때의 마우스 또는 키보드의 상태 정보
MouseEventFlags 열거형 상수의 논리합 조합 전달
• userdatasetMouseCallback() 함수에서 설정한 사용자 데이터의 포인터
만약 설정값이 없었다면, 항상 0(NULL)이 전달됨

▼ MouseEventTypes 열거형 상수

MouseEventTypes 열거형 상수설명
EVENT_MOUSEMOVE0마우스가 창 위에서 움직이는 경우
EVENT_LBUTTONDOWN1마우스 왼쪽 버튼을 누른 경우
EVENT_RBUTTONDOWN2마우스 오른쪽 버튼을 누른 경우
EVENT_MBUTTONDOWN3마우스 가운데 버튼을 누른 경우
EVENT_LBUTTONUP4마우스 왼쪽 버튼을 떼는 경우
EVENT_RBUTTONUP5마우스 오른쪽 버튼을 떼는 경우
EVENT_MBUTTONUP6마우스 가운데 버튼을 떼는 경우
EVENT_LBUTTONDBLCLK7마우스 왼쪽 버튼을 더블클릭하는 경우
EVENT_RBUTTONDBLCLK8마우스 오른쪽 버튼을 더블클릭하는 경우
EVENT_MBUTTONDBLCLK9마우스 가운데 버튼을 더블클릭하는 경우
EVENT_MOUSEWHEEL10마우스 휠을 앞뒤로 돌리는 경우
EVENT_MOUSEHWHEEL11마우스 휠을 좌우로 움직이는 경우

▼ MouseEventFlags 열거형 상수

MouseEventFlags 열거형 상수설명
EVENT_FLAG_LBUTTON1마우스 왼쪽 버튼이 눌려 있음
EVENT_FLAG_RBUTTON2마우스 오른쪽 버튼이 눌려 있음
EVENT_FLAG_MBUTTON4마우스 가운데 버튼이 눌려 있음
EVENT_FLAG_CTRLKEY8Ctrl 키가 눌려 있음
EVENT_FLAG_SHIFTKEY16Shift 키가 눌려 있음
EVENT_FLAG_ALTKEY32Alt 키가 눌려 있음

마우스 이벤트 처리 예제

    #include "opencv2/opencv.hpp"
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    Mat img;
    Point ptOld;
    
    void on_mouse(int event, int x, int y, int flags, void*);
    
    int main(void)
    {
        img = imread("lenna.bmp");
    
        if (img.empty()) {
            cerr << "Image load failed!" << endl;
            return -1;
        }
    
        namedWindow("img");
        setMouseCallback("img", on_mouse);
    
        imshow("img", img);
        waitKey(0);
    
        return 0;
    }
    
    void on_mouse(int event, int x, int y, int flags, void*)
    {
        switch (event) {
        case EVENT_LBUTTONDOWN:
            ptOld = Point(x, y);
            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) {
                line(img, ptOld, Point(x, y), Scalar(0, 255, 255), 2);
                imshow("img", img);
                ptOld = Point(x, y);
            }
            break;
        default:
            break;
        }
    }
  • on_mouse() 함수에서 이전 마우스 이벤트 발생 위치를 저장하기 위한 용도로 ptOld 변수를 전역 변수 형태로 선언
  • ptOld : 마우스 왼쪽 버튼이 눌린 좌표 저장, ptOld는 마우스가 움직인 궤적을 그릴 때 사용
  • 마우스가 움직이는 경우, 마우스 왼쪽 버튼이 눌려 있는 상태라면 img 영상 위에 노란색 직선을 이어 그림
  • if (flags & EVENT_FLAG_LBUTTON) → flags 인자에 EVENT_FLAG_LBUTTON 비트가 설정되어 있 는지 확인하기 위해 & 연산자 사용
  • ptOld 좌표부터 현재 마우스 이벤트 발생 좌표까지 그림, 직선을 그리고 난 후에는 현재 마우스 이벤트 발생 좌표를 ptOld에 저장

트랙바 사용

OpenCV에서 지공하는 범용적인 GUI

트랙바는 슬라이더 컨트롤(slider control)이라고도 부르며, 영상 출력 창에 부착되어 프로그램 동작 중에 사용자가 지정된 범위 안의 값을 선택

  • 사용자가 지정한 영상 출력 창의 상단에 부착
  • 창 하나에 여러 개의 트랙바 생성 가능
  • 트랙바에 고유한 이름을 지정해야 함, 이름은 트랙바 왼쪽에 표시
  • 트랙바 위치는 사용자가 마우스를 이용하여 이동, 현재 위치는 트랙바 이름 옆에 함께 표시
  • 가리킬 수 있는 최대 위치 : 트랙바 생성 시 지정, 최소 위치 : 0 고정

createTrackbar() : 트랙바 생성 함수

💡

int createTrackbar(const String& trackbarname, const String& winname,
                   int* value, int count, TrackbarCallback onChange = 0,
                   void* userdata = 0);

콜백 함수는 트랙 바의 바를 조절할 때 위치한 값을 전달합니다.

• trackbarname트랙바 이름
• winname트랙바를 생성할 창 이름
• value트랙바 최소값(초기값)
• count트랙바 최대 위치
• onChange트랙바 위치가 변경될 때마다 호출되게 만들 콜백 함수 이름(함수의 포인터) 만약 NULL을 지정하면 콜백 함수는 호출되지 않고 value로 지정한 변수 값만 갱신
• userdata트랙바 콜백 함수에 전달할 사용자 데이터의 포인터
• 반환값정상 동작하면 1, 실패하면 0 반환

정수형 변수를 하나 만들고, 그 변수의 주소를 value 인자로 설정하면, 트랙바 위치가 해당 변수에 자동으로 저장됨

onchange의 TrackbarCallback 함수

💡 typedef void (*TrackbarCallback)(int pos, void* userdata);

  • pos : 현재 트랙바의 위치 정보 전달
  • userdata : createTrackbar() 함수에서 지정한 사용자 데이터 포인터 값

트랙바를 이용한 그레이스케일 레벨 표현 (0~16값 선택)

    #include "opencv2/opencv.hpp"
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    void on_level_change(int pos, void* userdata);
    
    int main(void)
    {
        Mat img = Mat::zeros(400, 400, CV_8UC1);
    
        namedWindow("image");
        createTrackbar("level", "image", 0, 16, on_level_change, (void*)&img);
    
        imshow("image", img);
        waitKey(0);
    
        return 0;
    }
    
    void on_level_change(int pos, void* userdata)
    {
        Mat img = *(Mat*)userdata;
    
        img.setTo(pos * 16);
        imshow("image", img);
    }

트랙바 콜백 함수로 등록된 on_level_change() 함수는 사용자가 선택한 트랙바 위치에 16을 곱하여 영상의 전체 픽셀 값으로 설정한다. 즉, 이 예제 프로그램은 그레이스케일 레벨을 16단계로 보여 준다.

getTrackbarPos() : 트랙바의 현재 위치 반환

💡 int getTrackbarPos(const String& trackbarname, const String& winname);

• trackbarname트랙바 이름
• winname트랙바가 부착되어 있는 창 이름
• 반환값지정한 트랙바의 현재 위치

setTrackbarPos() : 프로그램 동작 중 트랙바 위치를 강제로 특정 위치로 옮김

💡 void setTrackbarPos(const String& trackbarname, const String& winname, int pos);

• trackbarname트랙바 이름
• winname트랙바가 부착되어 있는 창 이름
• pos트랙바를 이동할 위치
profile
私はゲームと日本が好きなBackend Developer志望生のOguです🐤🐤

0개의 댓글