오랜만에 포스팅하는군요!
이번 포스팅에서는 Perspective Transformation을 이용한 이미지 와핑 방법을 알아보도록 하겠습니다.
요즘 스마트폰 많이들 사용하실텐데요. 스마트폰 앱 중에서 CamScanner 같은 앱을 이용하여 마치 스캔한 것과 같은 이미지를 얻을 수 있는 걸 많이 보셨을 겁니다.
다음 그림을 보시면 이해가 되실텐데요. 직접 찍은 사진에서 원하는 영역만을 마치 스캔한 것과 효과를 내는 것을 확인할 수 있습니다.
이는 와핑 기법 중 하나로 투영 변환(Perspective Transformation)을 이용한 가장 대표적인 예라고 할 수 있습니다.
다음 사진을 이용하여 위처럼 구현해보도록 하겠습니다.
위 캡처된 영상에서 A4 용지 부분만 검출하여 이미지를 와핑해보도록 하겠습니다.
OpenCV 내의 WarpPerspective 함수를 이용하여 이미지를 와핑하기 위해서는 입력 영상 내에서 와핑하고자 하는 영역의 네 개의 점과 와핑된 이미지를 저장하고자 하는 영역의 네 개의 점을 이용하여 소위 말하는 변환 행렬을 구해주어야 합니다.
위 이미지에서 와핑하고자 하는 영역의 네 개의 점은 픽셀 좌표로 구할 수 있습니다.
네모박스 안의 값은 차례대로 x, y 좌표입니다.
자 이제 입력 영상에서 와핑하고자 하는 영역의 네 개의 점의 좌표를 구했습니다.
다음은 이 영역을 와핑하여 저장하고자 하는 영역의 네개의 점을 구해야 하는데요. 와핑의 크기는 항상 달라질 수 있기 때문에 사용자가 고정적으로 입력하는 것보다는 와핑 영역의 크기를 이용하여 네 개의 점의 위치를 구할 수 있습니다.
코드로 보면 다음과 같습니다.
Point TopLeft = Point(223, 44); Point TopRight = Point(496, 44); Point BottomRight = Point(715, 301); Point BottomLeft = Point(13, 322); vector<Point> rect; rect.push_back(TopLeft); // 왼쪽 위 rect.push_back(TopRight); // 오른쪽 위 rect.push_back(BottomRight); // 오른쪽 아래 rect.push_back(BottomLeft); // 왼쪽 아래 double w1 = sqrt( pow(BottomRight.x - BottomLeft.x, 2) + pow(BottomRight.x - BottomLeft.x, 2) ); double w2 = sqrt( pow(TopRight.x - TopLeft.x, 2) + pow(TopRight.x - TopLeft.x, 2) ); double h1 = sqrt( pow(TopRight.y - BottomRight.y, 2) + pow(TopRight.y - BottomRight.y, 2) ); double h2 = sqrt( pow(TopLeft.y - BottomLeft.y, 2) + pow(TopLeft.y - BottomLeft.y, 2) ); double maxWidth = (w1 < w2) ? w1 : w2; double maxHeight = (h1 < h2) ? h1 : h2; Point2f src[4], dst[4]; src[0] = Point2f(TopLeft.x, TopLeft.y); src[1] = Point2f(TopRight.x, TopRight.y); src[2] = Point2f(BottomRight.x, BottomRight.y); src[3] = Point2f(BottomLeft.x, BottomLeft.y); dst[0] = Point2f(0, 0); dst[1] = Point2f(maxWidth-1, 0); dst[2] = Point2f(maxWidth-1, maxHeight-1); dst[3] = Point2f(0, maxHeight-1);
일단 입력 영상에서 얻은 점들을 이용하여 최대 width와 최대 height를 이용해서 저장하고자 하는 영역의 크기를 설정하는 부분입니다. dst 배열이 저장하고자 하는 영역의 점들입니다.
여기까지 완료하였으면 다음 줄에 다음과 같이 한 줄만 추가해주면 변환행렬을 구할 수 있습니다.
transformMatrix = getPerspectiveTransform(src, dst);
변환행렬을 구했으니 다음은 이미지를 와핑하면 끝입니다.
와핑은 warpPerspective함수를 이용하면 쉽게 할 수 있습니다.
코드로 보면 다음과 같습니다.
warpPerspective(srcFrame, dstFrame, transformMatrix, Size(maxWidth, maxHeight));
여기서 srcFrame은 입력이고 dstFrame은 저장할 변수입니다. transforMatrix는 위에서 구한 변환 행렬이고 maxWidth와 maxHeight는 위에서 구한 값입니다.
결과를 보도록 하겠습니다.
제가 원하는 영역만 와핑된 것을 확인할 수 있습니다!
이상 포스팅 마치도록 하겠습니다.
'영상처리' 카테고리의 다른 글
[적외선 웹캠 개조] Logitech C920 적외선 웹캠으로 개조하기! (7) | 2014.01.16 |
---|---|
[OpenCV] YCbCr 컬러 모델을 이용하여 피부 검출하기 (1) | 2013.12.29 |