상위 목록: 하위 목록: 작성 날짜: 읽는 데 21 분 소요

윤곽선 관련 함수는 검출된 윤곽선의 형상을 분석 및 재가공할 때 사용되는 함수입니다.

윤곽선 검출 정보를 활용하여 파생될 수 있는 정보를 제공합니다.

윤곽선 객체의 중심점, 길이, 넓이, 최소 사각형 등 윤곽선 정보를 통해 계산할 수 있는 정보들을 쉽게 구할 수 있습니다.



메인 코드

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)를 계산할 수 있습니다.



출력 결과

댓글 남기기