C# OpenCV 강좌 : 제 23강 - 블록 껍질

C# OpenCV ConvexHull

C# OpenCV 강좌 : 제 23강 - 블록 껍질
[ C#-OpenCvSharp2 ] - 윤대희

블록 껍질(ConvexHull)


1 영상이나 이미지의 외곽점들을 잇기 위해 사용합니다. 영상이나 이미지에서 ContourConvexHull2를 이용해 최외곽점들이 연결된 다각형을 만들 수 있습니다.


원본(Source, src)를 영상이나 이미지를 사용하면 됩니다.

영상 사용하기 : 3강 바로가기

이미지 사용하기 : 4강 바로가기



Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace test
{
    class OpenCV : IDisposable
    {  
        IplImage bin;    
        IplImage convex;        
        
        public IplImage Binary(IplImage src)
        {
            bin = new IplImage(src.Size, BitDepth.U8, 1);
            Cv.CvtColor(src, bin, ColorConversion.RgbToGray);
            Cv.Threshold(bin, bin, 150, 255, ThresholdType.Binary);
            return bin;
        }
            
        public IplImage ConvexHull(IplImage src)
        {
            convex = new IplImage(src.Size, BitDepth.U8, 3);
            bin = new IplImage(src.Size, BitDepth.U8, 1);
            bin = this.Binary(src);

            CvMemStorage Storage = new CvMemStorage();
            CvSeq<CvPoint> contours;
            Cv.FindContours(bin, Storage, out contours, CvContour.SizeOf, ContourRetrieval.List, ContourChain.ApproxNone);

            CvSeq<CvPoint> apcon_seq = Cv.ApproxPoly(contours, CvContour.SizeOf, Storage, ApproxPolyMethod.DP, 3, true);

            for (CvSeq<CvPoint> c = apcon_seq; c != null; c = c.HNext)
            {
                CvPoint[] ptseq = new CvPoint[c.Total];

                if (c.Total > 4)
                {
                    for (int i = 0; i < c.Total; i++)
                    {
                        CvPoint? p = Cv.GetSeqElem(c, i);
                        ptseq[i] = new CvPoint
                        {
                            X = p.Value.X,
                            Y = p.Value.Y
                        };
                    }

                    foreach (CvPoint pt in ptseq)
                    {
                        Cv.Circle(convex, pt, 4, CvColor.Red, -1);
                    }

                    CvPoint[] hull;
                    Cv.ConvexHull2(ptseq, out hull, ConvexHullOrientation.Clockwise);

                    CvPoint pt0 = hull.Last();
                    foreach (CvPoint pt in hull)
                    {
                        Cv.Line(convex, pt0, pt, CvColor.Green, 2);
                        pt0 = pt;
                    }
                }
            }  
            return convex;
        }
            
        public void Dispose()
        {
            if (bin != null) Cv.ReleaseImage(bin);        
            if (convex != null) Cv.ReleaseImage(convex);        
        }
    }
}



Class Code


convex = new IplImage(src.Size, BitDepth.U8, 3);
bin = new IplImage(src.Size, BitDepth.U8, 1);
bin = this.Binary(src);

검은 이미지인 convex과 Binary 이미지인 bin을 선언하고 적용시킵니다.

  • Tip : convex는 원본을 복사하지 않아 검은색 이미지입니다.


CvMemStorage Storage = new CvMemStorage();
CvSeq<CvPoint> contours;
Cv.FindContours(bin, Storage, out contours, CvContour.SizeOf, ContourRetrieval.List, ContourChain.ApproxNone);

윤곽(Contour)을 검출하기 위하여 Storage, contours를 선언하고 Cv.FindContours()를 적용합니다.

Contour 알아보기 : 20강 바로가기


CvSeq<CvPoint> apcon_seq = Cv.ApproxPoly(contours, CvContour.SizeOf, Storage, ApproxPolyMethod.DP, 3, true);

다각형 곡선을 근사화 하기 위해 Cv.ApproxPoly()를 사용하여 근사합니다.

ApproxPoly 알아보기 : 22강 바로가기


for (CvSeq<CvPoint> c = apcon_seq; c != null; c = c.HNext)
{
    CvPoint[] ptseq = new CvPoint[c.Total];

    if (c.Total > 4)
    {
        for (int i = 0; i < c.Total; i++)
        {
            CvPoint? p = Cv.GetSeqElem(c, i);
            ptseq[i] = new CvPoint
            {
                X = p.Value.X,
                Y = p.Value.Y
            };
        }

        foreach (CvPoint pt in ptseq)
        {
            Cv.Circle(convex, pt, 4, CvColor.Red, -1);
        }

        CvPoint[] hull;
        Cv.ConvexHull2(ptseq, out hull, ConvexHullOrientation.Clockwise);

        CvPoint pt0 = hull.Last();
        foreach (CvPoint pt in hull)
        {
            Cv.Line(convex, pt0, pt, CvColor.Green, 2);
            pt0 = pt;
        }
    }
}  

if문 까지는 22강과 흡사합니다. 코너를 검출하기 위해 사용합니다. 자세한 사항은 22강의 설명을 참고하시기 바랍니다.

CvPoint[] ptseq = new CvPoint[c.Total]을 이용하여 다각형을 만들기 위해 생성자를 만듭니다.

생성될 다각형과 다각형 안의 모든 점의 개수c.Total값과 동일합니다.

ptseq[i] = new CvPoint를 이용하여 하나의 다각형 안에 있는 점의 좌표들을 배열로 저장합니다.

이 정보들을 통하여 최외곽점들을 알 수 있습니다.

ptseq[i] = new CvPoint{ ... }에서 각 점들의 위치를 저장합니다.

foreach문을 이용하여 모든 점들을 그립니다. 이 구문은 점을 표현하기 위한 구문이므로 생략하셔도 가능합니다.

CvPoint[] hull을 선언합니다. 이 구문은 최 상단의 for문 밖에 선언하셔도 됩니다. 코드의 원활한 설명을 위하여 for문 안에 삽입하였습니다.

Cv.ConvexHull2()를 이용하여 블록 껍질을 찾습니다.

ConvexHull2(코너점들의 집합, 최외곽 점, 회전 방향)입니다.

코너점들을 이용하여 최외곽점들을 찾습니다. ConvexHullOrientation은 시계방향인 Clockwise와 반시계방향인 Counterclockwise가 있습니다.

CvPoint pt0 = hull.Last()을 이용하여 블록 껍질을 만들기 위해 최초 지점을 설정합니다.

모든 점들을 그리는 방법과 동일하게 foreach문을 이용하여 선들을 연결합니다. pt0를 현재의 pt점으로 대체해서 다음 지점과 연결되게 만듭니다.



Result


2



Book Image

개정판이 출간됐습니다!

C#과 파이썬을 활용한 OpenCV 4 프로그래밍 (개정판)

컴퓨터 비전 기초 이론부터 머신러닝을 활용한 영상 처리 프로젝트까지

  • C#과 파이썬용 OpenCV의 데이터 형식과 행렬 및 배열 연산
  • 이미지/동영상/카메라를 활용한 입출력과 결과 저장
  • 전처리 과정과 정보를 탐색하기 위한 이미지 변형
  • 유의미한 정보를 검출하기 위한 이미지 변환
  • 이미지에서 정보를 검출 및 인식
  • 객체 검출을 포함한 모션 추적
  • K-means, KNN, SVM 등의 머신러닝 알고리즘 적용 방법
  • 카페(Caffe), 다크넷(Darknet), 텐서플로 모델을 활용한 딥러닝 모듈 적용 방법
  • Tesseract-OCR과 C# OpenCvSharp4를 활용한 프로젝트
  • 텐서플로와 Python OpenCV4를 활용한 프로젝트
  • 윤대희 저 | 위키북스

    [yes24 바로가기] [알라딘 바로가기] [교보문고 바로가기]

    후원하기


    ⤧  Previous post C# OpenCV 강좌 : 제 22강 - 코너 검출 (2) ⤧  Next post C# OpenCV 강좌 : 제 24강 - 중심점
    C#-OpenCvSharp2 Category