Perspective Projection 이란 무엇인가?
Perspective Projection 이미지가 투영되는 면을 변화시키고자 할 때 사용하는 알고리즘이다.
내가 이 알고리즘을 접하게 된 것은 과거 프로젝트를 진행하면서 로봇 장치와 카메라를 가지고 사각 화면을 터치해야 하는 부분이 있었다. 알겠지만 카메라를 통해 보는 터치화면은 실체 터치화면 처럼 사각형으로 보이지 않을 경우가 있다. 그래서 클릭해야 할 좌표에 대한 보정이 필요한데 이 때 사용한 것이 이 알고리즘을 기반으로 한 것이다.
기본적으로 Perspective Transform 을 위한 수식은 다음과 같다.
저 행렬에서 1을 넣는 것은 표현식을 쉽고 구하기 편하게 하기 위함이다. 위 행렬의 의미는 일단 본 직선 방정식에 어떠한 변화를 주어 변경이 되었을 경우 직선방정식이 되는 a, b, c, d, e, f, g, h 값을 구하는 것이라고 생각하면 될 것 같다.
위의 표현식은 homogenious 좌료를 사용하고 있으니 x' 와 y' 는 아래와 같이 표현할 수 있다.
위 식을 정리하면 다시 아래와 같이 표현할 수 있다.
알고자 하는 값은 앞서 말한 것처럼 a 부터 h 의 값이다. 즉 대상이 사각형이라면 원래 크기의 사각형과 투영되는 사각형의 대응되는 4쌍의 좌표를 알면 구할 수 있는 것이다.
위 식을 각 점에 표현된 것으로 보면 x1 -> x1', y1 -> y1', x2 -> x2', y2 -> y2' .......
위와 같이 행렬로 표현할 수 있고 a ~ h 의 값은 위 식에 8 * 8 행렬의 역행렬을 구함으로써 알아낼 수 있다. 8개의 좌표 정보를 알고 있고 이 값을 대입하여 a~h 값을 구하면 Perspective Transform 행렬을 구할 수 있으며 해당 행렬을 가지고 사각형 내 임의의 좌표에 대한 보간 좌표를 얻을 수 있다. 실제 opencv 에는 이 행렬을 구하는 함수가 쉽게 지원되고 있으며 다음은 예제이다.
nAVNWidth = _wtoi(pProfile->GetProfileWidth());
nAVNHeight = _wtoi(pProfile->GetProfileHeight());
m_ptScrCoordiate[0] = cvPoint2D32f(_wtoi(pProfile->GetProfileTopLeftX()), _wtoi(pProfile->GetProfileTopLeftY()));
m_ptScrCoordiate[1] = cvPoint2D32f(_wtoi(pProfile->GetProfileTopRightX()), _wtoi(pProfile->GetProfileTopRightY()));
m_ptScrCoordiate[2] = cvPoint2D32f(_wtoi(pProfile->GetProfileBtmRightX()), _wtoi(pProfile->GetProfileBtmRightY()));
m_ptScrCoordiate[3] = cvPoint2D32f(_wtoi(pProfile->GetProfileBtmLeftX()), _wtoi(pProfile->GetProfileBtmLeftY()));
m_ptPerspectiveCoordinate[0] = cvPoint2D32f(0, 0);
m_ptPerspectiveCoordinate[1] = cvPoint2D32f(nAVNWidth, 0);
m_ptPerspectiveCoordinate[2] = cvPoint2D32f(nAVNWidth, nAVNHeight);
m_ptPerspectiveCoordinate[3] = cvPoint2D32f(0, nAVNHeight);
cvGetPerspectiveTransform(m_ptScrCoordiate, m_ptPerspectiveCoordinate, &m_perspectiveMatrix);
위 코드를 보면 cvGetPerspectiveTransform 함수를 이용하여 Perspective Transform 행렬을 구할 수 있다. 이 구한 행렬에서 (3, 3) 위치의 값이 1이 되도록 만들고 해당 행렬을 좌표 보정에 이용하면 끝이다.!!