본문 바로가기
Study(Data Analysis, OpenCV, Python, AI)/OpenCV-Python

08.기하학 처리

by emergensaur 2024. 4. 30.

영상처리에서 기하학은 대상의 길이, 넓이, 각도 등을 측정하거나 공간상의 특성을 연구하는 수학의 한 분야이다. 영상 처리에서의 기하학 처리는 영상 내에 있는 기하학적인 대상의 공간적 배치를 변경하는 과정을 말한다. 이를 화소 입장에서 보면, 영상을 구성하는 화소들의 공간적 위치를 재배치 하는 과정이라고 볼 수 있다. 

이러한 변환에는 크게 회전, 크기변경, 평행이동 등이 있다. 보통 영상처리 관련 논문에서 이 세가지 변환을 일컬어 RST변환이라고 한다. R은 Rotation, S는 Scaling, T는 Transition의 첫 글자이다. 

사상

기하학 처리 기본은 화소들의 배치를 변경하는 것이다. 사상은 화소들의 배치를 변경할 때, 입력영상의 좌표가 새롭게 배치될 해당 목적 영상의 좌표를 찾아서 화소값을 옮기는 과정을 말한다.  순방향 사상, 역방향 사상 두가지 방식이 존재한다. 순방향 사상은 입력 영상의 좌표를 중심으로 목적 영상의 좌표를 계산하여 화소의 위치를 변환하는 방식이다. 이 방식은 일반적으로 입력영상과 목적영상이 크기가 같을 때 유용하게 사용이 가능하다. 다만 두 영상의 크기가 달라지면 홀(hole)이나 오버랩(overlap)의 문제가 발생할 수 있다. 

 

홀은 입력 영상의 좌표들로 목적 영상의 좌표를 만드는 과정에서 사상되지 않은 화소를 가리킨다. 보통 영상을 확대하거나 회전할 때 발생한다. 반면, 오버랩은 영상을 축소할 때 주로 발생한다. 입력 영상의 여러 호소들이 목적 영상의 한 화소로 사상되는 것을 말한다. 

 

이런 문제를 해결 하는 방법이 역방향 사상이다.  역뱡향 사상은 목적 영상의 좌표를 중심으로 역변환을 계산하여 해당하는 원본 영상의 좌표를 찾아서 화소값을 가져오는 방식이다. 입력 영상의 한 화소를 목적영상의 여러 화소에서 사용하게 되면 결과 영상의 품질이 떨어진다. 이를 해결하는 것이 보간법

크기 변경(확대/축소)

영상의 크기 변경을 위하여 영상을 확대하거나 축소하는 것은 포토샵을 비롯한 많은 응용프로그램에서 경험해 보았을 것이다. 이러한 크기변경(scaling)은 입력 영상의 가로와 세로로 크기를 변경해서 목적 영상을 만드는 방법이다. 목적영상이 입력영상보다 커지면 확대가 되고, 작아지면 축소가 된다. 

 

영상의 크기 변경 방법은 먼저 비율을 이용해서 수행할 수 있다. 변경하려는 가로와 세로의 비율(ratioX, ratioY)를 지정해 입력해 목적영상의 좌표를 계산할 수 있다.  다른 목적으로 영상의 크기를 지정해 변경하는 것 역시 가능하다. 입력 영상과 목적영상의 크기로 비율을 계산하고 계산된 비율로 목적 영상의 좌표를 계산한다. 

보간 

순방향 사상으로 확대할 경우에 목적 화소의 빈 부분인 홀들이 많이 발생하게 된다. 이렇게 빈 공간들을 채우기 위해서 목적영상에서 홀들의 화소를 채우며, 오버랩 되지 않게 화소들을 배치하여 목적영상을 만드는 기법을 보간법(interpolation)이라 한다. 목적영상에서의 홀의 화소들을 채우며, 오버랩되지 않게 화소들을 배치하여 목적영상을 만드는 기법을 보간법이라 한다. 보간법의 종류에는 최근접 이웃 보간법, 양선형 보간법, 3차회선 보간법 등 다양한 방법이 존재한다. 

최근접 이웃 보간법(nearest neighbor interpolation)

목적영상을 만드는 과정에서 홀이되어 화소값을 할당 받지 못한 위치의 값을 가장 가갑게 이웃한 입력화소의 값을 가져오는 방식이다. 목적영상의 품질을 쉽게 올릴 수 있지만, 확대 비율이 커지면 영상내에서 경계선이나 모서리 부분에서 계단현상이 나타날 수 있다. 

양선형 보간법(bilinear interpolation)

직선의 특징을 가진 것으로 직선 방정식을 예로 들 수 있다. 직선 우에 위치한 화소값들은 직선 수식을 이용해 쉽게 계산이 가능하다. 직선 수식을 활용해서 자신을 중심으로 두개의 선을 구성하고 이 선의 중심점에 목적영상 화소가 존재하도록 하는 방식이다. 이러한 양선형 보간을 수행한 결과가 cv2.resize()함수를 이용한 방법이다. cv2.remap(), cv2.warpAffine(), cv2.warpPerspective()등과 같이 보간이 필요한 함수들을 위해 OpenCV에서 다양한 보간 방법을 지원한다. 다음은 보간 방법과 그 옵션 값이다. 

평행 이동 

일반적으로 그래프에 좌표를 표시할 때와는 다르게 영상에서 원점 표시는 기본적으로 최상단 인쪽이다. 이를 기준으로 x, y만큼 이동하게 되는 것이다. 평행이동을 수식으로 표현하면 다음과 같다. 순방향 사상을 적용하면 입력 영상의 화소(x,y)에서 이동할 화소 수만큼 가로방향과 세로 방향으로 더해주어 목적 영상의 화소 위치를 정하면 된다. 반면, 역방향 사상을 적용하면 평행 이동하려는 화소개수를 목적영상의 좌표에서 빼면 양의 방향(오른쪽 하단)으로 이동한다. 

회전 

회전은 입력 영상의 모든 화소를 영상의 원점을 기준으로 원하는 각도만큼 모든 화소에 대해서 회전 변환을 시키는 것을 말한다. 이것은 2차원 평면에서 회전 변환을 나타나는 행렬을 통해서 수식으로 표현한다. 순방향 사상과 역방향 사상 모두 sin함수의 부호만이 차이가 난다. 평행이동과 마찬가지로 목적영상의 예상범위를 벗어나는 입력화소는 제거되고, 입력영상에서 찾지 못하는 목적화소는 검은색이나 흰색으로 지정한다. 

 

일반적으로 영상을 회전 시킬 때에는 회전의 기준을 영상의 기준 원점인 좌상단이 아닌 물체의 중심(center X, center Y)로 하는 경우가 많다 이 경우에는 평행 이동의 수식을 포함해 회전 변환을 수행한다. 

행렬 연산을 통한 기하학 변환- 어파인 변환

기하학 변환의 수식은 행렬식으로 표현이 가능하다. 즉, 기하학 변환 수식이 행렬의 곱으로 표현되는 것이다. 어파인 변환은 변환 전과 변환후의 두어파인 공간 사이에 공선점(한 직선상의 점)을 보존하는 변환이고 변환 전의 직선은 변환 후에도 그대로 직선이며, 그 거리으 비율도 유지된다. 또한 변환전에 평행선도 변환 후에 평행선이 된다. 

OpenCV에서는 어파인 변환 수행 가능한 함수로 cv2.warpAffine()함수를 제공함. 이 함수는 어파인 변환 행렬을 적용하면 입력영상에 어파인 변환을 수행한 목적 영상을 반환한다. 어파인 변환 행렬을 만드는 함수로는 cv2.getAffineTransform(), cv2.getRotationMatrix2D()가 있고 둘 모두 어파인 행렬을 반환한다. 회전 방향은 양수일 때 반시계 방향으로 회전 행렬을 반환한다. 

cv2.warpAffine(src, M, dsize[,dst[,flags[,borderMode, [, borderValue]]]])→dst 

입력 영상에 어파인 변환을 수행해서 반환한다. 

(입력영상, 어파인 변환 행렬, 반환영상 크기,[ 반환영상,[,보간방법,[경계지정 방법,[경계값]]]]) 반환영상

cv2.getAffineTransform(src, dst)→retval

3개의 좌표쌍을 입력하면 어파인 변환행렬을 반환한다.

(입력 영상좌표 3개, 목적영상좌표 3개)

cv2.getRotationMatrix2D(center, angle, scale)→retval

회전 변환과 크기 변경을 수행할 수 있는 어파인 행렬을 반환한다. 

(회전의 중심점, 회전각도-양수각도가 반시계방향 회전수행, 변경할 크기)

cv2.invertAffineTransform(M[,iM])→iM 

어파인 변환 행렬의 역행렬을 반환함

M어파인 변환 행렬, iM어파인 역변환 행렬

원근 투시 변환(투영)

3차원 세계를 2차원 그림(평면)으로 옮길 때 관찰자가 보는 것 그대로 사물과의 거리를 반영하여 그리는 방법을 말한다. 정확히는 투시 혹은 투영 원근법(projection transformation)이 이에 해당함. 원근 투시 변환(perspective projection transformation)은 이 원근법은 영상 좌표게에서 표현하는 것으로서 3차원 실세계 좌표 P를 투영 스크린 상의 2차원 좌표로 표현 가능하게 변환하는 것을 말한다. 영상 처리에서 원근 변환은 주로 2차원 영상을 다른 2차원 영상으로 변환할 때 사용된다. 원근 투영 변환을 사용할 때는 동차 좌표계(homogeneous coordinates)를 사용하는 것이 편리하다. 동차 좌표계는 모든 항의 차수가 동일하기 때문에 n 차원의 투영공간을 n+1개의 좌표로 나타내는 좌표계이다. (x,y)를 (x,y,1)로 표현하는 것이다. 0이 아닌 상수 w에 대해 (x,y)를 (ax, ay, a)로 표현한다. 이렇게 되면 같은 비율을 가지는 상수는 무한하게 많기 때문에 (x,y)에 대한 동차 좌표표현은 무한히 많이 존재하게 된다.

거꾸로 동차 좌표계에서 한점을 직교 좌표로 나타내면 상수로 나누고 뒤의 항을 없앤 (x/a, y/a)가 된다. 

cv2.getPerspectiveTransform(src, dst[, solveMethod]) →retval  

4개 좌표쌍을 입력하면 원근 변환 행렬을 반환한다. (입력 영상 4개 좌표, 목적영상 4개 좌표, [경계지정법])

cv2.warpPerspective(src, M, dsize[,dst[,flags[,borderMode[,borderValue]]]])→dst

영상에 원근 변환을 적용한다. 

(입력영상, 원근 변환행렬, 결과 영상의 크기, [결과영상,[보간방법[경계지정 방법,[경계화소값]]]])

cv2.transform(src, M)→dst

입력 좌표 행렬에 원근 변환을 수행한 결과를 반환한다.  

(입력 좌표행렬, 원근 좌표행렬, 결과 좌표 행렬)

cv2.wrapPerspective()함수를 적용해서 원근 변환된 영상을 반환하고 cv2.transform함수로 원근 변환된 좌표를 반환한다. 

좌표 사각형을 순회해서 가죠오고, 좌표로 그리기 위해 시작좌표와 크기를 따로 가져온다. cv2.polylines() 함수로 두번째 인수의 좌표들을 잇는 선들을 그려 사각형을 구성한다. 이 사각형에 대해 원근 변환을 getPerspectiveTransform 로 바꿔서 데이터를 받고, 이 데이터를 활용해서 warpPerspective로 실제 영상을 만든다. 

 

https://www.booksr.co.kr/product/opencv-python%EC%9C%BC%EB%A1%9C-%EB%B0%B0%EC%9A%B0%EB%8A%94-%EC%98%81%EC%83%81%EC%B2%98%EB%A6%AC-%EB%B0%8F-%EC%9D%91%EC%9A%A9/

 

OpenCV-Python으로 배우는 영상처리 및 응용 | 생능출판사

셜 맥루한이 1962년 처음으로 사용한 ‘글로벌 빌리지(global village)’는 세상이 인터넷과 같은 정보통신 기술에 의해 전 세계가 하나의 마을처럼 된다고 했습니다. 2020년은 그런 의미를 넘어서, 코

www.booksr.co.kr