상위 목록: 하위 목록: 작성 날짜: 읽는 데 15 분 소요

내부 채우기 (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은 원본을 복사한 이미지입니다.

fillsrc를 복제하여 같은 이미지로 변경합니다.


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키가 눌러졌을 때, 종료합니다.



출력 결과

댓글 남기기