5.27. 원과 사각형 찾기¶
선과 선분은 캡처한 프레임 안의 직선 에지를 다루지만, 카메라가 찾는 현실 세계의 많은 특징은 직선이 아닙니다. 책상 위에 놓인 동전은 원 입니다. 인쇄된 레이블, 포스트잇, 비스듬히 본 상자의 윗면은 사각형 입니다. image 모듈은 각각에 대해 전용 검출기를 제공합니다. 원을 찾는 Hough 방식 탐색과 AprilTag에서 유래한 사변형 탐색이 그것입니다.
두 메서드 모두 선 검출기와 동일한 틀을 따릅니다. threshold 는 검출에 필요한 투표 수를 제어하고, roi 는 탐색 범위를 좁히며, 반환되는 객체는 위치와 신뢰도 크기를 모두 담고 있습니다. 다만 매개변수 공간과 적절한 기본값이 충분히 달라서 별도로 설명할 가치가 있습니다.
5.27.1. Hough 원¶
find_circles() 는 Hough 변환의 원형 변형을 실행합니다. Sobel 전처리 단계에서 나온 각 에지 픽셀은 자신을 지날 수 있는 모든 원에 투표하며, 충분한 투표를 모은 원이 반환됩니다.
circles = img.find_circles(threshold=3500,
x_margin=10, y_margin=10, r_margin=10,
r_min=10, r_max=80, r_step=2)
for c in circles:
img.draw_circle((c.x, c.y, c.r), color=(255, 0, 0))
threshold 는 후보 원을 따라 누적된 Sobel 에지 크기의 최소 합입니다. 큰 원은 더 많은 픽셀을 지나므로 통과하려면 더 높은 임계값이 필요합니다. 반경 20픽셀 동전을 찾는 값은 반경 100픽셀 에지 주변의 노이즈에도 반응하고, 반대로 큰 동전에 맞춘 값은 작은 동전을 놓칩니다. 대상 반경 범위를 알고 있다면 적절한 임계값은 둘레에 비례하여 정해집니다. 대략 threshold = 50 * 2 * pi * r 정도가 합리적인 출발점이며, 적절한 값은 짧은 튜닝 과정을 거쳐 따라옵니다.
r_min, r_max, r_step 은 반경 탐색 을 설정합니다. 경계가 없으면 검출기는 몇 픽셀부터 이미지 폭의 절반까지 모든 반경을 탐색하게 되는데, 이는 느릴 뿐만 아니라 오검출을 부르는 지름길입니다. r_min 과 r_max 를 예상 대상 크기 주변으로 넉넉한 여유를 두고 설정하면(예: 약 20픽셀로 알려진 동전에 대해 r_min=15, r_max=25) 작업량이 크게 줄고 투표의 신호 대 잡음비가 개선됩니다. r_step 은 탐색의 세밀함을 제어합니다. 단계가 크면 더 빠르게 실행되지만 실제 반경이 샘플링된 두 값 사이에 있는 원을 놓칠 수 있습니다. 기본값 r_step=2 는 합리적인 절충안입니다.
x_margin, y_margin, r_margin 은 인접한 검출들의 병합 을 제어하는데, 이는 선 검출에서 theta_margin 과 rho_margin 이 하는 역할과 같습니다. 이미지 안의 단일 물리적 원은 중심과 반경이 몇 픽셀 이내로 일치하는 후보 원들의 군집에 투표합니다. 마진은 결과 목록이 만들어지기 전에 각 군집을 그 정점으로 합칩니다. 마진이 크면 더 적고 더 신뢰도 높은 검출이 반환되고, 마진이 작으면 거의 중복일 수 있는 검출이 더 많이 반환됩니다.
x_stride 와 y_stride 는 투표 스캔의 보폭을 정하며, 다른 검출기에서와 같은 방식으로 동작합니다. 기본값 2 와 1 은 대부분의 이미지에 적합합니다. 큰 원이 들어 있다고 알려진 이미지에서는 둘 다 4 로 올리는 것이 표준적인 속도 절충 방법입니다.
반환되는 각 Circle 은 x, y, r (중심과 반경)과 magnitude (투표 총합, 정렬이나 필터링을 위한 신뢰도 점수로 유용함)를 담습니다. 검출 결과를 프레임에 다시 그리는 것은 한 번의 호출로 끝납니다. draw_circle() 은 (x, y, r) 3-튜플을 받으며, 이는 결과에서 곧바로 (c.x, c.y, c.r) 로 얻을 수 있습니다.
5.27.2. 사각형¶
find_rects() 는 AprilTag 파이프라인에서 사변형 검출기를 빌려 옵니다. 태그 주위의 검은 사각형을 찾는 바로 그 루틴이 범용 사각형 탐색기로 단독 제공되는 것입니다.
rects = img.find_rects(threshold=12000)
for r in rects:
img.draw_rectangle(r.rect, color=(0, 255, 0))
for corner in r.corners:
img.draw_circle((corner[0], corner[1], 4),
color=(0, 255, 0))
threshold 는 사각형 둘레를 따라 누적된 에지 크기의 최소 합입니다. 조명이 좋은 프레임에서 흰 바탕에 검게 인쇄된 사각형은 10000 을 쉽게 넘깁니다. 질감 있는 배경 위의 희미한 사각형은 2000 까지 낮춰야 할 수도 있는데, 이는 민감도를 위해 오검출을 감수하는 절충입니다. 원 검출기와 마찬가지로, 적절한 값은 대상을 화면에 두고 빠르게 튜닝하는 과정을 거쳐 정해집니다.
이 검출기는 투영적 입니다. 즉 변이 직선이지만 반드시 평행하거나 축에 정렬되어 있을 필요는 없는 사변형을 찾습니다. 비스듬히 본 레이블은 이미지에서 사다리꼴처럼 보이며, 사각형 검출기는 이를 올바르게 찾습니다. 축에 정렬된 사각형은 네 모서리가 우연히 직각 상자를 이루는 퇴화된 경우일 뿐입니다. roi 는 탐색 범위를 제한하며, 나머지 키워드 인자는 AprilTag 파이프라인의 기본값을 그대로 따르고 거의 튜닝할 필요가 없습니다.
반환되는 각 Rect 는 축에 정렬된 경계 상자, 즉 x, y, w, h 와 draw_rectangle() 이 기대하는 rect 4-튜플을 담으며, 그리고 검출된 네 모서리를 corners 로 담습니다. 경계 상자는 애플리케이션이 대략적인 위치와 크기를 파악하는 데 사용하고, 모서리는 투영적 사변형 자체를 기술합니다. 카메라가 평평한 대상을 비스듬히 보고 있고 애플리케이션이 키스톤 왜곡을 되돌려야 할 때(레이블의 텍스트를 읽거나 평평한 부분에서 색상을 샘플링할 때), 모서리는 corners= 키워드와 함께 rotation_corr() 에 직접 입력되며(렌즈 및 원근 보정 참고), 그 출력은 다음 분석 단계에 바로 쓸 수 있는 보정된 사각형입니다.
경고
이 검출기는 AprilTag 파이프라인이 필요로 하는 것, 즉 흰 종이 위의 검은 태그 윤곽처럼 강하고 대비가 높은 경계를 가진 사변형에 맞춰져 있기 때문에, 모든 사각형을 찾아내는 검출기가 아닙니다. 대비가 약하거나 에지에 질감이 있거나 주변이 복잡한 사각형은 아예 검출되지 않을 수 있습니다. 얼마나 잘 동작하는지는 상황에 따라 다릅니다. 이를 중심으로 파이프라인을 구축하기 전에 실제 대상으로 일찍 테스트해 보세요.
5.27.3. 검출기가 잘못 동작할 때¶
특히 원은 입력에 대한 사전 필터 로 효과를 봅니다. 노이즈가 많은 프레임은 산발적인 에지 픽셀을 많이 만들어내고 이들이 모두 투표하므로, 결과로 나오는 Hough 공간에는 병합기가 분리하기 어려운 넓고 흐릿한 정점들이 생깁니다. find_circles() 앞에 gaussian() 이나 mean() 단계를 두면 노이즈가 매끄럽게 제거되고 실제 에지는 그대로 남습니다. 검출기는 더 적은 시간에 더 깔끔한 정점을 반환합니다.
사각형의 경우 흔한 실패 모드는 반대입니다. 사각형과 배경 사이의 대비가 낮으면 에지 크기 합이 threshold 를 결코 넘지 못합니다. histeq() 단계로 밝기 범위를 0부터 255까지 전체로 재분배하면 검출기가 필요로 하는 대비가 복원됩니다. (대비는 이미지 어딘가에는 존재해야 합니다. 히스토그램 평활화는 이미 존재하는 것을 증폭할 수 있을 뿐입니다.)