관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

OpenCV로 시작하는 컴퓨터 비전 7 - 웹 캠에서 비디오 읽기와 그래픽 기능으로 사용자 인터페이스 만들기 본문

인공지능/컴퓨터 비전

OpenCV로 시작하는 컴퓨터 비전 7 - 웹 캠에서 비디오 읽기와 그래픽 기능으로 사용자 인터페이스 만들기

huenuri 2024. 11. 8. 03:45

오늘은 평소보다 1시간 일찍 일어나 공부를 시작해 본다. 어젯밤에 11시에 취침을 했는데 새벽에 2시도 되지 않아서 눈이 떠졌다. 일어나자마자 어제 다 하지 못했던 컴퓨터 비전 공부를 하고 싶었다. 매일 새벽에 일어나자마자 개발 생각부터 드는 걸 보니 난 정말 개발자가 천직임을 느낀다.

그럼 오늘의 공부를 시작해보겠다.


 

 

 

 

웹 캠에서 비디오 읽기 이어서

 

비디오에서 영상 수집하기

지금 시도하고 있는 예제는 바로 이것이다.

 

 

 

 

출력된 화면은 바로 이것이다.

 

 

 

 

코드를 해석하면 다음과 같다. 10행은 수집한 영상을 저장할 리스트 frames를 생성한다. 21~23행은 사용자가 C를 누를 때마다 획득한 프레임을 frames 리스트에 추가한다.

 

 

27~29행은 수집한 영상을 이어 붙여 윈도우에 표시한다. 30행은 frames 리스트에 있는 0번 요소를 imgs 배열에 저장한다. 31~32행은 1번, 2번, 6번 요소를 덧붙인다. min(3, len(frames))를 이용해 최대 3개까지만 이어 붙였다. 3개로 한정한 이유는 영상이 너무 커서 화면 밖으로 나가는 것을 방지하기 위해서다.

 

이제 스파이더 콘솔 창에서 다음 명령을 내려 frames 리스트와 imgs 배열을 조사해 보자.

 

 

책에는 len이 7인데 난 3번만 C를 눌러서 화면을 캡처했기에 그런 것 같다. 이 명령은 frames 리스트에 있는 요소의 개수이다. 두 번째 명령은 frames 리스트의 0번 요소, 즉 첫 번째 영상을 저장한 배열의 모양을 shape 함수로 알아낸다. 처음에는 frame이라고 써서 2차원 배열이 출력되었다. 마지막에 올바르게 쓴 코드를 입력했는데 480 x 640 x 3인 영상임을 알 수 있다.

세 번째 명령어를 통해 세 장의 영상을 이어 붙여 만든 imgs가 numy.ndarray 형이라는 사실을 알 수 있다. 네 번째 명령어는 imgs가 수평 방향으로 긴 영상이라는 사실을 알려준다.

 

 

 

위의 그림은 조사한 내용을 그림으로 보여준다. 컴퓨터 비전 프로그래밍을 잘하는 요령 중의 하나는 프로그램에 등장하는 수많은 객체의 데이터 형과 모양을 정확히 이해하는 것이다. 이때 type과 shape은 아주 중요하다. type과 shape이 주는 정보만으로 잘 이해되지 않으면 연필과 종이를 들고 이 그림과 같이 그려보면 도움이 된다.


 

 

 

 

그래픽 기능과 사용자 인터페이스 만들기

종종 영상에 도형을 그리거나 글씨를 써넣어야 하는 경우가 있다. 예를 들어 영상에서 얼굴을 검출하면 얼굴 영역을 직사학경으로 표시해야 하고, 얼굴 표정을 인식한다면 어떤 표정인지 써야 한다. 아직 자동으로 검출이나 인식을 할 수 없으니 사용자가 좌표를 지정하는 방식으로 프로그래밍한다.

 

 

영상에 도형을 그리고 글씨 쓰기

OpenCV는 직선을 그리는 line, 직사각형을 그리는 rectangle, 다각형을 그리는 polylines, 원을 그리는 circle, 타원을 그리는 ellipse, 문자열을 쓰는 putText 함수를 제공한다. 이 예제의 9행은 rectangle 함수로 얼굴에 직사각형을 그린다.

첫 번째 인수 img는 직사각형을 그릴 영상이고, 두 번째 인수 (830, 30)은 직사각형의 왼쪽 위 구석점의 좌표다. 이때 x와 y 좌표 순으로 쓴다. 세 번째 인수 (1000, 200)은 직사각형의 오른쪽 아래 구석점의 좌표이다.

네 번째 인수 (0,0,255)는 색을 지정하는데 (B, G, R)에서 R만 255이므로 빨간색이다. 다섯 번째 인수 2는 두께를 지정한다. 

 

 

 

 

 

 

함수 선언을 정확히 피악하고 제대로 활용하는 일이 매우 중요하다. 앞으로 함수를 사용할 때 OpenCV 공식 사이트 또는 구글 검색 등을 통해 함수 선언을 정확하게 파악하고 활용하는 습관을 들이자. 

 

OpenCV 공식 사이트

 

OpenCV: OpenCV Tutorials

OpenCV  4.10.0 Open Source Computer Vision

docs.opencv.org

 


 

 

 

 

마우스를 통한 상호 작용

앞의 예제는 고정된 위치에 직사각형을 그린다. 이제 마우스를 이용해 위치를 지정할 수 있도록 확장해 보자. 다음 예제는 마우스를 클릭한 곳에 직사각형을 그린다. 왼쪽 버튼을 클릭하면 크기가 200 x 200인 빨간색 직사각형을 그리고, 오른쪽 버튼을 클릭하면 크기가 100 x 100인 파란색 직사각형을 그린다.

 

마우스로 클릭한 곳에 직사각형 그리기

 

마우스를 다루려면 콜백 함수라는 새로운 프로그래밍 방식이 필요하다. 보통 프로그램은 정해진 순서에 따라 명령어를 실행하는데, 마우스를 다루는 프로그램에서는 클릭이나 커서 이동 같은 이벤트가 언제 발생할지 알 수 없기 때문에 콜백 함수가 필요하다. 17행은 'Drawing'이라는 이름의 윈도우를 생성하고, 18행은 윈도우에 img 연상을 디스플레이한다. 20행은 Drawing이라는 이름의 윈도우에서 마우스 이벤트가 발생하면 draw라는 콜백 함수를 호출하라고 등록한다.

마우스 이벤트는 버튼 클릭하기, 버튼에서 손 놓기, 커서 이동, 휠 돌리기를 하면 발생한다.

 

20행까지만 코딩하면 콜백 함수를 등록하고 프로그램이 끝나기 때문에 아무 일도 일어나지 않는다. 22~25행은 무한 루프를 돌아 프로그램 실행을 지속한다. 실행 도중에 마우스 이벤트가 발생하면 콜백 함수가 호출되어 img 영상에 직사각형을 그린다.

 

 

이렇게 빨간색과 파란색 직사각형이 만들어졌다. 난 왼손 마우스를 사용하니 오른쪽을 클릭했을 때 빨간색 직사각형이 만들어졌다.


 

 

 

 

마우스 드래그로 도형 크기 조절하기 

앞의 프로그램은 직사각형 위치는 선택할 수 있지만 크기는 정해져 있다. 직사각형 크기를 마음대로 조절하려면 마우스 클릭과 드래그를 함께 사용하면 된다. 다음 프로그램은 사용자가 직사각형 크기를 조절할 수 있게 확장한다.

드래그는 마우스를 클릭한 채 커서를 이동해 원하는 곳에 버튼을 놓는 행위다. 따라서 버튼을 클릭했을 때와 놓았을 때 좌표를 읽어 직사각형을 그리면 된다. 이 논리에 따라 콜백 함수 draw만 수정하면 된다.

 

10행은 버튼을 클릭한 순간의 좌표를 저장할 ix와 iy를 전역 변수로 선언한다. 10행이 없으면 ix와 iy는 함수가 시작할 때 생겼다가 끝날 때 소멸하는 지역 변수로 작용해 드래그하는 동안 발생하는 여러 번의 함수 호출에서 생성과 소멸을 거듭하므로 좌표값을 유지하지 못한다.

12~13행은 클릭하는 순간, 즉 evnt가 EVENT_LBUTTONDOWN이면 좌표 x와 y를 전역 변수 ix와 iy에 저장한다. 14~15행은 버튼을 놓는 순간 클릭했을 때 저장해 둔 좌표 (ix, iy)와 놓았을 때 좌표 (x, y)를 이용해 직사각형을 그린다.

 

마우스 드래그로 직사각형 그리기

 

 

 

 

마우스를 드래그하면 그 모양대로 그려진다. 이번에는 왼쪽과 마우스 버튼의 구분은 없다.

 


 

 

 

학습을 마치고

이제 컴퓨터 비전을 어느 정도 잘 다룰 수 있게 되었다. 코드도 많이 이해하고 정말 재미있다. 2장은 환경 설정하는데 오류가 많아서 진도를 천천히 나갔는데 이제 딱 하나의 소단원만 남아있다. 이것만 마치고 연습문제를 풀고 나면 나머지 새벽 시간에는 수업 영상을 들으면서 비주얼 코드로도 학습을 진행해 볼 것이다.

 

어제 스파이더 처음 배울 때는 너무 어려워서 과연 이걸로 내가 혼자서 책 보고 공부를 할 수 있을까 걱정이었는데 난 충분히 잘 해낼 수 있었다.