Polygon detection
Peponi │ 5/27/2025 │ 5m
Polygon detection
Peponi
1. Introduction
Polygon detection
은 이미지 내에서 다각형 모양의 영역을 추출하는 것이다. 삼각형, 사각형 등 다양한 형태의 다각형을 검출할 수 있으며, 주로 다음과 같은 단계를 거쳐 수행한다.
-
Preprocessing
색상 공간 변환, 노이즈 제거 등을 수행하여 프로세싱에 알맞게 이미지를 조정한다. -
Edge detection
이미지의 엣지를 찾아낸다. 주로 Canny, Sobel 등의 알고리즘이 사용되며 이미지 특성에 따라 Thresholding 처리를 하기도 한다. -
Contour detection
검출된 엣지를 연결하여 contour를 만들어낸다. -
Filtering
검출된 contour 중 다각형이 될 수 있을 객체를 추려낸다. Contour의 면적, 길이 등을 이용하여 수행한다. -
Polygon approximation
이 단계에서 세밀하게 표현되어 있는 contour를 line segment로 이루어진 다각형으로 근사한다.TIP
Line segment가 만나는 지점이 다각형의 corner가 된다. 이를 이용하여 corner detection을 수행할 수 있다.
-
Post processing
Polygon들에 대한 추가 작업을 수행한다. 특정 크기, 형태 등을 이용하여 원하는 객체만 최종 결과로 출력한다.
OpenCV에서는 polygon detection을 수행할 수 있도록 Cv2.ApproxPolyDP()
메서드를 제공한다. 이 메서드는 Ramer–Douglas–Peucker algorithm에 기반하여 주어진 contour 또는 curve를 polygon 형태로 근사하며 다음과 같은 연산을 수행한다.
-
직선 생성
주어진 line segment의 시작점과 끝점을 찾아 직선을 생성한다. -
가장 멀리 떨어진 점 찾기
Line segment의 point 중 직선과 가장 멀리 떨어져 있는 point () 를 찾는다. -
임계값 () 비교
와 직선 사이의 거리 () 를 과 비교한다.
Line segment의 중간 점이 근사화에 기여하지 않는 것으로 판단하여 재귀 호출이 중단된다.
를 다각형의 corner로 포함한다. 이 점을 기준으로 line segment를 두 개로 분할하여 1 ~ 3 과정을 재귀적으로 반복한다.
더 이상 나눌 수 있는 line segment가 없어 연산이 종료되면 선택된 들이 근사된 다각형의 corner가 된다.
이 문서에서는 Cv2.ApproxPolyDP()
메서드를 이용하여 polygon detection을 수행하는 방법을 알아본다.
실습에 사용할 이미지는 다음과 같다.
2. Example


private void ApproxPolyDP(Mat image)
{
using var grayscale = image.CvtColor(ColorConversionCodes.BGR2GRAY);
using var canny = grayscale.Canny(50, 150);
// Contour detection : 가장 바깥쪽 외곽선만 가져오고, 필요한 최소한의 포인트만 구함
canny.FindContours(out var contours, out var hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
using var detected = image.Clone();
// 면적이 너무 작은 외곽선은 객체가 아닐 가능성이 높음
var contourThreshold = 10;
foreach (var contour in contours)
{
if (Cv2.ContourArea(contour) < contourThreshold)
continue;
// 다각형 계산 : epsilon 값은 보통 외곽선 길이의 5% 이하로 설정 (허용 오차)
var polygon = Cv2.ApproxPolyDP(contour, 0.03 * Cv2.ArcLength(contour, true), true);
// 도형 외곽선 그리기
detected.DrawContours([polygon], 0, Scalar.White, 2);
// 꼭지점의 수를 도형 안에 표현
detected.PutText($"{polygon.Length}", GetCenterApprox(polygon), HersheyFonts.HersheySimplex, 1, Scalar.Black, 2);
}
Cv2.ImShow("Canny", canny);
Cv2.ImShow("ApproxPolyDP", detected);
OpenCvSharp.Point GetCenterApprox(OpenCvSharp.Point[] polygon)
{
double sumX = 0, sumY = 0;
foreach (var corner in polygon)
{
sumX += corner.X;
sumY += corner.Y;
}
return new((int)(sumX / polygon.Length), (int)(sumY / polygon.Length));
}
}