C#/C# OpenCV/

C# OpenCV 7-3. Contour(3) 근사화경계

2019. 12. 10.

대표함수

Cv2.CvtColor 색공간 변환 [프로그래밍/C# OpenCV] - C# OpenCV 5-1. 색공간 변환

Cv2.Threshold 이진화 [프로그래밍/C# OpenCV] - C# OpenCV 4-2. Binary

Cv2.FindContour contour 찾기 [프로그래밍/C# OpenCV] - C# OpenCV 7-1. Contour(1) 윤곽선 찾기

Cv2.DrawContour contour 그리기 [프로그래밍/C# OpenCV] - C# OpenCV 7-1. Contour(1) 윤곽선 찾기

Cv2.ArcLength contour perimeter 혹은 곡선의 길이 계산

Cv2.ApproxPolyDp Douglas-Peucker 알고리즘을 이용 contour 혹은 곡선의 근사화

 

Example Code


using System;
using System.Windows.Forms;
using OpenCvSharp;

namespace findContour3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Mat src = Cv2.ImRead("image.png");
            Mat bin = new Mat();
            Mat result = new Mat();
            src.CopyTo(result);
            Cv2.CvtColor(src, bin, ColorConversionCodes.BGR2GRAY);
            Cv2.Threshold(bin, bin, 0, 255, ThresholdTypes.Otsu);
            Cv2.ImShow("src", src);
            
            Cv2.FindContours(bin, out Point[][] contour, out HierarchyIndex[] hierarchy, 
                RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);

            for(int i = 0; i &lt contour.Length; i++)
            {
                Cv2.DrawContours(result, contour, i, Scalar.Yellow, 2, LineTypes.AntiAlias);
            }
            Cv2.ImShow("result", result);

            Point[][] approx = new Point[contour.Length][];
            for (int i = 0; i &lt contour.Length; i++)
            {
                double epsilon = 0.05 * Cv2.ArcLength(contour[i], true);                
                approx[i] = Cv2.ApproxPolyDP(contour[i], epsilon, true);
            }

            for (int i = 0; i &lt contour.Length; i++)
            {
                Cv2.DrawContours(result, approx, i, Scalar.Red, 2, LineTypes.AntiAlias);
            }
            Cv2.ImShow("result", result);

            Cv2.WaitKey(0);
            Cv2.DestroyAllWindows();
        }
    }
}

 

Explain Code


	    Mat src = Cv2.ImRead("image.png");
            Mat bin = new Mat();
            Mat result = new Mat();
            src.CopyTo(result);
            Cv2.CvtColor(src, bin, ColorConversionCodes.BGR2GRAY);
            Cv2.Threshold(bin, bin, 0, 255, ThresholdTypes.Otsu);
            Cv2.ImShow("src", src);
            

필요한 요소 선언, 초기화

이미지 이진화

 


	    Cv2.FindContours(bin, out Point[][] contour, out HierarchyIndex[] hierarchy, 
                RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);

            for(int i = 0; i &lt contour.Length; i++)
            {
                Cv2.DrawContours(result, contour, i, Scalar.Yellow, 2, LineTypes.AntiAlias);
            }
            Cv2.ImShow("result", result);
            

contour 찾기

contour 그리기 - 노란색

 


	    Point[][] approx = new Point[contour.Length][];

근사 정보저장할 Point[][]변수 approx 선언

contour의 정보를 근사변환 저장할 변수이기에 Point[][]로 선언,

다중배열 1의 길이값은 contour의 길이와 동일,

다중배열 2의 길이값은 변환되어 저장될거라 null

 

	    for (int i = 0; i &lt contour.Length; i++)
            {
                double epsilon = 0.05 * Cv2.ArcLength(contour[i], true);                
                approx[i] = Cv2.ApproxPolyDP(contour[i], epsilon, true);
            }
            

Cv2.ArcLengthCv2.ApproxPolyDp 함수로 contour 근사변환

 

Cv2.ArcLength(IEnumerable<Point> curve, bool cloesd)

      curve contour 혹은 곡선 정보를 담고있는 Point

      bool값 곡선의 닫힘 정보, true일 경우 시작점과 끝점을 연결하여 계산

 

Cv2.ApproxPolyDp(IEnumerable<Point> curve, double epsilon, bool closed)

      curve contour 혹은 곡선 정보를 담고있는 Point

      epsilon 근사치 최대거리

      bool값 곡선선의 닫힘 정보, true일 경우 시작점과 끝점을 연결하여 계산

 


	    for (int i = 0; i &lt contour.Length; i++)
            {
                Cv2.DrawContours(result, approx, i, Scalar.Red, 2, LineTypes.AntiAlias);
            }

근사정보를 이용하여 새로운 contour 그리기 - 빨강

 

결과