[computer-vision]
도형 검출
직선 검출
src = cv.imread("road.webp")
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 윤곽선 추출
canny = cv.Canny(gray, 5000, 1500, apertureSize = 5, L2gradient = True)
허프 변환
- 윤곽선을 이루는 점들을 지나는 직선의 방정식을 찾음
- 여러 개의 직선들 중에 가장 조건에 맞는 직선들만 골라냄
멀티 스케일 허프 변환 Multi-Scale Hough Transform
lines = cv.HoughLines(
canny,
0.8, # 거리 측정 해상도, 0~1
np.pi / 180, # 각도의 해상도(라디안)
150, # 임계값(키울 수록 정확도 증가하고 검출되는 직선의 수는 감소)
srn = 100, # 거리의 약수(≥0), 허프 변환을 좀 더 정확하게 하기 위한 값
stn = 200, # 각도의 약수(≥0), 허프 변환을 좀 더 정확하게 하기 위한 값
min_theta = 0, # 최소 각도
max_theta = np.pi) # 최대 각도
시각화
dst = src.copy()
for i in lines:
rho, theta = i[0][0], i[0][1]
a, b = np.cos(theta), np.sin(theta)
x0, y0 = int(a*rho), int(b*rho)
scale = src.shape[0] + src.shape[1]
x1 = int(x0 + scale * -b)
y1 = int(y0 + scale * a)
x2 = int(x0 - scale * -b)
y2 = int(y0 - scale * a)
cv.line(dst, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv.circle(dst, (x0, y0), 3, (255, 0, 0), 5, cv.FILLED)
점진성 확률적 허프 변환 Progressive Probabilistic Hough Transform
# 속도는 빠르지만 정확성은 떨어지는 방식
lines = cv.HoughLinesP(
canny,
0.8, # 거리 측정 해상도, 0~1
np.pi / 180, # 각도의 해상도(라디안)
90, # 임계값(키울 수록 정확도 증가하고 검출되는 직선의 수는 감소)
minLineLength = 10, # 검출할 직선의 최소 길이
maxLineGap = 100) # 최대 허용 간격(이 간격 내에 있는 직선은 검출 안함)
시각화
dst = src.copy()
lines = lines.astype(int, copy=False)
for i in lines:
cv.line(
dst,
(i[0][0], i[0][1]), # 시작
(i[0][2], i[0][3]), # 끝
(0, 255, 0), # 색깔
2) # 굵기
원 검출
src = cv.imread("balls.webp") # 예제 이미지
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
circles = cv.HoughCircles(# 허프 변환
gray,
cv.HOUGH_GRADIENT, # 검출 방법, HOUGH_GRADIENT_ALT도 있음
1, # 해상도 비율
100, # 원의 중심 간 최소 거리
param1 = 250, # 검출 방법의 매개 변수
param2 = 10, # 검출 방법의 매개 변수
minRadius = 80, # 최소 반지름
maxRadius = 120) # 최대 반지름
시각화
dst = src.copy()
circles = circles.astype(int)
for i in circles[0]:
cv.circle(dst, (i[0], i[1]), i[2], (255, 255, 255), 5)
볼록 껍질
어떤 도형을 둘러싼 볼록한 다각형 찾기
src = cv.imread("convex.webp") # 예제 데이터
dst = src.copy()
gray = cv.cvtColor(src, cv.COLOR_RGB2GRAY)
ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_BINARY_INV) # 이진화
contours, hierarchy = cv.findContours(# 윤곽선
binary, cv.RETR_CCOMP, cv.CHAIN_APPROX_NONE)
for i in contours:
hull = cv.convexHull(i, clockwise=True) # 볼록 껍질 찾기(True: 시계 방향)
cv.drawContours(dst, [hull], 0, (0, 0, 255), 2)
윤곽선 관련 기타 함수들
cv.contourArea윤곽선이 감싸는 영역의 면적cv.fitLine주어진 점에 적합한 직선cv.minEnclosingTriangle주어진 점을 감싸는 최소 크기 삼각형cv.boundingRect주어진 점을 감싸는 최소 크기 사각형cv.minAreaRect주어진 점을 감싸는 최소 크기 회전된 사각형cv.minEnclosingCircle주어진 점을 감싸는 최소 크기 원cv.fitEllipse주어진 점을 감싸는 타원cv.isContourConvex볼록 여부cv.convexityDefects볼록 껍질에서 가장 안으로 들어간 점