Tech이야기~!
welcom 자세히보기

Computer/OpenCV

[Opencv] 이미지 필터_도형 검출(선)

Enhold 2019. 12. 16. 22:47

Hough변환으로 이미지에서 이런 특정 모양을 검출

특정 모양을 파라미터화하고 이미지에서 모양을 찾는 일반적인 프레임 워크

 

직선

이미지에 있는 선들의 기울기와 상수를 찾을려 한다. 

이미지 속에 있는 두 점이 주어졌을 때, 직선의 방정식을 다음과 같이 표현

 

선의 기울기와 y축과 만나는 지점을 계산한다. 

* 확률적 Hough 직선이라 불리는 Hough직선의 다른 변형이 있다. 

기본적으로 같은 일을 하지만, 직선 파라미터를 계산할 때는 다른 접근법을 사용, 더 복잡한 수학이 필요하다. 

 

from skimage.data import checkerboard
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = checkerboard()
rows, cols = img.shape

pts1 = np.float32([[25, 25], [175, 25], [25, 175], [175, 175]])
pts2 = np.float32([[25, 50], [150, 25], [75, 175], [175, 125]])

H = cv2.getPerspectiveTransform(pts1, pts2)
img = cv2.warpPerspective(img, H, (cols, rows))

edges = cv2.Canny(img, 100, 150, apertureSize=3)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 50, 50, 8)

plt.figure(figsize=(9, 7))
plt.subplot(1, 2, 1)
plt.imshow(img, cmap="gray")
plt.title("원본 이미지")
plt.axis("off")
plt.subplot(1, 2, 2)
plt.imshow(img, cmap="gray")
plt.axis("off")
for i in range(len(lines)):
    for x1, y1, x2, y2 in lines[i]:
        plt.plot([x1, x2], [y1, y2], c='r', lw=10, alpha=0.9)
plt.title("확률적 Hough 변환으로 추출한 직선")

plt.tight_layout()
plt.show()

 

* 추후 자율주행에서 도로 라인을 검출할때 사용됩니다.

 

Hough 원

cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) → circles

Parameters:

  • image – 8-bit single-channel image. grayscale image.
  • method – 검출 방법. 현재는 HOUGH_GRADIENT가 있음.
  • dp – dp=1이면 Input Image와 동일한 해상도.
  • minDist – 검출한 원의 중심과의 최소거리. 값이 작으면 원이 아닌 것들도 검출이 되고, 너무 크면 원을 놓칠 수 있음.
  • param1 – 내부적으로 사용하는 canny edge 검출기에 전달되는 Paramter
  • param2 – 이 값이 작을 수록 오류가 높아짐. 크면 검출률이 낮아짐.
  • minRadius – 원의 최소 반지름.
  • maxRadius – 원의 최대 반지름.
import cv2
import numpy as np

img = cv2.imread('chapter02/circle_singapor.jpg',0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)

circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 90,param1=80,param2=80,minRadius=0, maxRadius=0)

circles = np.uint16(np.around(circles))

for i in circles[0,:]:
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)

cv2.imshow('img', cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()