C# OpenCV 강좌 : 제 20강 - 윤곽선 검출
윤곽선(Contour)
영상이나 이미지의 윤곽선(컨투어)을 검출
하기 위해 사용합니다.
영상이나 이미지에서 외곽과 내곽
의 윤곽선(컨투어)을 검출 할 수 있습니다.
원본(Source, src)
은 영상이나 이미지를 사용합니다.
FindContours
클래스 코드
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 con;
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 Contour(IplImage src)
{
con = new IplImage(src.Size, BitDepth.U8, 3);
bin = new IplImage(src.Size, BitDepth.U8, 1);
Cv.Copy(src, con);
bin = this.Binary(src);
CvMemStorage Storage = new CvMemStorage();
CvSeq<CvPoint> contours;
Cv.FindContours(bin, Storage, out contours, CvContour.SizeOf, ContourRetrieval.List, ContourChain.ApproxNone);
Cv.DrawContours(con, contours, CvColor.Yellow, CvColor.Red, 1, 4, LineType.AntiAlias);
Cv.ClearSeq(contours);
Cv.ReleaseMemStorage(Storage);
return con;
}
public void Dispose()
{
if (bin != null) Cv.ReleaseImage(bin);
if (con != null) Cv.ReleaseImage(con);
}
}
}
세부 코드
con = new IplImage(src.Size, BitDepth.U8, 3);
bin = new IplImage(src.Size, BitDepth.U8, 1);
컨투어는 8Bit 단일 채널
, Binary
영상으로 검출합니다.
출력할 이미지인 con
과 검색할 이미지인 bin
을 만듭니다.
Cv.Copy(src, con);
bin = this.Binary(src);
con
과 bin
을 만들고 이미지를 복사하고 덮어씌웁니다.
CvMemStorage Storage = new CvMemStorage();
CvSeq<CvPoint> contours;
Storage
는 윤곽선(컨투어)의 메모리를 저장
합니다.
점의 좌표들이 저장됩니다.
contours
는 윤곽선(컨투어)의 정보
와 정수의 2D 좌표
를 저장합니다.
Cv.FindContours(bin, Storage, out contours, CvContour.SizeOf, ContourRetrieval.List, ContourChain.ApproxNone);
Cv.FindContours()
를 이용하여 모든 윤곽선(컨투어)를 검색
합니다.
Cv,FindContours(이진화 이미지, 메모리 저장소, 윤곽선 저장, 자료구조의 크기, 검색 방법, 근사화 방법)
을 의미합니다.
-
검색 방법 (ContourRetrieval.*)
-
ContourRetrieval.CComp
: 모든 윤곽선을 검색하여 2 단계 계층 구조로 구성합니다. 최상위 레벨은 구성 요소의 외곽(외부) 경계이고, 두 번째 레벨은 내곽(홀)의 경계입니다. -
ContourRetrieval.External
: 외곽 윤곽선만 검출합니다. -
ContourRetrieval.List
: 모든 윤곽선을 검출하여 list에 넣습니다. -
ContourRetrieval.Tree
: 모든 윤곽선을 검출하여 Tree계층 구조로 만듭니다.
-
-
근사화 방법(ContourChain.*)
-
ContourChain.ApproxNone
: 윤곽점들의 모든 점을 반환합니다. -
ContourChain.ApproxSimple
: 윤곽점들 단순화 수평, 수직 및 대각선 요소를 압축하고 끝점만 남겨 둡니다. -
ContourChain.Code
: 프리먼 체인 코드에서의 윤곽선으로 적용합니다. -
ContourChain.ApproxTC89KCOS
,ContourChain.ApproxTC89L1
: Teh-chin 알고리즘 적용합니다. -
ContourChain.LinkRuns
: 하나의 수평 세그먼트를 연결하여 완전히 다른 윤곽선 검색 알고리즘을 사용합니다.
-
Cv.DrawContours(con, contours, CvColor.Yellow, CvColor.Red, 1, 4, LineType.AntiAlias);
Cv.DrawContours()
를 이용하여 컨투어를 그립니다.
Cv.DrawContours(결과, 윤곽선, 외곽윤곽색상, 내곽윤곽색상, 최대레벨, 두께, 선형타입)
입니다.
최대레벨은 0일 경우 지정된 윤곽선만 그리며, 1일 경우 윤곽선과 중첩 된 모든 윤곽선을 그립니다.
2일 경우 윤곽선과 중첩된 윤곽선, 중첩에 중첩된 모든 윤곽선을 그립니다.
Cv.ClearSeq(contours);
Cv.ReleaseMemStorage(Storage);
Cv.ClearSeq()
와 Cv.ReleaseMemStorage()
를 이용하여 초기화 및 메모리를 해제합니다.
CvContourScanner
클래스 코드
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 con;
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 Contour(IplImage src)
{
con = new IplImage(src.Size, BitDepth.U8, 3);
bin = new IplImage(src.Size, BitDepth.U8, 1);
Cv.Copy(src, con);
bin = this.Binary(src);
CvMemStorage Storage = new CvMemStorage();
CvSeq<CvPoint> contours;
CvContourScanner scanner = Cv.StartFindContours(bin, Storage, CvContour.SizeOf, ContourRetrieval.List, ContourChain.ApproxNone);
// #1
while(true)
{
contours = Cv.FindNextContour(scanner);
if (contours == null) break;
else
{
Cv.DrawContours(con, contours, CvColor.Yellow, CvColor.Red, 1, 4, LineType.AntiAlias);
}
}
Cv.EndFindContours(scanner);
// #2
//foreach (CvSeq<CvPoint> c in scanner)
//{
// con.DrawContours(c, CvColor.Yellow, CvColor.Red, 1, 4, LineType.AntiAlias);
//}
//Cv.ClearSeq(contours);
Cv.ReleaseMemStorage(Storage);
return con;
}
public void Dispose()
{
if (bin != null) Cv.ReleaseImage(bin);
if (con != null) Cv.ReleaseImage(con);
}
}
}
세부 코드 (1)
CvContourScanner scanner = Cv.StartFindContours(bin, Storage, CvContour.SizeOf, ContourRetrieval.List, ContourChain.ApproxNone);
Cv.StartFindContours()
는 하나의 윤곽선(컨투어)
를 찾는데 사용합니다.
Cv.StartFindContours(이진화 이미지, 메모리 저장소, 객체 할당, 검색 방법, 근사화 방법)
을 의미합니다.
CvContourScanner
는 시퀀스의 정보를 가지고 있습니다.
while(true)
{
contours = Cv.FindNextContour(scanner);
if (contours == null) break;
else
{
Cv.DrawContours(con, contours, CvColor.Yellow, CvColor.Red, 1, 4, LineType.AntiAlias);
}
}
Cv.EndFindContours(scanner);
while(true)
를 이용하여 한 개씩 찾아 모든 컨투어를 표시합니다.
contours = Cv.FindNextContour(scanner)
는 순차적으로 검사합니다. 검사할 컨투어가 없는 경우 null
값을 반환합니다.
이를 이용하여 if(contours == null)
이 될 때 while
문을 종료합니다. 그렇지 않으면 Cv.DrawContours()
를 이용하여 컨투어를 하나씩 그려냅니다.
Cv.EndFindContours()
는 스캐닝이 끝나면 스캐너를 완료상태로 만듭니다. 시퀀스의 첫 원소에 대한 포인터를 반환합니다.
세부 코드 (2)
foreach (CvSeq<CvPoint> cont in scanner)
{
con.DrawContours(cont, CvColor.Yellow, CvColor.Red, 1, 4, LineType.AntiAlias);
}
Cv.ClearSeq(contours);
foreach
문을 이용하여 scanner
로 찾은 모든 컨투어를 그려주는 방법입니다.
3 가지의 방법을 통하여 모든 컨투어 또는 일부 컨투어만 검출 할 수 있습니다.
- Tip :
if
,for
,배열
등을 이용하여일부 컨투어만을 검출
할 수 있습니다.
출력 결과
공유하기


댓글 남기기