Main Content

이 번역 페이지는 최신 내용을 담고 있지 않습니다. 최신 내용을 영문으로 보려면 여기를 클릭하십시오.

영상에서 원형 객체를 검출하고 측정하기

이 예제에서는 영상에서 원 또는 원형 객체를 자동으로 검출하고 검출된 원을 시각화하는 방법을 보여줍니다.

1단계: 영상 불러오기

다양한 색의 둥근 플라스틱 칩의 영상을 읽어 들여서 표시합니다. 이 영상에는 검출할 원이 많다는 점 외에도, 원 검출 측면에서 흥미로운 점도 몇 가지 있습니다.

  1. 다양한 색의 칩이 있으며, 배경과의 대비도 다양합니다. 파란색과 빨간색 칩은 배경과 강하게 대비됩니다. 반면, 노란색 칩 중 일부는 배경과 그다지 대비되지 않습니다.

  2. 서로 겹쳐진 칩도 있고, 서로 가까이 있는 칩과 거의 닿는 칩도 있습니다. 객체 경계선 겹침과 객체 가림은 객체 검출을 까다롭게 만듭니다.

rgb = imread("coloredChips.png");
imshow(rgb)

2단계: 원을 찾기 위해 반지름 범위 구하기

drawline 함수를 사용하여 원의 적절한 반지름 범위를 구합니다. 칩의 대략적인 지름 위에 선을 그립니다.

d = drawline;

Figure contains an axes object. The axes object contains 2 objects of type image, images.roi.line.

선 ROI의 길이는 칩의 지름입니다. 일반적인 칩의 지름 범위는 40~50 픽셀입니다.

pos = d.Position;
diffPos = diff(pos);
diameter = hypot(diffPos(1),diffPos(2))
diameter = 45.4533

3단계: 원을 찾기 위한 첫 번째 시도

imfindcircles 함수는 반지름 범위를 사용하여 원을 검색합니다. 반지름 범위가 20~25 픽셀인 원을 검색합니다. 그 전에, 객체를 배경보다 더 밝게 할지 아니면 더 어둡게 할지 정해 두는 것이 좋습니다. 그 답을 찾기 위해, 이 영상의 회색조 버전을 표시하겠습니다.

gray_image = im2gray(rgb);
imshow(gray_image)

Figure contains an axes object. The axes object contains an object of type image.

배경이 상당히 밝고, 칩 대부분이 배경보다 더 어둡습니다. 그러나 기본적으로 imfindcircles는 배경보다 더 밝은 원형 객체를 찾습니다. 그러므로 어두운 원을 찾기 위해 imfindcircles에서 파라미터 "ObjectPolarity"를 "dark"로 설정합니다.

[centers,radii] = imfindcircles(rgb,[20 25],"ObjectPolarity","dark")
centers =

     []


radii =

     []

출력 인수 centersradii가 비어 있습니다. 이는 발견된 원이 없다는 뜻입니다. 이 현상은 자주 발생합니다. imfindcircles는 원 검출기이고, 다른 검출기와 마찬가지로 imfindcircles는 감도를 확인하는 내부 검출 임계값을 갖기 때문입니다. 간단히 말하면, 특정 (원) 검출이 유효할 수 있으려면 그 검출에서 검출기의 신뢰가 특정 수준보다 커야 합니다. imfindcircles에는 이 내부 임계값을 조정(결과적으로, 알고리즘의 감도 조정)하는 데 사용할 수 있는 파라미터 "Sensitivity"가 있습니다. "Sensitivity" 값을 높이면 검출 임계값이 더 낮게 설정되어 더 많은 원을 검출하게 됩니다. 이는 주택 보안 시스템에 사용되는 동작 감지기의 감도 조정과 비슷합니다.

4단계: 검출 감도 늘리기

다시 칩 영상으로 돌아와 보면, 디폴트 감도 수준에서 모든 원이 내부 임계값보다 낮을 수 있습니다. 원이 검출되지 않은 이유가 바로 이 때문입니다. 기본적으로 "Sensitivity"(0과 1 사이의 숫자)는 0.85로 설정되어 있습니다. "Sensitivity"를 0.9로 늘립니다.

[centers,radii] = imfindcircles(rgb,[20 25],"ObjectPolarity","dark", ...
    "Sensitivity",0.9)
centers = 8×2

  146.1895  198.5824
  328.8132  135.5883
  130.3134   43.8039
  175.2698  297.0583
  312.2831  192.3709
  327.1316  297.0077
  243.9893  166.4538
  271.5873  280.8920

radii = 8×1

   23.1604
   22.5710
   22.9576
   23.7356
   22.9551
   22.9995
   22.9055
   23.0298

이번에는 imfindcircles가 원을 몇 개(정확하게는 8개) 찾았습니다. centers에는 원의 중심의 위치가 들어 있고, radii에는 그 원의 추정 반지름이 들어 있습니다.

5단계: 영상에 원 그리기

함수 viscircles를 사용하여 영상에 원을 그릴 수 있습니다. imfindcircles의 출력 변수 centersradiiviscircles에 바로 전달할 수 있습니다.

imshow(rgb)
h = viscircles(centers,radii);

Figure contains an axes object. The axes object contains 3 objects of type line, image.

원의 중심의 위치가 정확한 것 같고, 해당 반지름도 실제 칩에 잘 맞는 것 같습니다. 그러나 아직도 상당히 많은 칩이 누락되었습니다. "Sensitivity"를 0.92로 더 늘려 봅니다.

[centers,radii] = imfindcircles(rgb,[20 25],"ObjectPolarity","dark", ...
    "Sensitivity",0.92);

length(centers)
ans = 16

"Sensitivity"를 늘려 훨씬 더 많은 원을 찾을 수 있습니다. 이 원들을 다시 영상에 플로팅합니다.

delete(h)  % Delete previously drawn circles
h = viscircles(centers,radii);

Figure contains an axes object. The axes object contains 3 objects of type line, image.

6단계: 원을 찾기 위해 두 번째 방법(2단계) 사용하기

이 결과가 더 좋아 보입니다. imfindcircles에는 원을 찾을 수 있는 방법이 두 가지 있습니다. 지금까지는 원을 검출하는 데 위상 코딩(phase coding)이라는 디폴트 방법을 사용했습니다. imfindcircles에서는 2단계(two-stage) 방법이라고 하는 또 다른 방법도 사용할 수 있습니다. 2단계 방법을 사용하여 결과를 표시합니다.

[centers,radii] = imfindcircles(rgb,[20 25],"ObjectPolarity","dark", ...
          "Sensitivity",0.92,"Method","twostage");

delete(h)
h = viscircles(centers,radii);

Figure contains an axes object. The axes object contains 3 objects of type line, image.

2단계 방법은 Sensitivity가 0.92일 때 더 많은 원을 검출했습니다. 대체로 이 두 방법은 장점이 서로 다르기 때문에 상호 보완적입니다. 위상 코딩 방법은 일반적으로 2단계 방법보다 속도가 빠르고 잡음에 조금 더 강합니다. 그러나 2단계 방법의 검출 개수와 동일하려면 "Sensitivity" 수준을 더 올려야 할 수도 있습니다. 예를 들어, "Sensitivity" 수준을 더 올리면 즉, 0.95로 올리면, 위상 코딩 방법도 같은 개수의 칩을 찾게 됩니다.

[centers,radii] = imfindcircles(rgb,[20 25],"ObjectPolarity","dark", ...
          "Sensitivity",0.95);

delete(h)
viscircles(centers,radii);

Figure contains an axes object. The axes object contains 3 objects of type line, image.

imfindcircles의 두 방법은 일부만 보이는(가린) 칩의 중심과 반지름을 정확하게 찾습니다.

7단계: 왜 아직도 일부 원이 누락되는 걸까요?

마지막 결과를 보면, 의아스럽게도 imfindcircles는 영상의 노란색 칩을 찾지 못합니다. 노란색 칩은 배경과 강한 대비를 이루지 않습니다. 실제로 노란색 칩은 배경과 명암이 상당히 유사한 것 같습니다. 가정한 대로, 노란색 칩이 배경보다 실제로 "더 어두울" 가능성은 없을까요? 확인하기 위해, 이 영상의 회색조 버전을 다시 표시합니다.

imshow(gray_image)

Figure contains an axes object. The axes object contains an object of type image.

8단계: 영상에서 "밝은" 원 찾기

노란색 칩은 배경과 비교하여 명암이 거의 같거나, 조금 더 밝을 수 있습니다. 따라서 노란색 칩을 검출하기 위해 "ObjectPolarity"를 "bright"로 변경합니다.

[centersBright,radiiBright] = imfindcircles(rgb,[20 25], ...
    "ObjectPolarity","bright","Sensitivity",0.92);

9단계: 서로 다른 색으로 "밝은" 원 그리기

viscircles에서 "Color" 파라미터를 변경하여, 서로 다른 색으로 밝은 원을 그립니다.

imshow(rgb)

hBright = viscircles(centersBright, radiiBright,"Color","b");

Figure contains an axes object. The axes object contains 3 objects of type line, image.

누락된 노란색 칩 중 세 개는 찾았지만, 한 개는 여전히 찾지 못하고 있습니다. 그 칩은 이 배경에서 다른 칩과 함께 두드러지지 않기 때문에 찾기 힘듭니다.

10단계: "EdgeThreshold" 값 낮추기

imfindcircles에는 "EdgeThreshold"라는 또 다른 파라미터가 있습니다. 여기서 유용할 수 있는 파라미터입니다. imfindcircles는 원을 찾을 때 영상의 경계 픽셀만 사용합니다. 이러한 경계 픽셀은 기본적으로 기울기 값이 큰 픽셀입니다. 픽셀을 경계 픽셀로 간주하여 계산에 넣기 전에, "EdgeThreshold" 파라미터를 사용하여 해당 픽셀의 기울기 값을 얼마나 높일지 조정할 수 있습니다. 이 파라미터에 높은 값(1에 근접)을 사용하면 강한 경계(기울기 값이 더 높음)만 포함할 수 있는 반면, 낮은 값(0에 근접)은 좀 더 관대하여 약한 경계(기울기 값이 더 낮음)도 계산에 포함합니다. 누락된 노란색 칩의 경우, 대비가 낮아 (칩의 원주에서) 경계선 픽셀 중 일부의 기울기 값이 낮을 것입니다. 따라서 노란색 칩의 경계 픽셀 대부분을 계산에 넣으려면 "EdgeThreshold" 파라미터를 낮추어야 합니다.

[centersBright,radiiBright,metricBright] = imfindcircles(rgb,[20 25], ...
    "ObjectPolarity","bright","Sensitivity",0.92,"EdgeThreshold",0.1);

delete(hBright)
hBright = viscircles(centersBright, radiiBright,"Color","b");

Figure contains an axes object. The axes object contains 3 objects of type line, image.

11단계: "어두운" 원과 "밝은" 원을 함께 그리기

이제 imfindcircles는 모든 노란색 칩과 녹색 칩도 찾았습니다. 이러한 칩은 파란색으로 그리고, 이전에 찾은 다른 칩("ObjectPolarity"가 "dark"로 설정됨)은 빨간색으로 함께 그립니다.

h = viscircles(centers,radii);

Figure contains an axes object. The axes object contains 5 objects of type line, image.

모든 원을 검출했습니다. 마지막으로 한 가지 유의할 점을 덧붙이자면, 검출 시 파라미터를 좀 더 공격적으로 변경하면 원을 더 많이 찾을지 모르지만, 원을 잘못 찾을 가능성도 늘어납니다. 정확하게 찾을 수 있는 원(검출률)이 있으면, 그와 함께 잘못 찾는 원(오검출률)도 있는 법입니다.

즐겁게 원을 찾으시길 바랍니다!

참고 항목

|

관련 항목