C# OpenCV 강좌 : 제 61강 - 내부 채우기
내부 채우기 (Flood Fill)
영상이나 이미지에서 지정된 색으로 연결된 객체의 내부
를 채우는데 사용합니다.
원본(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 fill;
public IplImage FloodFill(IplImage src)
{
fill = new IplImage(src.Size, BitDepth.U8, 3);
fill = src.Clone();
CvWindow win = new CvWindow("Window", WindowMode.StretchImage, fill);
CvPoint Pt = new CvPoint(-1, -1);
CvConnectedComp Comp = new CvConnectedComp();
win.OnMouseCallback += delegate (MouseEvent eve, int x, int y, MouseEvent flag)
{
if (eve == MouseEvent.LButtonDown)
{
Pt = new CvPoint(x, y);
Cv.FloodFill(fill, Pt, CvColor.Black, Cv.ScalarAll(50), Cv.ScalarAll(50), out Comp, FloodFillFlag.Link8);
win.ShowImage(fill);
Console.WriteLine(Comp.Area);
}
else if (eve == MouseEvent.RButtonDown)
{
Pt = new CvPoint(x, y);
Cv.FloodFill(fill, Pt, CvColor.White, Cv.ScalarAll(50), Cv.ScalarAll(50), out Comp, FloodFillFlag.Link8);
win.ShowImage(fill);
Console.WriteLine(Comp.Area);
}
};
while(true)
{
int key = Cv.WaitKey(0);
if (key == 'r')
{
fill = src.Clone();
win.ShowImage(fill);
}
else if(key == 'q')
{
Cv.DestroyAllWindows();
break;
}
}
return fill;
}
public void Dispose()
{
if (fill != null) Cv.ReleaseImage(fill);
}
}
}
세부 코드
fill = new IplImage(src.Size, BitDepth.U8, 3);
fill = src.Clone();
fill
은 원본을 복사한 이미지입니다.
fill
에 src
를 복제하여 같은 이미지로 변경합니다.
CvWindow win = new CvWindow("Window", WindowMode.StretchImage, fill);
CvPoint Pt = new CvPoint(-1, -1);
CvConnectedComp Comp = new CvConnectedComp();
윈도우 창 win
을 생성하고 초기 이미지를 fill
로 사용합니다.
마우스 포인터의 위치로 사용할 Pt
를 -1, -1
의 좌표로 초기화합니다.
함수를 구조화하기위한 포인터인 Comp
를 생성합니다.
- Tip :
Comp
에 내부 채우기를 실행했을 때 생성되는 정보가 담겨있습니다.
win.OnMouseCallback += delegate (MouseEvent eve, int x, int y, MouseEvent flag)
{
if (eve == MouseEvent.LButtonDown)
{
...
}
else if (eve == MouseEvent.RButtonDown)
{
...
}
};
마우스 콜백 이벤트
를 delegate
형식으로 적용하여 클래스
내부에서도 함수가 작동하게 생성합니다.
if (eve == MouseEvent.LButtonDown)
{
Pt = new CvPoint(x, y);
Cv.FloodFill(fill, Pt, CvColor.Black, Cv.ScalarAll(50), Cv.ScalarAll(50), out Comp, FloodFillFlag.Link8);
win.ShowImage(fill);
Console.WriteLine(Comp.Area);
}
else if (eve == MouseEvent.RButtonDown)
{
Pt = new CvPoint(x, y);
Cv.FloodFill(fill, Pt, CvColor.White, Cv.ScalarAll(50), Cv.ScalarAll(50), out Comp, FloodFillFlag.Link8);
win.ShowImage(fill);
Console.WriteLine(Comp.Area);
}
Pt
에 현재 마우스 좌표를 저장합니다.
Cv.FloodFill()
를 이용하여 내부 채우기를 실행합니다. Cv.FloodFill(계산 이미지, 내부 채우기 색상, 하한 값, 상한 값, 연결 요소, 연결성)
입니다.
하한 값
은 Pt
위치에서의 (해당 색상 값 - 하한 값)의 색상까지는 같은 색상으로 간주합니다.
상한 값
은 Pt
위치에서의 (해당 색상 값 + 상한 값)의 색상까지는 같은 색상으로 간주합니다.
연결 요소
는 내부 채우기를 실행하였을 때의 정보가 담겨있습니다.
연결성
은 픽셀의 어떠한 이웃 값이 고려될지를 설정합니다.
FloodFillFlag.*
Link4
: 이웃한 4 픽셀을 고려합니다.Link8
: 이웃한 8 픽셀을 고려합니다.FixedRange
: 시드 픽셀간의 차이를 고려합니다.MaskOnly
: 이미지를 변경하지 않고, 마스크를 채웁니다.
- Tip :
마스크
의 매개변수는연결성
매개변수 이후에 쉼표 (,)를 추가하여 값을 할당할 수 있습니다.
while(true)
{
int key = Cv.WaitKey(0);
if (key == 'r')
{
fill = src.Clone();
win.ShowImage(fill);
}
else if(key == 'q')
{
Cv.DestroyAllWindows();
break;
}
}
키 이벤트
를 사용하여 r
키가 눌러졌을 때, 이미지를 초기화하며 q
키가 눌러졌을 때, 종료합니다.
출력 결과
공유하기


댓글 남기기