๐ ๊ณต๋ถํ๋ ์ง์ง์ํ์นด๋ ์ฒ์์ด์ง?
[v0.25]์์์ฒ๋ฆฌ_ํํ ๋ณํ ๋ณธ๋ฌธ
[v0.25]์์์ฒ๋ฆฌ_ํํ ๋ณํ
์ง์ง์ํ์นด 2022. 1. 12. 18:50220112 ์์ฑ
<๋ณธ ๋ธ๋ก๊ทธ๋ ๊ทํ์ด ์์ฌ๋์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํด์ ๊ณต๋ถํ๋ฉฐ ์์ฑํ์์ต๋๋ค>
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()
- ๋์ ๊ฒ์ถํ๊ธฐ !
- cv2.HoughCircles() ๋ ํจ์ ์์ฒด์ ์ผ๋ก ์บ๋ ์ฃ์ง ์ฌ์ฉ !
- ๊ฐ์ฐ์์ ๋ธ๋ฌ ํตํด์ ๋ ธ์ด์ฆ ์ ๊ฑฐ O , ์ฃ์ง๊ฒ์ถ X
- dp ๊ฐ์ 1์ ๊ฐ๊น์ธ ์๋ก ์ ํํ๊ฒ ์ ๊ฒ์ถ
ํ ์ด๋ฏธ์ง ์ฐพ๊ธฐ๋ ํ๋๋ก๊ณ ใ ใ
'๐ฉโ๐ป IoT (Embedded) > Image Processing' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[v0.27]์์์ฒ๋ฆฌ_์ด๋ฏธ์ง ๋งค์นญ (Image Matching) (0) | 2022.01.13 |
---|---|
[v0.26]์์์ฒ๋ฆฌ_์ฐ์ ์์ญ ๋ถํ (0) | 2022.01.12 |
[v0.24]์์์ฒ๋ฆฌ_์ปจํฌ์ด (์์๋ถํ ๋ฐฉ๋ฒ) (0) | 2022.01.12 |
[v0.23]์์์ฒ๋ฆฌ_ ๋ธ๋ฌ๋งํ์ฉ & ๋ชจ์์ดํฌ ์ฒ๋ฆฌ, ์ด๋ฏธ์ง ์ค์ผ์น ํจ๊ณผ (0) | 2022.01.12 |
[v0.22]์์์ฒ๋ฆฌ_๋ชจํด๋ก์ง(Morphology) ์ฐ์ฐ (0) | 2022.01.12 |