C# OpenCV 강좌 : 제 48강 - 윤곽 추적
윤곽 추적(Snake Image)

SnakeImage 함수를 이용하여 이미지나 영상의 윤곽을 추적합니다.
원본(Source, src)은 영상이나 이미지를 사용합니다.
-
영상 사용하기: [3강 바로가기][3강] -
이미지 사용하기: [4강 바로가기][4강]
메인 코드
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenCvSharp;
namespace Project
{
class OpenCV : IDisposable
{
IplImage snake;
public IplImage SnakeImage(IplImage src)
{
IplImage snake_calc = new IplImage(src.Size, BitDepth.U8, 1);
snake = new IplImage(src.Size, BitDepth.U8, 3);
Cv.CvtColor(src, snake_calc, ColorConversion.BgrToGray);
Cv.Threshold(snake_calc, snake_calc, 150, 255, ThresholdType.Binary);
Cv.Smooth(snake_calc, snake_calc, SmoothType.Gaussian, 9);
int contour_num = 2000;
CvPoint[] contour = new CvPoint[contour_num];
CvPoint center = new CvPoint(snake_calc.Width / 2, snake_calc.Height / 2);
for (int i = 0; i < contour.Length; i++)
{
contour[i].X = (int)(center.X * Math.Cos(2 * Math.PI * i / contour.Length) + center.X);
contour[i].Y = (int)(center.Y * Math.Sin(2 * Math.PI * i / contour.Length) + center.Y);
}
CvWindow window = null;
int k = 0;
while ( k < contour_num / 2)
{
k++;
window = new CvWindow("SnakeImage", WindowMode.StretchImage);
window.Resize(640, 480);
Cv.SnakeImage(snake_calc, contour, 0.50f, 0.40f, 0.30f, new CvSize(15, 15), new CvTermCriteria(1), true);
Cv.Copy(src, snake);
for (int i = 0; i < contour.Length - 1; i++)
{
Cv.Line(snake, contour[i], contour[i + 1], CvColor.Red, 5);
}
Cv.Line(snake, contour[contour.Length - 1], contour[0], CvColor.Red, 5);
window.Image = snake;
Application.DoEvents();
}
window.Close();
return snake;
}
public void Dispose()
{
if (snake != null) Cv.ReleaseImage(snake);
}
}
}세부 코드
IplImage snake_calc = new IplImage(src.Size, BitDepth.U8, 1);
snake = new IplImage(src.Size, BitDepth.U8, 3);계산에 사용할 snake_calc와 결과에 사용할 snake를 생성합니다.
Cv.CvtColor(src, snake_calc, ColorConversion.BgrToGray);
Cv.Threshold(snake_calc, snake_calc, 150, 255, ThresholdType.Binary);
Cv.Smooth(snake_calc, snake_calc, SmoothType.Gaussian, 9);snake_calc를 그레이스케일로 변환 후, 이진화를 적용합니다.
이 후 가우시안 블러를 적용하여 이미지를 단순화합니다.
int contour_num = 2000;
CvPoint[] contour = new CvPoint[contour_num];
CvPoint center = new CvPoint(snake_calc.Width / 2, snake_calc.Height / 2);윤곽의 개수로 사용할 contour_num을 생성합니다.
contour를 생성하여 contour_num의 개수만큼 생성합니다.
center를 생성하여 윤곽 추적을 위한 이미지의 중심점을 생성합니다.
for (int i = 0; i < contour.Length; i++)
{
contour[i].X = (int)(center.X * Math.Cos(2 * Math.PI * i / contour.Length) + center.X);
contour[i].Y = (int)(center.Y * Math.Sin(2 * Math.PI * i / contour.Length) + center.Y);
}for문을 사용하여 중심점을 기준으로 coutour_num 개수만큼 둘러싸게 합니다.
윤곽의 X 좌표와 Y 좌표를 저장합니다.
- Tip : 초기 윤곽은 중심점(center)을 기준으로 둥글게 생성됩니다.
CvWindow window = null;윤곽 추적을 보여줄 window를 생성합니다.
int k = 0;
while ( k < contour_num / 2)
{
k++;
...
}윤곽 추적을 위하여 contour_num의 절반만큼 반복합니다.
window = new CvWindow("SnakeImage", WindowMode.StretchImage);
window.Resize(640, 480);window를 생성하고 크기 모드를 StretchImage로 사용하며 크기를 적절하게 변경합니다.
Cv.SnakeImage(snake_calc, contour, 0.50f, 0.40f, 0.30f, new CvSize(15, 15), new CvTermCriteria(1), true);Cv.SnakeImage를 사용하여 윤곽을 추적합니다.
Cv.SnakeImage(이미지, 윤곽선, 알파, 베타, 감마, 이웃 크기, 종료 기준, 그라디언트 플래그)입니다.
-
알파: 연속성의 가중치입니다. -
베타: 곡률의 가중치입니다. -
감마: 이미지의 가중치입니다. -
이웃크기: 최솟값을 검색하는데 사용되는 모든 이웃 점의 크기입니다. -
종료 기준: 반복 알고리즘의 종료 기준입니다. 최대 반복 횟수를 의미합니다. -
그라디언트 플래그: 모든 이미지 픽셀에 대한 그래디언트 크기를 계산하고이를 에너지 필드로 간주 유/무 입니다.
Cv.Copy(src, snake);그려진 윤곽선을 지우고 새롭게 그리기 위하여 원본을 덧씌웁니다.
for (int i = 0; i < contour.Length - 1; i++)
{
Cv.Line(snake, contour[i], contour[i + 1], CvColor.Red, 5);
}
Cv.Line(snake, contour[contour.Length - 1], contour[0], CvColor.Red, 5);for문을 이용하여 윤곽점을 이어 윤곽선으로 그립니다.
for문에서는 첫 번째 윤곽점과 마지막 윤곽점을 잇지 못하므로 for문이 모두 반복된 후 남은 점을 잇습니다.
window.Image = snake;
Application.DoEvents();window에 윤곽 추적 결과를 표시합니다.
Application.DoEvents()를 사용하여 while문이 반복중에도 윈도우 창이 업데이트되도록 합니다.
- Tip : 네임스페이스에
using System.Windows.Forms;이 포함되어야 합니다.
window.Close();추적이 완료되면 window를 닫습니다.
출력 결과


공유하기
Kakao
Naver
Twitter
LinkedIn
Facebook
댓글 남기기