허프 변환을 응용하여 원을 검출할 수 있다.
직선 검출과 같이 원의 방정식을 파라미터 좌표평면에 표현하면 3차원 축적 평면이 되므로 연산속도가 너무 오래 걸리게 된다.
속도를 더 빠르기 위해 제안된 방법이 Hough gradient method 이다.
Hough gradient method
원에서 검출된 에지의 원주 점의 정보를 이용한다. 원 에지 픽셀에서 그래디언트를 계산한다.
그래디언트 크기 방향으로 직선을 그리면서 값을 누적시킨다. 그래디언트 크기는 원의 중심을 향하므로 직선은 원의 중심에서 모이게 된다.
원의 중심을 찾은 후 반지름을 찾고, 원의 중심에서 반지름을 점점 키워가면서 원주와 만나는지를 확인한다.
단점은 여러 개의 동심원을 검출 못하고 가장 작은 원 하나만 검출한다.
✔︎ 허프 변환 원 검출 함수 - cv2.HoughCircles
circles = cv2.HoughCircles(image, method, dp, minDist, circles=None,
param1=None, param2=None, minRadius=None, maxRadius=None)
- image : 입력 영상. (에지 영상이 아닌 일반 영상)
- method : OpenCV 4.2 이하에서는 cv2.HOUGH_GRADIENT만 지정 가능
- dp : 입력 영상과 축적 배열의 크기 비율. 1이면 동일 크기. 2이면 축적 배열의 가로, 세로 크기가 입력 영상의 반.
- minDist : 검출된 원 중심점들의 최소 거리
- circles : (cx, cy, r) 정보를 담은 numpy.ndarray.
shape=(1, N, 3), dtype=np.float32 - param1 : Canny 에지 검출기의 높은 임계값
- param2 : 축적 배열에서 원 검출을 위한 임계값
- minRadius, maxRadius : 검출할 원의 최소, 최대 반지름
허프 변환 원 검출 함수는 직선 검출 함수와 다르게 입력 영상에 에지 영상이 아닌 일반 영상을 입력해준다.
에지의 방향 성분을 이용해야 하는데 에지 영상은 방향 정보가 제공되지 않는다. 따라서 함수 내부에서 캐니 에지를 진행하여 방향 성분을 추출한다.
method는 cv2.Hough_GRADIENT_ALT가 기존 방법보다 더 정확한 원을 검출할 수 있습니다. 또한 기존 방법은 파라미터의 영향을 많이 받았지만 cv2.Hough_GRADIENT_ALT는 적은 영향을 받는다. cv2.Hough_GRADIENT_ALT의 경우에 입력 인자가 달라지므로 주의해야 한다.
dp는 보통 1을 설정하며 경우에 따라 2로 설정하여 입력 영상보다 1/2 크기의 축적 영상을 생성한다.
1/2 크기의 영상을 생성하면 연산 속도가 빨라지지만 아주 정교한 원은 찾아내지 못합니다.
mniDIst는 검출된 원 중심점들의 최소거리를 설정하여 원이 너무 붙어 있는 것은 찾지 않는다.
💬 허프 변환 원 검출 예제
import sys
import numpy as np
import cv2
# 입력 이미지 불러오기
src = cv2.imread('dial.jpg')
if src is None:
print('Image open failed!')
sys.exit()
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
blr = cv2.GaussianBlur(gray, (0, 0), 1.0)
def on_trackbar(pos):
rmin = cv2.getTrackbarPos('minRadius', 'img')
rmax = cv2.getTrackbarPos('maxRadius', 'img')
th = cv2.getTrackbarPos('threshold', 'img')
circles = cv2.HoughCircles(blr, cv2.HOUGH_GRADIENT, 1, 50,
param1=120, param2=th, minRadius=rmin, maxRadius=rmax)
dst = src.copy()
if circles is not None:
for i in range(circles.shape[1]):
cx, cy, radius = circles[0][i]
cv2.circle(dst, (cx, cy), int(radius), (0, 0, 255), 2, cv2.LINE_AA)
cv2.imshow('img', dst)
# 트랙바 생성
cv2.imshow('img', src)
cv2.createTrackbar('minRadius', 'img', 0, 100, on_trackbar)
cv2.createTrackbar('maxRadius', 'img', 0, 150, on_trackbar)
cv2.createTrackbar('threshold', 'img', 0, 100, on_trackbar)
cv2.setTrackbarPos('minRadius', 'img', 10)
cv2.setTrackbarPos('maxRadius', 'img', 80)
cv2.setTrackbarPos('threshold', 'img', 40)
cv2.waitKey()
cv2.destroyAllWindows()
'OpenCV' 카테고리의 다른 글
[OpenCV with Python] 이진 영상 처리 : 자동 이진화 - Otsu 방법 (0) | 2022.02.04 |
---|---|
[OpenCV with Python] 이진 영상 처리 : 영상의 이진화 - cv2.threshold (0) | 2022.02.04 |
[OpenCV with Python] 영상의 특징 추출 : 영상에서 직선 검출하기 - 허프 변환 (0) | 2022.02.04 |
[OpenCV with Python] 영상의 특징 추출 : 캐니 에지 검출 cv2.Canny (1) | 2022.02.04 |
[OpenCV with Python] 영상의 특징 추출 : 그래디언트와 에지 검출 (0) | 2022.02.04 |