C# OpenCV 강좌 : 제 23강 - 블록 껍질
블록 껍질(ConvexHull)
영상이나 이미지의 외곽점들을 잇기
위해 사용합니다.
영상이나 이미지에서 Contour
와 ConvexHull2
를 이용해 최외곽점들이 연결된 다각형을 만들 수 있습니다.
원본(Source, src)
은 영상이나 이미지를 사용합니다.
클래스 코드
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
namespace Project
{
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);
}
}
}
세부 코드
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
점으로 대체해서 다음 지점과 연결되게 만듭니다.
출력 결과
공유하기


댓글 남기기