C# OpenCV 강좌 : 제 19강 - 윤곽선 관련 함수 (2)
윤곽선 관련 함수(Contour Related Functions)
윤곽선 관련 함수
는 검출된 윤곽선의 형상을 분석 및 재가공할 때 사용되는 함수입니다.
윤곽선 검출 정보를 활용하여 파생될 수 있는 정보를 제공합니다.
윤곽선 객체의 중심점
, 길이
, 넓이
, 최소 사각형
등 윤곽선 정보를 통해 계산할 수 있는 정보들을 쉽게 구할 수 있습니다.
메인 코드
using System;
using OpenCvSharp;
using System.Collections.Generic;
namespace Project
{
class Program
{
static void Main(string[] args)
{
Mat src = new Mat("hex.jpg");
Mat yellow = new Mat();
Mat dst = src.Clone();
Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.InRange(src, new Scalar(0, 127, 127), new Scalar(100, 255, 255), yellow);
Cv2.FindContours(yellow, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxTC89KCOS);
foreach (Point[] p in contours)
{
double length = Cv2.ArcLength(p, true);
double area = Cv2.ContourArea(p, true);
if (length < 100 && area < 1000 && p.Length < 5) continue;
bool convex = Cv2.IsContourConvex(p);
Point[] hull = Cv2.ConvexHull(p, true);
Moments moments = Cv2.Moments(p, false);
//Cv2.FillConvexPoly(dst, hull, Scalar.White);
//Cv2.Polylines(dst, new Point[][] { hull }, true, Scalar.White, 1);
Cv2.DrawContours(dst, new Point[][] { hull }, -1, Scalar.White, 1);
Cv2.Circle(dst, (int)(moments.M10 / moments.M00), (int)(moments.M01 / moments.M00), 5, Scalar.Black, -1);
}
Cv2.ImShow("dst", dst);
Cv2.WaitKey(0);
}
}
}
세부 코드
Mat src = new Mat("hex.jpg");
Mat yellow = new Mat();
Mat dst = src.Clone();
new Mat
을 사용해 이미지를 src
에 할당합니다.
전처리 결과를 저장할 yellow
를 선언합니다.
연산 결과를 저장할 dst
를 선언합니다.
Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.InRange(src, new Scalar(0, 127, 127), new Scalar(100, 255, 255), yellow);
Cv2.FindContours(yellow, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxTC89KCOS);
List<Point[]> new_contours = new List<Point[]>();
foreach (Point[] p in contours)
{
...
}
윤곽선 관련 함수 알고리즘은 윤곽선 형태의 배열 구조
를 사용해 근사합니다.
그러므로, 윤곽선 검출 알고리즘을 진행합니다.
윤곽선 관련 함수 알고리즘은 하나의 윤곽선을 대상으로 진행되므로, 반복문(foreach)를 활용해 개별의 윤곽선에서 정보를 계산합니다.
if (length < 100 && area < 1000 && p.Length < 5) continue;
간단한 조건문(if)
을 활용해 유의미한 정보만 계산합니다.
윤곽선의 길이가 100 미만, 면적이 1000 미만, 윤곽점의 개수가 5 미만인 윤곽선은 무시
합니다.
bool convex = Cv2.IsContourConvex(p);
볼록성 시험 함수(Cv2.IsContourConvex)
는 윤곽선의 볼록한 형태인지 확인합니다.
Cv2.IsContourConvex(윤곽선 배열)
로 볼록성을 확인합니다.
볼록한 형태는 볼록한 형태
나 수직한 형태
를 갖는 것을 의미합니다.
볼록한 형태라면 단순한 다각형 형태를 지니고 있습니다.
즉, 교차하는 점이 없는 형태가 되어 하나의 윤곽선 그룹안에 하나의 다각형만 존재하게 됩니다.
볼록하다면 참
값을 반환하며, 볼록하지 않다면 거짓
값을 반환합니다.
Point[] hull = Cv2.ConvexHull(p, true);
볼록 껍질 함수(Cv2.ConvexHull)
는 윤곽선의 경계면을 둘러싸는 다각형을 반환합니다.
Cv2.ConvexHull(윤곽선 배열, 방향)
로 볼록 껍질을 계산합니다.
볼록한 형태를 반환하므로, 윤곽선 배열과 동일한 값을 반환합니다.
방향
은 검출된 볼록 껍질 배열의 색인(index)
순서를 결정합니다.
참
값일 경우 시계 방향으로 정렬되며, 거짓
값인 경우 반시계 방향으로 정렬됩니다.
볼록 껍질 알고리즘은 O(NlogN)
시간 복잡도를 갖는 스크랜스키(Sklansky) 알고리즘을 이용해 입력된 좌표들의 볼록한 외곽을 찾습니다.
스크랜스키 알고리즘은 윤곽점에서 경계 사각형의 정점(Vertex)
을 검출합니다.
경계면을 둘러싸는 다각형은 경계 사각형 내부에 포함되며, 해당 정점을 볼록점으로 사용합니다.
Moments moments = Cv2.Moments(p, false);
모멘트 함수(Cv2.Moments)
는 윤곽선의 0차 모멘트부터 3차 모멘트까지 계산합니다.
Cv2.Moments(배열, 이진화 이미지)
로 모멘트를 계산합니다.
이진화 이미지
는 입력된 배열
매개변수가 이미지일 경우, 이미지의 픽셀 값들을 이진화 처리할지 결정합니다.
이진화 이미지
매개변수에 참
값을 할당한다면 이미지의 픽셀 값이 0이 아닌 값은 모두 1의 값으로 변경해 모멘트를 계산합니다.
모멘트 함수는 공간 모멘트(Spatial Moments)
, 중심 모멘트(Central Moments)
정규화된 중심 모멘트(Normalized Central Moments)
를 계산합니다.
모멘트 값을 활용하면, 윤곽선의 질량 중심을 계산할 수 있습니다.
이 값을 주로, 객체의 중심점으로 활용합니다.
//Cv2.FillConvexPoly(dst, hull, Scalar.White);
//Cv2.Polylines(dst, new Point[][] { hull }, true, Scalar.White, 1);
Cv2.DrawContours(dst, new Point[][] { hull }, -1, Scalar.White, 1);
그리기 함수
를 활용해 검출된 정보들을 시각화 할 수 있습니다.
볼록 껍질은 볼록 껍질 그리기 함수(Cv2.FillConvexPoly)
로 시각화 할 수 있습니다.
단, 볼록 껍질 그리기 함수는 내부가 채워진 이미지로 그려집니다.
그러므로 다각형 그리기 함수(Cv2.Polylines)
나, 윤곽선 그리기 함수(Cv2.DrawContours)
등을 통해 내부가 채워지지 않은 다각형을 그릴 수 있습니다.
이 함수들은 2차원 배열을 입력 값으로 요구하므로, 2차원 배열로 변경하여 값을 입력합니다.
Cv2.Circle(dst, (int)(moments.M10 / moments.M00), (int)(moments.M01 / moments.M00), 5, Scalar.Black, -1);
모멘트 반환 값을 통해 윤곽선의 중심점(무게 중심)
을 계산할 수 있습니다.
모멘트 M_ij
는 윤곽선(이미지)의 모든 픽셀에 대한 합으로 정의됩니다.
X 좌표는 M_10 / M_00
로, Y 좌표는 M_01 / M_00
로 무게 중심 (X, Y)를 계산할 수 있습니다.
출력 결과
공유하기
![](http://developers.kakao.com/assets/img/about/logos/kakaolink/kakaolink_btn_medium.png)
![](/assets/images/naver.png)
댓글 남기기