Hole Filling

1 개요

Threshold 를 사용하여 Hole 영역을 규정하고, Filling Method 로 해당 영역을 채우는 알고리즘

2 알고리즘 상세 설명

Source Image Parameters Destination Image
Source Image Hole
Single
(Greater Equal)
(90)
Ignore Boundary Hole
50 <= Area <= 102
Destination Image
Fig. Source and Destination images of Hole Filling.

정의한 threshold 를 통과한 픽셀은 threshold pass target 값 설정에 의해 hole 또는 object(non-hole) 로 규정되며 두 영역은 서로 상호 배타적입니다.

만일 이미지 경계 부분에 맞닿은 hole 이 있다고 가정하면, 해당 영역은 background 와 사실상 구분이 불가능 하게 됩니다. 따라서 이런 케이스를 hole 로 처리하고 싶지 않을 수 있으므로 ignore boundary hole 옵션이 존재합니다. 이 옵션이 활성화 된 경우, 이미지 경계와 맞닿은 영역의 hole 들을 모두 object 플래그로 설정합니다.
해당 알고리즘에서는 hole 영역으로 감싸인 영역은 hole 으로 처리합니다. 따라서 background 가 존재하는 이미지의 경우, ignore boundary hole 옵션을 활성화 하는 것이 권장됩니다.

Threshold condition 및 logical condition of channels 연산자들에 not 을 취하고 threshold pass Target 을 뒤집으면 개념적으로 동일한 의미를 지니지만, hole 영역으로 감싸인 영역은 object 로 처리되지 않는 점 및 비선형적 옵션인 ignore boundar holes 과 hole area 크기 제한으로 인하여 일반적으로 두 경우가 같은 출력을 보이지는 않습니다.

Hole 영역을 찾은 이후에는 해당 영역을 설정된 filling method 를 사용하여 채우게 됩니다. 기본적으로 Harmonic Interpolation 알고리즘을 내부에서 호출하여 채워지며, 마스킹을 원하는 경우 constant 로 설정하여 원하는 값으로 채울 수 있습니다.

Source ImageSource Image with Hole Figure
Source ImageSource Image
Fig. Source image view after execution with show hole figure enabled.

GUI 상에서는 Show Hole Figure 옵션이 존재하며, 활성화 시 figure 객체 생성이 활성화 되고 Source 이미지 뷰의 레이어에 일시적으로 그려집니다. 코드 상에서는 figure 객체 생성 활성화 후 figure 를 얻어 원하는 뷰의 레이어에 그릴 수 있습니다.

3 파라미터 설정 및 사용 방법

넓이 및 위치 Threshold 설정

색상 도메인 Threshold 설정

Filling Method 설정

Figure 획득

4 예제 코드

CHoleFilling hf;

CFLImage fliSourceImage;
CFLImage fliDestinationImage;
CMultiVar<uint64_t> mvThresholdCondition;
mvThresholdCondition.PushBack((uint64_t)ELogicalCondition_GreaterEqual);
mvThresholdCondition.PushBack((uint64_t)ELogicalCondition_GreaterEqual);
mvThresholdCondition.PushBack((uint64_t)ELogicalCondition_GreaterEqual);
CMultiVar<uint64_t> mvThresholdValue;
mvThresholdValue.PushBack(170);
mvThresholdValue.PushBack(230);
mvThresholdValue.PushBack(240);

hf.SetSourceImage(fliSourceImage);
hf.SetDestinationImage(fliDestinationImage);
hf.SetMinimumHoleArea(500);
hf.SetMaximumHoleArea(999999);
hf.EnableIgnoreBoundaryHole(true);
hf.SetThresholdPassTarget(CHoleFilling::EThresholdPassTarget_Object);
hf.SetThresholdMode(EThresholdMode_Single);
hf.SetThresholdCondition(EThresholdIndex_First, mvThresholdCondition);
hf.SetThresholdValue(EThresholdIndex_First, mvThresholdValue);
hf.SetFillingMethod(CHoleFilling::EFillingMethod_HarmonicInterpolation);
hf.SetPrecision(0.001);
hf.SetMaxIteration(100);

hf.Execute();

do 
{
    // do not delete this figure pointer
    const CFLFigure* pFlfOriginal = hf.GetSelectedPageFigureObject();

    if(!pFlfOriginal)
        break;

    CFLBase* pFlbDuplicated = pFlfOriginal->DuplicateObject();

    if(!pFlbDuplicated)
        break;

    CFLFigure* pFlfDuplicated = dynamic_cast<CFLFigure*>(pFlbDuplicated);

    if(!pFlfDuplicated)
    {
        delete pFlbDuplicated;
        break;
    }

    CGUIViewImage* pSrcView;
    CGUIViewImageLayer* pSrcViewLayer = pSrcView->GetLayer(0);
    pSrcViewLayer->DrawFigureImage(pFlfDuplicated, 0xffff00);
    delete pFlfDuplicated;
}
while(false);
CHoleFilling hf;

CFLImage fliSourceImage;
CFLImage fliDestinationImage;
CMultiVar<uint64_t> mvThresholdCondition;
mvThresholdCondition.PushBack((uint64_t)ELogicalCondition_GreaterEqual);
mvThresholdCondition.PushBack((uint64_t)ELogicalCondition_GreaterEqual);
mvThresholdCondition.PushBack((uint64_t)ELogicalCondition_GreaterEqual);
CMultiVar<uint64_t> mvThresholdValue;
mvThresholdValue.PushBack(170);
mvThresholdValue.PushBack(230);
mvThresholdValue.PushBack(240);

hf.SetSourceImage(fliSourceImage);
hf.SetDestinationImage(fliDestinationImage);
hf.SetMinimumHoleArea(500);
hf.SetMaximumHoleArea(999999);
hf.EnableIgnoreBoundaryHole(true);
hf.SetThresholdPassTarget(CHoleFilling::EThresholdPassTarget_Object);
hf.SetThresholdMode(EThresholdMode_Single);
hf.SetThresholdCondition(EThresholdIndex_First, mvThresholdCondition);
hf.SetThresholdValue(EThresholdIndex_First, mvThresholdValue);
hf.SetFillingMethod(CHoleFilling::EFillingMethod_HarmonicInterpolation);
hf.SetPrecision(0.001);
hf.SetMaxIteration(100);

hf.Execute();

do 
{
    // do not delete this figure pointer
    const CFLFigure* pFlfOriginal = hf.GetSelectedPageFigureObject();

    if(!pFlfOriginal)
        break;

    CFLBase* pFlbDuplicated = pFlfOriginal->DuplicateObject();

    if(!pFlbDuplicated)
        break;

    CFLFigure* pFlfDuplicated = dynamic_cast<CFLFigure*>(pFlbDuplicated);

    if(!pFlfDuplicated)
    {
        delete pFlbDuplicated;
        break;
    }

    CGUIViewImage* pSrcView;
    CGUIViewImageLayer* pSrcViewLayer = pSrcView->GetLayer(0);
    pSrcViewLayer->DrawFigureImage(pFlfDuplicated, 0xffff00);
    delete pFlfDuplicated;
}
while(false);
CHoleFilling hf = new CHoleFilling();

CFLImage fliSourceImage = new CFLImage();
CFLImage fliDestinationImage = new CFLImage();
CMultiVar<UInt64> mvThresholdCondition = new CMultiVar<UInt64>();
mvThresholdCondition.PushBack((UInt64)ELogicalCondition.GreaterEqual);
mvThresholdCondition.PushBack((UInt64)ELogicalCondition.GreaterEqual);
mvThresholdCondition.PushBack((UInt64)ELogicalCondition.GreaterEqual);
CMultiVar<UInt64> mvThresholdValue = new CMultiVar<UInt64>();
mvThresholdValue.PushBack(170);
mvThresholdValue.PushBack(230);
mvThresholdValue.PushBack(240);

hf.SetSourceImage(ref fliSourceImage);
hf.SetDestinationImage(ref fliDestinationImage);
hf.SetMinimumHoleArea(500);
hf.SetMaximumHoleArea(999999);
hf.EnableIgnoreBoundaryHole(true);
hf.SetThresholdPassTarget(CHoleFilling.EThresholdPassTarget.Object);
hf.SetThresholdMode(EThresholdMode.Single);
hf.SetThresholdCondition(EThresholdIndex.First, mvThresholdCondition);
hf.SetThresholdValue(EThresholdIndex.First, mvThresholdValue);
hf.SetFillingMethod(CHoleFilling.EFillingMethod.HarmonicInterpolation);
hf.SetPrecision(0.001);
hf.SetMaxIteration(100);

hf.Execute();

do 
{
    CFLFigure pFlfOriginal = hf.GetSelectedPageFigureObject();

    CGUIViewImage pSrcView = new CGUIViewImage();
    CGUIViewImageLayer pSrcViewLayer = pSrcView->GetLayer(0);
    pSrcViewLayer.DrawFigureImage(pFlfOriginal, 0xffff00);
}
while(false);

5 기타 사항

Supported Feature

Supported Format