관리 메뉴

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

영상 처리 5 - 기하 연산과 OpenCV의 시간 효율 본문

인공지능/컴퓨터 비전

영상 처리 5 - 기하 연산과 OpenCV의 시간 효율

huenuri 2024. 11. 9. 10:14

지금까지는 어떤 화소가 자기 자신 또는 이웃을 보고 값을 정하는 연산을 다루었는데 영상의 크기를 조절하거나 영상을 회전하려면 멀리 있는 화소에서 값을 가져올 수 있어야 한다. 기하 연산은 이런 경우를 다룬다.


 

 

기하 연산

 

1. 동차 좌표와 동차 행렬

동차 좌표는 2차원 점의 위치 (x, y)에 1을 추가해 식 (3.10)처럼 3차원 벡터로 표현한다. 동차 좌표에서는 3개 요소에 같은 값을 곱하면 같은 좌표를 나타낸다.

 

 

 

 

 

 

표 3-1의 변환 행렬은 아무리 여러 개를 곱해소 직선은 직선으로 유지되고 평행인 선은 평행을 유지한다. 이런 성질은 동차 행렬의 3행이 (0 0 1)이기 때문이다. 이런 성질을 가진 변환을 그렇지 않은 변환과 구분하려고 어파인 변환이라 한다. 투영은 멀리 있는 물체가 작게 보이기 때문에 평행을 유지하지 못하는 변환으로 어파인 변환이 아니다. 


 

 

 

 

2. 영상의 기하 변환

영상을 구성하는 점, 즉 화소에 동차 변환을 적용해 영상을 회전하거나 크기를 조정할 수 있다. 그런데 화소 위치를 정수로 지정하기 때문에 문제가 생긴다. 그림 3-20에서 점 (1, 3)이 (3.598, 0.232)로 변환되었는데 변환의 위치를 어떤 화소에 배정할 것인가? 쉽게 생각할 수 있는 방법은 반올림하여 (4,0) 화소에 배정하는 것이다. 

 


 

 

3. 영상 보간

 

영상에 기하 연산을 적용할 때 후방 변환을 사용하면 구멍이 생기는 현상을 방지할 수 있다. 하지만 여전히 실수 좌표를 정수로 변환하는 과정이 필요하다. 이때 반올림을 사용해 가장 가까운 화소에 배정하는 기법을 최근접 이웃 방법이라고 부른다. 최근접 이웃은 에일리어싱이 여전히 심하다. 예를 들어 그림 3-21 b에서 볼 수 있듯이 변환 영상에서 서로 다른 2개의 화소가 같은 값을 받고 있다. 이런 에일리어싱은 보간을 사용하면 상당히 개선된다.

 

 

위의 그림은 겹치는 비율을 곱하기 때문에 선형 보간법에 해당한다. 이 보간은 x와 y의 두 방향에 걸쳐 계산하므로 양선형 보간법이라 한다. 16개의 이웃과 3채 함수를 사용해 보간하는 양3차 보간법이 있다. 양선형 보간과 양3차 보간은 최근접 이웃에 비해 화질이 월등히 좋다. 대신 계산 시간이 더 걸리는데, 현대의 컴퓨터는 매우 빠르기 때문에 대부분 상황에서 계산 시간은 크게 문제가 되지 않는다.

 

보간을 이용한 영상 변환

다음 프로그램은 영상을 확대하는데 최근접 이웃, 양선형 보간, 양3차 보간을 적용하고 양상 품질을 비교한다. 7행은 100 x 100 패치를 잘라 patch 객체에 저장한다. 원래 영상을 확대하면 너무 커서 패치를 잘라 실험한다.

최근접 이웃 방법의 경우 꽃잎 가장자리에 계단 모양의 에일리어싱 현상이 심하다. 

 

보간을 이용해 영상의 기하 변환하기

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

OpenCV의 시간 효율

컴퓨터 비전은 인식 정확률이 중요하지만 시간 효율도 못지 않게 중요하다. 예를 들어 비디오에서 물체를 추적하는 경우 초당 수십 장의 고해상도 영상을 처리할 수 있어야 한다. 직접 작성한 코드와 OpenCV가 제공하는 함수의 처리 시간을 비교해 봄으로써 OpenCV의 시간 효율을 분석해 보자.

 

OpenCV의 시간 효율 확인

다음 프로그램은 컬러 영상을 명암 영상으로 변환하는 함수 2개를 정의한다. 25~27행은 my_cvtGray1 함수를 호출해 명암 영상으로 변환한다. 함수 시작 직전과 끝났을 때 시간을 빼서 소요 시간을 출력한다. 

 

직접 작성한 함수와 OpenCV가 제공하는 함수의 시간 비교하기

 

실행 결과를 분석해 보자. my_cvtGray1 함수는 4.7983초가 걸렸다. 94만 8천여 개의 화소에 각각 접근하여 곱심 세 번과 덧셈 두 번을 수행하는데 소요된 시간이다. 놀랍게도 배열 연산을 사용한 my_cvtGray2 함수는 0.0158초가 걸렸다. for 문 2개로 화소를 일일이 방문하는 my_cvtGray1 함수보다 무려 300배 가량 빠르다. 파이썬에서는 가능한 경우 배열 연산을 사용해야 하는 이유다.

 

OpenCV가 제공하는 함수는 0.0136초가 걸렸다. my_cvtGray2 함수보다 미세하게 빠르다. OpenCV는 C와 C++ 언어로 함수를 작성하고 인텔 마이크로프로세서에 최적화하는 등의 노력을 기울여 빠른 속도를 자랑한다.

 

 

이 코드를 실행하는데 많은 어려움이 있었다. 

 

 

계속 이런 오류가 떴는데 그건 이미지 파일이 해당 경로에 없었고 확장명도 잘못 되었었다. 책의 코드가 틀린 것이다. 어쨌든 문제를 해결할 수 있어서 다행이었다.

 


 

 

 

학습을 마치고

3장의 마지막 단원 학습을 마쳤다. 정말 여기까지 오느라 많이 힘들었다. 그래도 끝까지 포기하지 않고 잘 따라와 주었다. 이제 늦은 아침을 먹고 연습문제를 풀며 이 단원을 마무리해 볼 것이다.