๐ ๊ณต๋ถํ๋ ์ง์ง์ํ์นด๋ ์ฒ์์ด์ง?
[v0.24]์์์ฒ๋ฆฌ_์ปจํฌ์ด (์์๋ถํ ๋ฐฉ๋ฒ) ๋ณธ๋ฌธ
[v0.24]์์์ฒ๋ฆฌ_์ปจํฌ์ด (์์๋ถํ ๋ฐฉ๋ฒ)
์ง์ง์ํ์นด 2022. 1. 12. 18:30220112 ์์ฑ
<๋ณธ ๋ธ๋ก๊ทธ๋ ๊ทํ์ด ์์ฌ๋์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํด์ ๊ณต๋ถํ๋ฉฐ ์์ฑํ์์ต๋๋ค>
https://bkshin.tistory.com/entry/OpenCV-22-%EC%BB%A8%ED%88%AC%EC%96%B4Contour?category=1148027
1. ์ปจํฌ์ด (Contour)
: ๋ฑ๊ณ ์ , ์งํ์ ๋์ด๊ฐ ๊ฐ์ ์์ญ์ ํ๋์ ์ ์ผ๋ก ํ์
: ์ปจํฌ์ด๋ฅผ ๊ทธ๋ฆฌ๋ฉด ๋ชจ์์ ์ฝ๊ฒ ์ธ์
dst, contours, hierarchy = cv2.findContours(src, mode, method, contours, hierarchy, offset)
: ์ปจํฌ์ด๋ฅผ ์ฐพ์๋ด๊ธฐ
- src : ์ ๋ ฅ ์์, ๊ฒ์ ๊ณผ ํฐ์์ผ๋ก ๊ตฌ์ฑ๋ ๋ฐ์ด๋๋ฆฌ ์ด๋ฏธ์ง
- mode : ์ปจํฌ์ด ์ ๊ณต ๋ฐฉ์
- cv2.RETR_EXTERNA L: ๊ฐ์ฅ ๋ฐ๊นฅ์ชฝ ๋ผ์ธ๋ง ์์ฑ
- cv2.RETR_LIST : ๋ชจ๋ ๋ผ์ธ์ ๊ณ์ธต ์์ด ์์ฑ
- cv2.RET_CCOMP : ๋ชจ๋ ๋ผ์ธ์ 2 ๊ณ์ธต์ผ๋ก ์์ฑ
- cv2.RETR_TREE : ๋ชจ๋ ๋ผ์ธ์ ๋ชจ๋ ๊ณ์ธต ์ ๋ณด๋ฅผ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก ์์ฑ
- method : ๊ทผ์ฌ ๊ฐ ๋ฐฉ์
- cv2.CHAIN_APPROX_NONE : ๊ทผ์ฌ ์์ด ๋ชจ๋ ์ขํ ์ ๊ณต
- cv2.CHAIN_APPROX_SIMPLE : ์ปจํฌ์ด ๊ผญ์ง์ ์ขํ๋ง ์ ๊ณต
- cv2.CHAIN_APPROX_TC89_L1 : Teh-Chin ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ขํ ๊ฐ์ ์ถ์
- cv2.CHAIN_APPROX_TC89_KC0S : Teh-Chin ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ขํ ๊ฐ์ ์ถ์
- contours(optional) : ๊ฒ์ถํ ์ปจํฌ์ด ์ขํ (list type)
- hierarchy(optional) : ์ปจํฌ์ด ๊ณ์ธต ์ ๋ณด (Next, Prev, FirstChild, Parent, -1 [ํด๋น ์์])
- offset(optional) : ROI ๋ฑ์ผ๋ก ์ธํด ์ด๋ํ ์ปจํฌ์ด ์ขํ์ ์คํ์
cv2.drawContours(img, contours, contourIdx, color, thickness)
: ์ปจํฌ์ด ์ ๊ทธ๋ฆฌ๊ธฐ
- img : ์ ๋ ฅ ์์
- contours : ๊ทธ๋ฆผ ๊ทธ๋ฆด ์ปจํฌ์ด ๋ฐฐ์ด (cv2.findContours() ํจ์์ ๋ฐํ ๊ฒฐ๊ณผ๋ฅผ ์ ๋ฌํด์ฃผ๋ฉด ๋จ)
- contourIdx : ๊ทธ๋ฆผ ๊ทธ๋ฆด ์ปจํฌ์ด ์ธ๋ฑ์ค, -1: ๋ชจ๋ ์ปจํฌ์ด ํ์
- color : ์์ ๊ฐ
- thickness : ์ ๋๊ป, 0: ์ฑ์ฐ๊ธฐ
=> img์์์ contours ๋ฐฐ์ด์ ์๋ ์ปจํฌ์ด ์ค contourIdx์ ํด๋นํ๋ ์ปจํฌ์ด๋ฅผ
color ์์๊ณผ thickness ๋๊ป๋ก ์ ์ ๊ทธ๋ฆฐ๋ค
# ์ปจํฌ์ด ์ฐพ๊ธฐ์ ๊ทธ๋ฆฌ๊ธฐ
import cv2
import numpy as np
img = cv2.imread('img/shapes.JPG')
img2 = img.copy()
# ๊ทธ๋ ์ด ์ค์ผ์ผ๋ก ๋ณํ ---โ
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# ์ค๋ ์ํ๋๋ก ๋ฐ์ด๋๋ฆฌ ์ด๋ฏธ์ง๋ก ๋ง๋ค์ด์ ๊ฒ์๋ฐฐ๊ฒฝ์ ํฐ์์ ๊ฒฝ์ผ๋ก ๋ฐ์ ---โก
ret, imthres = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY_INV)
# ๊ฐ์ฅ ๋ฐ๊นฅ์ชฝ ์ปจํฌ์ด์ ๋ํด ๋ชจ๋ ์ขํ ๋ฐํ ---โข
im2, contour, hierarchy = cv2.findContours(imthres, cv2.RETR_EXTERNAL, \
cv2.CHAIN_APPROX_NONE)
# ๊ฐ์ฅ ๋ฐ๊นฅ์ชฝ ์ปจํฌ์ด์ ๋ํด ๊ผญ์ง์ ์ขํ๋ง ๋ฐํ ---โฃ
im2, contour2, hierarchy = cv2.findContours(imthres, cv2.RETR_EXTERNAL, \
cv2.CHAIN_APPROX_SIMPLE)
# ๊ฐ๊ฐ์ ์ปจํฌ์ ๊ฐฏ์ ์ถ๋ ฅ ---โค
print('๋ํ์ ๊ฐฏ์: %d(%d)'% (len(contour), len(contour2)))
# ๋ชจ๋ ์ขํ๋ฅผ ๊ฐ๋ ์ปจํฌ์ด ๊ทธ๋ฆฌ๊ธฐ, ์ด๋ก์ ---โฅ
cv2.drawContours(img, contour, -1, (0,255,0), 4)
# ๊ผญ์ง์ ์ขํ๋ง์ ๊ฐ๋ ์ปจํฌ์ด ๊ทธ๋ฆฌ๊ธฐ, ์ด๋ก์ ---โฆ
cv2.drawContours(img2, contour2, -1, (0,255,0), 4)
# ์ปจํฌ์ด ๋ชจ๋ ์ขํ๋ฅผ ์์ ํ๋์ ์ (์)์ผ๋ก ํ์ ---โง
for i in contour:
for j in i:
cv2.circle(img, tuple(j[0]), 1, (255,0,0), -1)
# ์ปจํฌ์ด ๊ผญ์ง์ ์ขํ๋ฅผ ์์ ํ๋์ ์ (์)์ผ๋ก ํ์ ---โจ
for i in contour2:
for j in i:
cv2.circle(img2, tuple(j[0]), 1, (255,0,0), -1)
# ๊ฒฐ๊ณผ ์ถ๋ ฅ ---โฉ
cv2.imshow('CHAIN_APPROX_NONE', img)
cv2.imshow('CHAIN_APPROX_SIMPLE', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
ValueError: not enough values to unpack (expected 3, got 2)
ํ ๋ ๋ญ ์๋ฌ๋!
- ์ : cv2.CHAIN_APPROX_SIMPLE์ ์ฌ์ฉํด์ ๊ผญ์ง์ ๋ง ํ์
- ์๋ : cv2.CHAIN_APPROX_NONE์ ์ฌ์ฉํด์ ๋ชจ๋ ์ขํ์ ์ปจํฌ์ด๋ฅผ ๊ทธ๋ฆฌ๊ธฐ
+) ํธ๋ฆฌ ๊ณ์ธต์ ์ปจํฌ์ด
# ์ปจํฌ์ด ๊ณ์ธต ํธ๋ฆฌ
import cv2
import numpy as np
# ์์ ์ฝ๊ธฐ
img = cv2.imread('img/shapes_donut.png')
img2 = img.copy()
# ๋ฐ์ด๋๋ฆฌ ์ด๋ฏธ์ง๋ก ๋ณํ
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, imthres = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY_INV)
# ๊ฐ์ฅ ๋ฐ๊นฅ ์ปจํฌ์ด๋ง ์์ง --- โ
im2, contour, hierarchy = cv2.findContours(imthres, cv2.RETR_EXTERNAL, \
cv2.CHAIN_APPROX_NONE)
# ์ปจํฌ์ด ๊ฐฏ์์ ๊ณ์ธต ํธ๋ฆฌ ์ถ๋ ฅ --- โก
print(len(contour), hierarchy)
# ๋ชจ๋ ์ปจํฌ์ด๋ฅผ ํธ๋ฆฌ ๊ณ์ธต ์ผ๋ก ์์ง ---โข
im2, contour2, hierarchy = cv2.findContours(imthres, cv2.RETR_TREE, \
cv2.CHAIN_APPROX_SIMPLE)
# ์ปจํฌ์ด ๊ฐฏ์์ ๊ณ์ธต ํธ๋ฆฌ ์ถ๋ ฅ ---โฃ
print(len(contour2), hierarchy)
# ๊ฐ์ฅ ๋ฐ๊นฅ ์ปจํฌ์ด๋ง ๊ทธ๋ฆฌ๊ธฐ ---โค
cv2.drawContours(img, contour, -1, (0,255,0), 3)
# ๋ชจ๋ ์ปจํฌ์ด ๊ทธ๋ฆฌ๊ธฐ ---โฅ
for idx, cont in enumerate(contour2):
# ๋๋คํ ์ปฌ๋ฌ ์ถ์ถ ---โฆ
color = [int(i) for i in np.random.randint(0,255, 3)]
# ์ปจํฌ์ด ์ธ๋ฑ์ค ๋ง๋ค ๋๋คํ ์์์ผ๋ก ๊ทธ๋ฆฌ๊ธฐ ---โง
cv2.drawContours(img2, contour2, idx, color, 3)
# ์ปจํฌ์ด ์ฒซ ์ขํ์ ์ธ๋ฑ์ค ์ซ์ ํ์ ---โจ
cv2.putText(img2, str(idx), tuple(cont[0][0]), cv2.FONT_HERSHEY_PLAIN, \
1, (0,0,255))
# ํ๋ฉด ์ถ๋ ฅ
cv2.imshow('RETR_EXTERNAL', img)
cv2.imshow('RETR_TREE', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
- ์ : cv2.RETR_EXTERNAL์ ์ฌ์ฉํด์ ๊ทธ๋ฆผ์ ์ธ๊ณฝ ๋ถ๋ถ์๋ง ์ปจํฌ์ด๋ฅผ ๊ทธ๋ฆฌ๊ธฐ
- ์๋ : cv2.RETR_TREE์ ์ฌ์ฉํด์ ๋ชจ๋ ๊ฒฝ๊ณ์ ์ปจํฌ์ด๋ฅผ ๊ทธ๋ฆฌ๊ธฐ
- ์ด๋ฅผ ํธ๋ฆฌ ๊ณ์ธต ์ปจํฌ์ด
2. ์ปจํฌ์ด๋ฅผ ๊ฐ์ธ๋ ๋ํ ๊ทธ๋ฆฌ๊ธฐ
x, y, w, h = cv2.boundingRect(contour)
: ์ขํ๋ฅผ ๊ฐ์ธ๋ ์ฌ๊ฐํ ๋ฐํ
- x, y : ์ฌ๊ฐํ์ ์ผ์ชฝ ์๋จ ์ขํ
- w, h : ์ฌ๊ฐํ์ ํญ๊ณผ ๋์ด
rotateRect = cv2.minAreaRect(contour)
: ์ขํ๋ฅผ ๊ฐ์ธ๋ ์ต์ํ์ ์ฌ๊ฐํ ๊ณ์ฐ
vertex = cv2.boxPoints(rotateRect)
: rotateRect๋ก๋ถํฐ ๊ผญ์ง์ ์ขํ ๊ณ์ฐ
- vertex : 4๊ฐ์ ๊ผญ์ง์ ์ขํ, ์์์ ํฌํจ์ด๋ฏ๋ก ์ ์ ๋ณํ ํ์
center, radius = cv2.minEnclosingCircle(contour)
: ์ขํ๋ฅผ ๊ฐ์ธ๋ ์ต์ํ์ ๋๊ทธ๋ผ๋ฏธ ๊ณ์ฐ
- center : ์์ ์ขํ(x, y)
- radius : ๋ฐ์ง๋ฆ
area, triangle = cv2.minEnclosingTriangle(points)
: ์ขํ๋ฅผ ๊ฐ์ธ๋ ์ต์ํ์ ์ผ๊ฐํ ๊ฒ์ฐ
- area : ๋์ด
- triangle : 3๊ฐ์ ๊ผญ์ง์ ์ขํ
ellipse = cv2.fitEllipse(points)
: ์ขํ๋ฅผ ๊ฐ์ธ๋ ์ต์ํ์ ํ์ ๊ณ์ฐ
line = cv2.fitLine(points, distType, param, reps, aeps, line)
: ์ค์ฌ์ ์ ํต๊ณผํ๋ ์ง์ ๊ณ์ฐ
- distType : ๊ฑฐ๋ฆฌ ๊ณ์ฐ ๋ฐฉ์
- cv2.DIST_L2
- cv2.DIST_L1
- cv2.DIST_L12
- cv2.DIST_FAIR
- cv2.DIST_WELSCH
- cv2.DIST_HUBER
- param : distType์ ์ ๋ฌํ ์ธ์, 0 = ์ต์ ๊ฐ ์ ํ
- reps : ๋ฐ์ง๋ฆ ์ ํ๋, ์ ๊ณผ ์๋ณธ ์ขํ์ ๊ฑฐ๋ฆฌ, 0.01 ๊ถ์ฅ
- aeps : ๊ฐ๋ ์ ํ๋, 0.01 ๊ถ์ฅ
- line(optional) : vx, vy ์ ๊ทํ๋ ๋จ์ ๋ฒกํฐ, x0, y0: ์ค์ฌ์ ์ขํ
# ์ปจํฌ์ด๋ฅผ ๊ฐ์ธ๋ ๋ํ ๊ทธ๋ฆฌ๊ธฐ
import cv2
import numpy as np
# ์ด๋ฏธ์ง ์ฝ์ด์ ๊ทธ๋ ์ด์ค์ผ์ผ ๋ณํ, ๋ฐ์ด๋๋ฆฌ ์ค์ผ์ผ ๋ณํ
img = cv2.imread("img/lighting.JPG")
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, th = cv2.threshold(imgray, 127,255,cv2.THRESH_BINARY_INV)
# ์ปจํ์ด ์ฐพ๊ธฐ
im, contours, hr = cv2.findContours(th, cv2.RETR_EXTERNAL, \
cv2.CHAIN_APPROX_SIMPLE)
contr = contours[0]
# ๊ฐ์ธ๋ ์ฌ๊ฐํ ํ์(๊ฒ์ ์)
x,y,w,h = cv2.boundingRect(contr)
cv2.rectangle(img, (x,y), (x+w, y+h), (0,0,0), 3)
# ์ต์ํ์ ์ฌ๊ฐํ ํ์(์ด๋ก์)
rect = cv2.minAreaRect(contr)
box = cv2.boxPoints(rect) # ์ค์ฌ์ ๊ณผ ๊ฐ๋๋ฅผ 4๊ฐ์ ๊ผญ์ง์ ์ขํ๋ก ๋ณํ
box = np.int0(box) # ์ ์๋ก ๋ณํ
cv2.drawContours(img, [box], -1, (0,255,0), 3)
# ์ต์ํ์ ์ ํ์(ํ๋์)
(x,y), radius = cv2.minEnclosingCircle(contr)
cv2.circle(img, (int(x), int(y)), int(radius), (255,0,0), 2)
# ์ต์ํ์ ์ผ๊ฐํ ํ์(๋ถํ์)
ret, tri = cv2.minEnclosingTriangle(contr)
cv2.polylines(img, [np.int32(tri)], True, (255,0,255), 2)
# ์ต์ํ์ ํ์ ํ์(๋
ธ๋์)
ellipse = cv2.fitEllipse(contr)
cv2.ellipse(img, ellipse, (0,255,255), 3)
# ์ค์ฌ์ ํต๊ณผํ๋ ์ง์ ํ์(๋นจ๊ฐ์)
[vx,vy,x,y] = cv2.fitLine(contr, cv2.DIST_L2,0,0.01,0.01)
cols,rows = img.shape[:2]
cv2.line(img,(0, 0-x*(vy/vx) + y), (cols-1, (cols-x)*(vy/vx) + y), \
(0,0,255),2)
# ๊ฒฐ๊ณผ ์ถ๋ ฅ
cv2.imshow('Bound Fit shapes', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
๋ ์๋จ ใ กใ ก
3. ์ปจํฌ์ด ๋จ์ํ
: ๊ทผ์ฌ ๊ฐ์ผ๋ก ์ปจํฌ์ด ๊ณ์ฐ
approx = cv2.approxPolyDP(contour, epsilon, closed)
- contour : ๋์ ์ปจํฌ์ด ์ขํ
- epsilon : ๊ทผ์ฌ ๊ฐ ์ ํ๋, ์ค์ฐจ ๋ฒ์
- closed : ์ปจํฌ์ด์ ๋ซํ ์ฌ๋ถ
- approx : ๊ทผ์ฌ ๊ณ์ฐํ ์ปจํฌ์ด ์ขํ
# ๊ทผ์ฌ ์ปจํฌ์ด
import cv2
import numpy as np
img = cv2.imread('img/bad_rect.png')
img2 = img.copy()
# ๊ทธ๋ ์ด์ค์ผ์ผ๊ณผ ๋ฐ์ด๋๋ฆฌ ์ค์ผ์ผ ๋ณํ
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, th = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY)
# ์ปจํฌ์ด ์ฐพ๊ธฐ ---โ
temp, contours, hierachy = cv2.findContours(th, cv2.RETR_EXTERNAL, \
cv2.CHAIN_APPROX_SIMPLE)
contour = contours[0]
# ์ ์ฒด ๋๋ ์ 0.05๋ก ์ค์ฐจ ๋ฒ์ ์ง์ ---โก
epsilon = 0.05 * cv2.arcLength(contour, True)
# ๊ทผ์ฌ ์ปจํฌ์ด ๊ณ์ฐ ---โข
approx = cv2.approxPolyDP(contour, epsilon, True)
# ๊ฐ๊ฐ ์ปจํฌ์ด ์ ๊ทธ๋ฆฌ๊ธฐ ---โฃ
cv2.drawContours(img, [contour], -1, (0,255,0), 3)
cv2.drawContours(img2, [approx], -1, (0,255,0), 3)
# ๊ฒฐ๊ณผ ์ถ๋ ฅ
cv2.imshow('contour', img)
cv2.imshow('approx', img2)
cv2.waitKey()
cv2.destroyAllWindows()
ValueError: not enough values to unpack (expected 3, got 2)
cv2 ๋ฒ์ ์ด ๋ค๋ฅด๋ฉด,, ์๋๋๊ฑด๊ฐ
- cv2.approPolyDP() ๋ ์์ฒ ๋ถ๋ถ ๋ฌด์ํ๊ณ ์ปจํฌ์ด ๊ณ์ฐ
+) ์ปจํฌ์ด ๋จ์ํ_ ๋ณผ๋ก ์ ์ฒด(convex hull)
: ๋ณผ๋ก ์ ์ฒด๋ ์ด๋ ํ ๋ถ๋ถ๋ ์ค๋ชฉํ์ง ์์ ๋ํ์ ์๋ฏธ
: ๋์์ ์์ ํ ํฌํจํ๋ ์ธ๊ณฝ ์์ญ์ ์ฐพ๋๋ฐ ์ ์ฉ
hull = cv2.convexHull(points, hull, clockwise, returnPoints)
: ๋ณผ๋ก ์ ์ฒด ๊ณ์ฐ
- points : ์
๋ ฅ ์ปจํฌ์ด
- hull(optional) : ๋ณผ๋ก ์ ์ฒด ๊ฒฐ๊ณผ
- clockwise(optional) : ๋ฐฉํฅ ์ง์ (True: ์๊ณ ๋ฐฉํฅ)
- returnPoints(optional) : ๊ฒฐ๊ณผ ์ขํ ํ์ ์ ํ (True: ๋ณผ๋ก ์ ์ฒด ์ขํ ๋ณํ, False: ์
๋ ฅ ์ปจํฌ์ด ์ค์ ๋ณผ๋ก ์ ์ฒด์ ํด๋นํ๋ ์ธ๋ฑ์ค ๋ฐํ)
retval = cv2.isContourConvex(contour)
: ๋ณผ๋ก ์ ์ฒด ๋ง์กฑ ์ฌ๋ถ ํ์ธ
- retval : True์ธ ๊ฒฝ์ฐ ๋ณผ๋ก ์ ์ฒด์
defects = cv2.convexityDefects(contour, convexhull)
: ๋ณผ๋ก ์ ์ฒด ๊ฒฐํจ ์ฐพ๊ธฐ
- contour : ์
๋ ฅ ์ปจํฌ์ด
- convexhull : ๋ณผ๋ก ์ ์ฒด์ ํด๋นํ๋ ์ปจํฌ์ด์ ์ธ๋ฑ์ค
- defects : ๋ณผ๋ก ์ ์ฒด ๊ฒฐํจ์ด ์๋ ์ปจํฌ์ด์ ๋ฐฐ์ด ์ธ๋ฑ์ค, N x 1 x 4 ๋ฐฐ์ด, [starts, end, farthest, distance]
- start : ์ค๋ชฉํ ๊ฐ์ด ์์๋๋ ์ปจํฌ์ด์ ์ธ๋ฑ์ค
- end : ์ค๋ชฉํ ๊ฐ์ด ๋๋๋ ์ปจํฌ์ด์ ์ธ๋ฑ์ค
- farthest : ๋ณผ๋ก ์ ์ฒด์์ ๊ฐ์ฅ ๋จผ ์ค๋ชฉํ ์ง์ ์ ์ปจํฌ์ด ์ธ๋ฑ์ค
- distance : farthest์ ๋ณผ๋ก ์ ์ฒด์์ ๊ฑฐ๋ฆฌ
# ๋ณผ๋ก ์ ์ฒด
import cv2
import numpy as np
img = cv2.imread('img/hand.png')
img2 = img.copy()
# ๊ทธ๋ ์ด ์ค์ผ์ผ ๋ฐ ๋ฐ์ด๋๋ฆฌ ์ค์ผ์ผ ๋ณํ ---โ
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, th = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
# ์ปจํฌ์ด ์ฐพ๊ธฐ์ ๊ทธ๋ฆฌ๊ธฐ ---โก
temp, contours, heiarchy = cv2.findContours(th, cv2.RETR_EXTERNAL, \
cv2.CHAIN_APPROX_SIMPLE)
cntr = contours[0]
cv2.drawContours(img, [cntr], -1, (0, 255,0), 1)
# ๋ณผ๋ก ์ ์ฒด ์ฐพ๊ธฐ(์ขํ ๊ธฐ์ค)์ ๊ทธ๋ฆฌ๊ธฐ ---โข
hull = cv2.convexHull(cntr)
cv2.drawContours(img2, [hull], -1, (0,255,0), 1)
# ๋ณผ๋ก ์ ์ฒด ๋ง์กฑ ์ฌ๋ถ ํ์ธ ---โฃ
print(cv2.isContourConvex(cntr), cv2.isContourConvex(hull))
# ๋ณผ๋ก ์ ์ฒด ์ฐพ๊ธฐ(์ธ๋ฑ์ค ๊ธฐ์ค) ---โค
hull2 = cv2.convexHull(cntr, returnPoints=False)
# ๋ณผ๋ก ์ ์ฒด ๊ฒฐํจ ์ฐพ๊ธฐ ---โฅ
defects = cv2.convexityDefects(cntr, hull2)
# ๋ณผ๋ก ์ ์ฒด ๊ฒฐํจ ์ํ
for i in range(defects.shape[0]):
# ์์, ์ข
๋ฃ, ๊ฐ์ฅ ๋จผ ์ง์ , ๊ฑฐ๋ฆฌ ---โฆ
startP, endP, farthestP, distance = defects[i, 0]
# ๊ฐ์ฅ ๋จผ ์ง์ ์ ์ขํ ๊ตฌํ๊ธฐ ---โง
farthest = tuple(cntr[farthestP][0])
# ๊ฑฐ๋ฆฌ๋ฅผ ๋ถ๋ ์์์ ์ผ๋ก ๋ณํ ---โจ
dist = distance/256.0
# ๊ฑฐ๋ฆฌ๊ฐ 1๋ณด๋ค ํฐ ๊ฒฝ์ฐ ---โฉ
if dist > 1 :
# ๋นจ๊ฐ์ ์ ํ์
cv2.circle(img2, farthest, 3, (0,0,255), -1)
# ๊ฒฐ๊ณผ ์ด๋ฏธ์ง ํ์
cv2.imshow('contour', img)
cv2.imshow('convex hull', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
- ๋ฐ ์ผ์ชฝ : ์ ๋ชจ์ ์ปจํฌ์ด
- ๋ฐ ์ค๋ฅธ์ชฝ : ๋ณผ๋ก ์ ์ฒด + ์ ์ฒด์ ๊ฒฐ์
4. ์ปจํฌ์ด์ ๋ํ ๋งค์นญ
: ์๋ก ๋ค๋ฅธ ๋ฌผ์ฒด์ ์ปจํฌ์ด๋ฅผ ๋น๊ตํ๋ฉด ๋ ๋ฌผ์ฒด๊ฐ ์ผ๋ง๋ ๋น์ทํ์ง ์์ ์๋ค
retval = cv2.matchShapes(contour1, contour2, method, parameter)
: ๋ ๊ฐ์ ์ปจํฌ์ด๋ก ๋ํ ๋งค์นญ
- contour1, contour2 : ๋น๊ตํ ๋ ๊ฐ์ ์ปจํฌ์ด
- method : ํด ๋ชจ๋ฉํธ ๋น๊ต ์๊ณ ๋ฆฌ์ฆ ์ ํ ํ๋๊ทธ
- cv2.CONTOURS_MATCH_I1
- cv2.CONTOURS_MATCH_I2
- cv2.CONTOURS_MATCH_I3
- parameter : ์๊ณ ๋ฆฌ์ฆ์ ์ ๋ฌ์ ์ํ ์๋น ์ธ์๋ก 0์ผ๋ก ๊ณ ์
- retval : ๋ ๋ํ์ ๋ฎ์ ์ ๋ (0=๋์ผ, ์ซ์๊ฐ ํด์๋ก ๋ค๋ฆ)
# ๋ํ ๋งค์นญ์ผ๋ก ๋น์ทํ ๋ํ ์ฐพ๊ธฐ
import cv2
import numpy as np
# ๋งค์นญ์ ์ํ ์ด๋ฏธ์ง ์ฝ๊ธฐ
target = cv2.imread('img/4star.jpg') # ๋งค์นญ ๋์
shapes = cv2.imread('img/shapestomatch.jpg') # ์ฌ๋ฌ ๋ํ
# ๊ทธ๋ ์ด ์ค์ผ์ผ ๋ณํ
targetGray = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
shapesGray = cv2.cvtColor(shapes, cv2.COLOR_BGR2GRAY)
# ๋ฐ์ด๋๋ฆฌ ์ค์ผ์ผ ๋ณํ
ret, targetTh = cv2.threshold(targetGray, 127, 255, cv2.THRESH_BINARY_INV)
ret, shapesTh = cv2.threshold(shapesGray, 127, 255, cv2.THRESH_BINARY_INV)
# ์ปจํฌ์ด ์ฐพ๊ธฐ
_, cntrs_target, _ = cv2.findContours(targetTh, cv2.RETR_EXTERNAL, \
cv2.CHAIN_APPROX_SIMPLE)
_, cntrs_shapes, _ = cv2.findContours(shapesTh, cv2.RETR_EXTERNAL, \
cv2.CHAIN_APPROX_SIMPLE)
# ๊ฐ ๋ํ๊ณผ ๋งค์นญ์ ์ํ ๋ฐ๋ณต๋ฌธ
matchs = [] # ์ปจํฌ์ด์ ๋งค์นญ ์ ์๋ฅผ ๋ณด๊ดํ ๋ฆฌ์คํธ
for contr in cntrs_shapes:
# ๋์ ๋ํ๊ณผ ์ฌ๋ฌ ๋ํ ์ค ํ๋์ ๋งค์นญ ์คํ ---โ
match = cv2.matchShapes(cntrs_target[0], contr, cv2.CONTOURS_MATCH_I2, 0.0)
# ํด๋น ๋ํ์ ๋งค์นญ ์ ์์ ์ปจํฌ์ด๋ฅผ ์์ผ๋ก ์ ์ฅ ---โก
matchs.append( (match, contr) )
# ํด๋น ๋ํ์ ์ปจํฌ์ด ์์์ง์ ์ ๋งค์นญ ์ ์ ํ์ ---โข
cv2.putText(shapes, '%.2f'%match, tuple(contr[0][0]),\
cv2.FONT_HERSHEY_PLAIN, 1,(0,0,255),1 )
# ๋งค์นญ ์ ์๋ก ์ ๋ ฌ ---โฃ
matchs.sort(key=lambda x : x[0])
# ๊ฐ์ฅ ์ ์ ๋งค์นญ ์ ์๋ฅผ ์ป๋ ๋ํ์ ์ปจํฌ์ด์ ์ ๊ทธ๋ฆฌ๊ธฐ ---โค
cv2.drawContours(shapes, [matchs[0][1]], -1, (0,255,0), 3)
cv2.imshow('target', target)
cv2.imshow('Match Shape', shapes)
cv2.waitKey()
cv2.destroyAllWindows()
- ์ซ์๊ฐ ์์ ์๋ก ์๋ก ๋ฎ์ ๋ํ
- ๊ฐ์ฅ ๋ฎ์ ๋ํ ์ฃผ์์ ์ด๋ก์ ์ปจํฌ์ด ๊ทธ๋ฆฌ๊ธฐ
์์ํด ใ ใ
์ปจํฌ์ด ์คํ์ด ์๋๋ค ใ ใ
'๐ฉโ๐ป IoT (Embedded) > Image Processing' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[v0.26]์์์ฒ๋ฆฌ_์ฐ์ ์์ญ ๋ถํ (0) | 2022.01.12 |
---|---|
[v0.25]์์์ฒ๋ฆฌ_ํํ ๋ณํ (0) | 2022.01.12 |
[v0.23]์์์ฒ๋ฆฌ_ ๋ธ๋ฌ๋งํ์ฉ & ๋ชจ์์ดํฌ ์ฒ๋ฆฌ, ์ด๋ฏธ์ง ์ค์ผ์น ํจ๊ณผ (0) | 2022.01.12 |
[v0.22]์์์ฒ๋ฆฌ_๋ชจํด๋ก์ง(Morphology) ์ฐ์ฐ (0) | 2022.01.12 |
[v0.21]์์์ฒ๋ฆฌ_๋ชจํด๋ก์ง(Morphology) ์ฐ์ฐ (0) | 2022.01.11 |