C# OpenCV 강좌 : 제 22강 - 코너 검출 (2)
코너(Corner)
영상이나 이미지의 모서리(코너)를 검출
하기 위해 사용합니다.
영상이나 이미지에서 Contour
와 ApproxPoly
를 이용하여 검출 할 수 있습니다.
원본(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 apcon;
public IplImage Binary(IplImage src)
{
bin = new IplImage(src.Size, BitDepth.U8, 1);
Cv.CvtColor(src, bin, ColorConversion.RgbToGray);
Cv.Threshold(bin, bin, 200, 255, ThresholdType.Binary);
return bin;
}
public IplImage ApproxPoly_Contour(IplImage src)
{
apcon = new IplImage(src.Size, BitDepth.U8, 3);
bin = new IplImage(src.Size, BitDepth.U8, 1);
Cv.Copy(src, apcon);
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)
{
if (c.Total > 4)
{
for (int i = 0; i < c.Total; i++)
{
CvPoint? p = Cv.GetSeqElem(c, i);
CvPoint conpt;
conpt.X = p.Value.X;
conpt.Y = p.Value.Y;
Cv.Circle(apcon, conpt, 3, CvColor.Black, -1);
}
}
}
return apcon;
}
public void Dispose()
{
if (bin != null) Cv.ReleaseImage(bin);
if (apcon != null) Cv.ReleaseImage(apcon);
}
}
}
세부 코드
apcon = new IplImage(src.Size, BitDepth.U8, 3);
bin = new IplImage(src.Size, BitDepth.U8, 1);
Cv.Copy(src, apcon);
bin = this.Binary(src);
원본 이미지를 복사한 apcon
과 Binary 이미지인 bin
을 선언하고 적용시킵니다.
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()
를 이용하여 다각형 곡선을 근사합니다.
Cv.ApproxPoly(시퀸스, 자료구조의 크기, 메모리 저장소, 근사방법, 근사정확도, 시퀀스결정)
입니다.
근사정확도
의 값이 낮을수록 세밀하며, 너무 높거나 낮을 경우 코너점이 너무 많이 검출되거나 적게 검출됩니다.
시퀀스결정
은 단일시퀀스로 근사화하기 위해 true
로 설정합니다.
- Tip : 근사방법은
Douglas-Peucker Algorithm
인 ApproxPolyMethod.DP만 사용할 수 있습니다.
for (CvSeq<CvPoint> c = apcon_seq; c != null; c = c.HNext)
{
if (c.Total > 4)
{
for (int i = 0; i < c.Total; i++)
{
CvPoint? p = Cv.GetSeqElem(c, i);
CvPoint conpt;
conpt.X = p.Value.X;
conpt.Y = p.Value.Y;
Cv.Circle(apcon, conpt, 3, CvColor.Black, -1);
}
}
}
for
문을 이용하여 코너를 검출합니다. apcon_seq
를 변수로 하여 검출합니다.
c
값이 null
값이 라면 멈추며, c.HNext
를 이용하여 다음 값으로 넘어갑니다.
if
문을 이용하여 코너점의 개수를 파악하여 4개보다 적으면 무시
하게 합니다.
화면상의 각 모서리도 하나의 물체(덩어리)이며 코너점으로 판단하게됩니다.
화면의 모서리 부분을 무시하기 위해 5개 이상의 코너점부터 검출합니다.
c
는 검출된 하나의 물체(덩어리)이며, 그때의 c.Total
이 그 물체(덩어리)에 포함된 코너점입니다.
다시 for
문을 이용하여 검출된 코너점들을 그려줍니다.
Cv.GetSeqElem()을 이용하여 해당 인덱스에 따라 시퀀스 요소에 대한 포인터를 반환합니다.
Cv.GetSeqElem(시퀀스, 인덱스)입니다.
conpt.X와
conpt.Y`에 받아온 포인터의 값을 저장합니다.
그 후, Cv.Circle()
을 이용하여 원을 그려 확인합니다.
출력 결과
No Change
ApproxPoly - 근사정확도 = 1
ApproxPoly - 시퀀스결정 = false
if - c.total > 3
공유하기


댓글 남기기