๐Ÿ˜Ž ๊ณต๋ถ€ํ•˜๋Š” ์ง•์ง•์•ŒํŒŒ์นด๋Š” ์ฒ˜์Œ์ด์ง€?

[v0.25]์˜์ƒ์ฒ˜๋ฆฌ_ํ—ˆํ”„ ๋ณ€ํ™˜ ๋ณธ๋ฌธ

๐Ÿ‘ฉ‍๐Ÿ’ป IoT (Embedded)/Image Processing

[v0.25]์˜์ƒ์ฒ˜๋ฆฌ_ํ—ˆํ”„ ๋ณ€ํ™˜

์ง•์ง•์•ŒํŒŒ์นด 2022. 1. 12. 18:50
728x90
๋ฐ˜์‘ํ˜•

220112 ์ž‘์„ฑ

<๋ณธ ๋ธ”๋กœ๊ทธ๋Š” ๊ท€ํ‰์ด ์„œ์žฌ๋‹˜์˜ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค>

https://bkshin.tistory.com/entry/OpenCV-23-%ED%97%88%ED%94%84-%EB%B3%80%ED%99%98Hough-Transformation?category=1148027 

 

OpenCV - 23. ํ—ˆํ”„ ๋ณ€ํ™˜(Hough Transformation)

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ํ—ˆํ”„ ๋ณ€ํ™˜์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ํฌ์ŠคํŒ… ์—ญ์‹œ 'ํŒŒ์ด์ฌ์œผ๋กœ ๋งŒ๋“œ๋Š” OpenCV ํ”„๋กœ์ ํŠธ(์ด์„ธ์šฐ ์ €)'๋ฅผ ์ •๋ฆฌํ•œ ๊ฒƒ์ž„์„ ๋ฐํž™๋‹ˆ๋‹ค. ์ฝ”๋“œ: github.com/BaekKyunShin/OpenCV_Project_Python/tree

bkshin.tistory.com

 

 

 

 

 

1. ํ—ˆํ”„ ๋ณ€ํ™˜

: ์ด๋ฏธ์ง€์—์„œ ์ง์„ ์ด๋‚˜ ์›๊ณผ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ๋ชจ์–‘์„ ์ธ์‹

: ์ด๋ฏธ์ง€์—์„œ ๋ชจ์–‘์„ ์ฐพ๋Š” ๊ฐ€์žฅ ์œ ๋ช…ํ•œ ๋ฐฉ๋ฒ•

: ์ด๋ฏธ์ง€์˜ ํ˜•ํƒœ๋ฅผ ์ฐพ๊ฑฐ๋‚˜, ๋ˆ„๋ฝ๋˜๊ฑฐ๋‚˜ ๊นจ์ง„ ์˜์—ญ์„ ๋ณต์›

 

 

 

 

2. ํ—ˆํ”„ ์„  ๋ณ€ํ™˜

: ์ด๋ฏธ์ง€๋Š” ์ˆ˜๋งŽ์€ ํ”ฝ์…€๋กœ ๊ตฌ์„ฑ

: ๊ทธ ํ”ฝ์…€ ์ค‘ ์„œ๋กœ ์ง์„  ๊ด€๊ณ„๋ฅผ ๊ฐ–๋Š” ํ”ฝ์…€๋“ค๋งŒ ๊ณจ๋ผ๋‚ด๋Š” ๊ฒƒ์ด ํ—ˆํ”„ ์„  ๋ณ€ํ™˜์˜ ํ•ต์‹ฌ

 

lines = cv2.HoughLines(img, rho, theta, threshold, lines, srn=0, stn=0, min_theta, max_theta)

- img : ์ž…๋ ฅ ์ด๋ฏธ์ง€, 1 ์ฑ„๋„ ๋ฐ”์ด๋„ˆ๋ฆฌ ์Šค์ผ€์ผ

- rho : ๊ฑฐ๋ฆฌ ์ธก์ • ํ•ด์ƒ๋„, 0~1

- theta : ๊ฐ๋„, ๋ผ๋””์•ˆ ๋‹จ์œ„ (np.pi / 0~180)

- threshold : ์ง์„ ์œผ๋กœ ํŒ๋‹จํ•  ์ตœ์†Œํ•œ์˜ ๋™์ผ ๊ฐœ์ˆ˜

: ๊ฐ™์€ ์ง์„ ์— ๋ช‡ ๊ฐœ์˜ ์ ์ด ๋“ฑ์žฅํ•ด์•ผ ์ง์„ ์œผ๋กœ ํŒ๋‹จํ• ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ตœ์†Œํ•œ์˜ ๊ฐœ์ˆ˜

(์ž‘์€ ๊ฐ’: ์ •ํ™•๋„ ๊ฐ์†Œ, ๊ฒ€์ถœ ๊ฐœ์ˆ˜ ์ฆ๊ฐ€ / ํฐ ๊ฐ’: ์ •ํ™•๋„ ์ฆ๊ฐ€, ๊ฒ€์ถœ ๊ฐœ์ˆ˜ ๊ฐ์†Œ)

- lines : ๊ฒ€์ถœ ๊ฒฐ๊ณผ, N x 1 x 2 ๋ฐฐ์—ด

- (r, Θ)srn, stn : ๋ฉ€ํ‹ฐ ์Šค์ผ€์ผ ํ—ˆํ”„ ๋ณ€ํ™˜์— ์‚ฌ์šฉ, ์„  ๊ฒ€์ถœ์—์„œ๋Š” ์‚ฌ์šฉ ์•ˆ ํ•จ

- min_theta, max_theta : ๊ฒ€์ถœ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ตœ๋Œ€, ์ตœ์†Œ ๊ฐ๋„

 

- ์ง์„ ์„ ๊ฒ€์ถœํ•˜๊ณ  ๊ธฐ์ค€ ์ขŒํ‘œ์— ๋นจ๊ฐ„ ์ ์„ ์ฐ์€ ์˜ˆ์‹œ

# ํ—ˆํ”„ ์„  ๊ฒ€์ถœ
import cv2
import numpy as np

img = cv2.imread('img/sudoku.jpg')
img2 = img.copy()
h, w = img.shape[:2]

# ๊ทธ๋ ˆ์ด ์Šค์ผ€์ผ ๋ณ€ํ™˜ ๋ฐ ์—ฃ์ง€ ๊ฒ€์ถœ ---โ‘ 
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(imgray, 100, 200 )

# ํ—ˆํ”„ ์„  ๊ฒ€์ถœ, ์ง์„ ์œผ๋กœ ํŒ๋‹จํ•  ์ตœ์†Œํ•œ์˜ ์ ์€ 130๊ฐœ๋กœ ์ง€์ • ---โ‘ก
lines = cv2.HoughLines(edges, 1, np.pi/180, 130)

for line in lines: # ๊ฒ€์ถœ๋œ ๋ชจ๋“  ์„  ์ˆœํšŒ
    r,theta = line[0] # ๊ฑฐ๋ฆฌ์™€ ๊ฐ๋„
    tx, ty = np.cos(theta), np.sin(theta) # x, y์ถ•์— ๋Œ€ํ•œ ์‚ผ๊ฐ๋น„
    x0, y0 = tx*r, ty*r  #x, y ๊ธฐ์ค€(์ ˆํŽธ) ์ขŒํ‘œ
    
    # ๊ธฐ์ค€ ์ขŒํ‘œ์— ๋นจ๊ฐ•์ƒ‰ ์  ๊ทธ๋ฆฌ๊ธฐ
    cv2.circle(img2, (abs(x0), abs(y0)), 3, (0,0,255), -1)
    
    # ์ง์„  ๋ฐฉ์ •์‹์œผ๋กœ ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•œ ์‹œ์ž‘์ , ๋์  ๊ณ„์‚ฐ
    x1, y1 = int(x0 + w*(-ty)), int(y0 + h * tx)
    x2, y2 = int(x0 - w*(-ty)), int(y0 - h * tx)
    
    # ์„ ๊ทธ๋ฆฌ๊ธฐ
    cv2.line(img2, (x1, y1), (x2, y2), (0,255,0), 1)

#๊ฒฐ๊ณผ ์ถœ๋ ฅ    
merged = np.hstack((img, img2))
cv2.imshow('hough line', merged)
cv2.waitKey()
cv2.destroyAllWindows()

Can't parse 'center'. Sequence item with index 0 has a wrong type

์—๋Ÿฌ๋‹น ๋ญ”๋œป์ผ๊นŒ?

ใ…‹ใ…‹ใ…‹ใ…‹ ใ…œใ…œ ์—๋Ÿฌ

- ์บ๋‹ˆ ์—ฃ์ง€ ๊ฒฝ๊ณ„ ๊ฐ’ ๊ฒ€์ถœ ํ›„ !! ํ—ˆํ”„ ์„  ๊ฒ€์ถœ ํ•˜๊ธฐ !

- ๊ฒฝ๊ณ„ ๊ธฐ์ค€์„ ์— ๋นจ๊ฐ„ ์  ! ์ถœ๋ ฅ

 

 

 

 

3. ํ™•๋ฅ ์  ํ—ˆํ”„ ์„  ๋ณ€ํ™˜

: ํ—ˆํ”„ ์„  ๊ฒ€์ถœ์€ ๋ชจ๋“  ์ ์— ๋Œ€ํ•ด ์ˆ˜๋งŽ์€ ์„ ์„ ๊ทธ์–ด์„œ ์ง์„ ์„ ์ฐพ๊ธฐ ๋•Œ๋ฌธ์— ์—ฐ์‚ฐ๋Ÿ‰์ด ๋ฌด์ฒ™ ๋งŽ๋‹ค

: ํ™•๋ฅ ์  ํ—ˆํ”„ ์„  ๋ณ€ํ™˜์€ ๋ชจ๋“  ์ ์„ ๊ณ ๋ คํ•˜์ง€ ์•Š๊ณ  ๋ฌด์ž‘์œ„๋กœ ์„ ์ •ํ•œ ํ”ฝ์…€์— ๋Œ€ํ•ด ํ—ˆํ”„ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๊ณ 

์ ์ฐจ ๊ทธ ์ˆ˜๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•

 

lines = cv2.HoughLinesP(img, rho, theta, threshold, lines, minLineLength, maxLineGap)
- minLineLength(optional) : ์„ ์œผ๋กœ ์ธ์ •ํ•  ์ตœ์†Œ ๊ธธ์ด
- maxLineGap(optional) : ์„ ์œผ๋กœ ํŒ๋‹จํ•  ์ตœ๋Œ€ ๊ฐ„๊ฒฉ
- lines : ๊ฒ€์ถœ๋œ ์„  ์ขŒํ‘œ, N x 1 x 4 ๋ฐฐ์—ด (x1, y1, x2, y2)
- ์ด์™ธ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” cv2.HoughLines()์™€ ๋™์ผ

 

: cv2.HoughLines()์˜ ๊ฒ€์ถœ ๊ฒฐ๊ณผ๋Š” r, Θ

: cv2.HoughLinesP()์˜ ๊ฒ€์ถœ ๊ฒฐ๊ณผ๋Š” ์„ ์˜ ์‹œ์ž‘๊ณผ ๋ ์ขŒํ‘œ

:  ํ™•๋ฅ ์ ์œผ๋กœ ์„ ์„ ๊ฒ€์ถœํ•˜๋ฏ€๋กœ ์„  ๊ฒ€์ถœ์ด ์ ๋‹ค

: ์—ฃ์ง€๋ฅผ ๊ฐ•ํ•˜๊ฒŒ ํ•˜๊ณ  threshold๋ฅผ ๋‚ฎ๊ฒŒ ์ง€์ •

# ํ™•๋ฅ  ํ—ˆํ”„ ๋ณ€ํ™˜์œผ๋กœ ์„  ๊ฒ€์ถœ
import cv2
import numpy as np

img = cv2.imread('img/sudoku.jpg')
img2 = img.copy()
# ๊ทธ๋ ˆ์ด ์Šค์ผ€์ผ๋กœ ๋ณ€ํ™˜ ๋ฐ ์—ฃ์ง€ ๊ฒ€์ถœ ---โ‘ 
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(imgray, 50, 200 )

# ํ™•์œจ ํ—ˆํ”„ ๋ณ€ํ™˜ ์ ์šฉ ---โ‘ก
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 10, None, 20, 2)
for line in lines:
    # ๊ฒ€์ถœ๋œ ์„  ๊ทธ๋ฆฌ๊ธฐ ---โ‘ข
    x1, y1, x2, y2 = line[0]
    cv2.line(img2, (x1,y1), (x2, y2), (0,255,0), 1)

merged = np.hstack((img, img2))
cv2.imshow('Probability hough line', merged)
cv2.waitKey()
cv2.destroyAllWindows()

ํ—ˆํ”„์„  ๋ณด๋‹ค ์„ ์„ ์ž˜ ๊ฒ€์ถœํ•˜์ง€ ์•Š์Œ

- ๊ฒ€์ถœ๋œ ์„ ์˜ ๊ฐœ์ˆ˜๋Š” ์ ์œผ๋‚˜, ์†๋„๋Š” ๋น ๋ฆ„

- ๋ฐ˜ํ™˜ ๊ฐ’์ด ์„ ์˜ ์‹œ์ž‘๊ณผ ๋ ์ขŒํ‘œ๋ผ์„œ ์ง์„  ๊ทธ๋ฆฌ๊ธฐ ๋” ํŽธ๋ฆฌ

 

 

 

 

4. ํ—ˆํ”„ ์› ๋ณ€ํ™˜

: ์›์„ ๊ฒ€์ถœ

 

circle = cv2.HoughCircles(img, method, dp, minDist, circles, param1, param2, minRadius, maxRadius)

- img : ์ž…๋ ฅ ์ด๋ฏธ์ง€, 1์ฑ„๋„ ๋ฐฐ์—ด

- method : ๊ฒ€์ถœ ๋ฐฉ์‹ ์„ ํƒ (ํ˜„์žฌ cv2.HOUGH_GRADIENT๋งŒ ๊ฐ€๋Šฅ)

- dp : ์ž…๋ ฅ ์˜์ƒ๊ณผ ๊ฒฝ์‚ฌ ๋ˆ„์ ์˜ ํ•ด์ƒ๋„ ๋ฐ˜๋น„๋ก€์œจ, 1: ์ž…๋ ฅ๊ณผ ๋™์ผ, ๊ฐ’์ด ์ปค์งˆ์ˆ˜๋ก ๋ถ€์ •ํ™•

- minDist : ์›๋“ค ์ค‘์‹ฌ ๊ฐ„์˜ ์ตœ์†Œ ๊ฑฐ๋ฆฌ (0: ์—๋Ÿฌ, 0์ด๋ฉด ๋™์‹ฌ์›์ด ๊ฒ€์ถœ ๋ถˆ๊ฐ€ํ•˜๋ฏ€๋กœ)

- circles(optional) : ๊ฒ€์ถœ ์› ๊ฒฐ๊ณผ, N x 1 x 3 ๋ถ€๋™ ์†Œ์ˆ˜์  ๋ฐฐ์—ด (x, y, ๋ฐ˜์ง€๋ฆ„)

- param1(optional) : ์บ๋‹ˆ ์—ฃ์ง€์— ์ „๋‹ฌํ•  ์Šค๋ ˆ์‹œํ™€๋“œ ์ตœ๋Œ€ ๊ฐ’ (์ตœ์†Œ ๊ฐ’์€ ์ตœ๋Œ€ ๊ฐ’์˜ 2๋ฐฐ ์ž‘์€ ๊ฐ’์„ ์ „๋‹ฌ)

- param2(optional) : ๊ฒฝ์‚ฌ๋„ ๋ˆ„์  ๊ฒฝ๊ณ„ ๊ฐ’ (๊ฐ’์ด ์ž‘์„์ˆ˜๋ก ์ž˜๋ชป๋œ ์› ๊ฒ€์ถœ)

- minRadius, maxRadius(optional) : ์›์˜ ์ตœ์†Œ ๋ฐ˜์ง€๋ฆ„, ์ตœ๋Œ€ ๋ฐ˜์ง€๋ฆ„ (0์ด๋ฉด ์ด๋ฏธ์ง€ ์ „์ฒด์˜ ํฌ๊ธฐ)

 

: ์บ๋‹ˆ ์—ฃ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋‚˜์„œ ์†Œ๋ฒจ ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•ด ์—ฃ์ง€์˜ ๊ฒฝ์‚ฌ๋„(gradient)๋ฅผ ๋ˆ„์ 

: ์บ๋‹ˆ ์—ฃ์ง€ ๋ฐ ๊ฒฝ์‚ฌ๋„ ๋ˆ„์ ์— ๋Œ€ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ(param1, param2) ์กด์žฌ

# ํ—ˆํ”„ ์› ๊ฒ€์ถœ
import cv2
import numpy as np

img = cv2.imread('img/coins_connected.png')
# ๊ทธ๋ ˆ์ด ์Šค์ผ€์ผ ๋ณ€ํ™˜ ---โ‘ 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# ๋…ธ์ด์ฆˆ ์ œ๊ฑฐ๋ฅผ ์œ„ํ•œ ๊ฐ€์šฐ์‹œ์•ˆ ๋ธ”๋Ÿฌ ---โ‘ก
blur = cv2.GaussianBlur(gray, (3,3), 0)
# ํ—ˆํ”„ ์› ๋ณ€ํ™˜ ์ ์šฉ( dp=1.2, minDist=30, cany_max=200 ) ---โ‘ข
circles = cv2.HoughCircles(blur, cv2.HOUGH_GRADIENT, 1.2, 30, None, 200)
if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        # ์› ๋‘˜๋ ˆ์— ์ดˆ๋ก์ƒ‰ ์› ๊ทธ๋ฆฌ๊ธฐ
        cv2.circle(img,(i[0], i[1]), i[2], (0, 255, 0), 2)
        # ์› ์ค‘์‹ฌ์ ์— ๋นจ๊ฐ•์ƒ‰ ์› ๊ทธ๋ฆฌ๊ธฐ
        cv2.circle(img, (i[0], i[1]), 2, (0,0,255), 5)

# ๊ฒฐ๊ณผ ์ถœ๋ ฅ
cv2.imshow('hough circle', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

https://deep-learning-study.tistory.com/214

- ๋™์ „ ๊ฒ€์ถœํ•˜๊ธฐ !

- cv2.HoughCircles() ๋Š” ํ•จ์ˆ˜ ์ž์ฒด์ ์œผ๋กœ ์บ๋‹ˆ ์—ฃ์ง€ ์‚ฌ์šฉ !

- ๊ฐ€์šฐ์‹œ์•ˆ ๋ธ”๋Ÿฌ ํ†ตํ•ด์„œ ๋…ธ์ด์ฆˆ ์ œ๊ฑฐ O , ์—ฃ์ง€๊ฒ€์ถœ X

- dp ๊ฐ’์€ 1์— ๊ฐ€๊นŒ์šธ ์ˆ˜๋ก ์ •ํ™•ํ•˜๊ฒŒ ์› ๊ฒ€์ถœ 

 

 

 

 

 

 

 

 

 

 

ํ›„ ์ด๋ฏธ์ง€ ์ฐพ๊ธฐ๋„ ํž˜๋“œ๋กœ๊ณ ใ…‹ใ…‹

 

 

 

 

728x90
๋ฐ˜์‘ํ˜•
Comments