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

[v0.26]์˜์ƒ์ฒ˜๋ฆฌ_์—ฐ์† ์˜์—ญ ๋ถ„ํ•  ๋ณธ๋ฌธ

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

[v0.26]์˜์ƒ์ฒ˜๋ฆฌ_์—ฐ์† ์˜์—ญ ๋ถ„ํ• 

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

220112 ์ž‘์„ฑ

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

https://bkshin.tistory.com/entry/OpenCV-24-%EC%97%B0%EC%86%8D-%EC%98%81%EC%97%AD-%EB%B6%84%ED%95%A0-%EA%B1%B0%EB%A6%AC-%EB%B3%80%ED%99%98-%EB%A0%88%EC%9D%B4%EB%B8%94%EB%A7%81-%EC%83%89-%EC%B1%84%EC%9A%B0%EA%B8%B0-%EC%9B%8C%ED%84%B0%EC%85%B0%EB%93%9C-%EA%B7%B8%EB%9E%A9%EC%BB%B7-%ED%8F%89%EA%B7%A0-%EC%9D%B4%EB%8F%99-%ED%95%84%ED%84%B0?category=1148027 

 

OpenCV - 24. ์—ฐ์† ์˜์—ญ ๋ถ„ํ•  (๊ฑฐ๋ฆฌ ๋ณ€ํ™˜, ๋ ˆ์ด๋ธ”๋ง, ์ƒ‰ ์ฑ„์šฐ๊ธฐ, ์›Œํ„ฐ์…ฐ๋“œ, ๊ทธ๋žฉ์ปท, ํ‰๊ท  ์ด๋™ ํ•„ํ„ฐ)

์ด์ „ ํฌ์ŠคํŒ…์—์„œ๋Š” ์™ธ๊ณฝ ๊ฒฝ๊ณ„๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ์ฒด ์˜์—ญ์„ ๋ถ„ํ• ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ ์ด๋ฏธ์ง€์—๋Š” ๋…ธ์ด์ฆˆ๋„ ๋งŽ๊ณ , ๊ฒฝ๊ณ„์„ ์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š์•„ ๊ฐ์ฒด ์˜์—ญ์„ ์ •ํ™•ํžˆ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์ด

bkshin.tistory.com

 

 

 

 

1. ๊ฑฐ๋ฆฌ ๋ณ€ํ™˜ (Distatnce Transformation)

: ์—ฐ์†๋œ ์˜์—ญ์„ ์ฐพ์•„ ๋ถ„ํ• 

: ์ด๋ฏธ์ง€์—์„œ ๋ฌผ์ฒด ์˜์—ญ์„ ์ •ํ™•ํžˆ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฌผ์ฒด ์˜์—ญ์˜ ๋ผˆ๋Œ€๋ฅผ ์ฐพ์•„์•ผ ํ•จ

: ๋ผˆ๋Œ€๋ฅผ ๊ฒ€์ถœํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๊ฐ€ ์™ธ๊ณฝ ๊ฒฝ๊ณ„๋กœ๋ถ€ํ„ฐ ๊ฐ€์žฅ ๋ฉ€๋ฆฌ ๋–จ์–ด์ง„ ๊ณณ์„ ์ฐพ๋Š” ๋ฐฉ๋ฒ•

 

cv2.distanceTransform(src, distanceType, maskSize)
: ๊ฑฐ๋ฆฌ ๋ณ€ํ™˜

 

- src : ์ž…๋ ฅ ์˜์ƒ, ๋ฐ”์ด๋„ˆ๋ฆฌ ์Šค์ผ€์ผ
- distanceType : ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ ๋ฐฉ์‹

  • cv2.DIST_L2
  • cv2.DIST_L1
  • cv2.DIST_L12
  • cv2.DIST_FAIR
  • cv2.DIST_WELSCH
  • cv2.DIST_HUBER

- maskSize : ๊ฑฐ๋ฆฌ ๋ณ€ํ™˜ ์ปค๋„ ํฌ๊ธฐ

# ๊ฑฐ๋ฆฌ ๋ณ€ํ™˜์œผ๋กœ ์ „์‹  ์Šค์ผˆ๋ ˆํ†ค ์ฐพ๊ธฐ
import cv2
import numpy as np

# ์ด๋ฏธ์ง€๋ฅผ ์ฝ์–ด์„œ ๋ฐ”์ด๋„ˆ๋ฆฌ ์Šค์ผ€์ผ๋กœ ๋ณ€ํ™˜
img = cv2.imread('img/full_body.jpg', cv2.IMREAD_GRAYSCALE)
_, biimg = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)

# ๊ฑฐ๋ฆฌ ๋ณ€ํ™˜ ---โ‘ 
dst = cv2.distanceTransform(biimg, cv2.DIST_L2, 3)
# ๊ฑฐ๋ฆฌ ๊ฐ’์„ 0 ~ 255 ๋ฒ”์œ„๋กœ ์ •๊ทœํ™” ---โ‘ก
dst = (dst/(dst.max()-dst.min()) * 255).astype(np.uint8)
# ๊ฑฐ๋ฆฌ ๊ฐ’์— ์“ฐ๋ ˆ์‹œํ™€๋“œ๋กœ ์™„์ „ํ•œ ๋ผˆ๋Œ€ ์ฐพ๊ธฐ ---โ‘ข
skeleton = cv2.adaptiveThreshold(dst, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, \
                                                 cv2.THRESH_BINARY, 7, -3)
# ๊ฒฐ๊ณผ ์ถœ๋ ฅ
cv2.imshow('origin', img)
cv2.imshow('dist', dst)
cv2.imshow('skel', skeleton)
cv2.waitKey(0)
cv2.destroyAllWindows()

&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;์›๋ณธ (๋ฐ”์ด๋„ˆ๋ฆฌ์ด๋ฏธ์ง€)&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0~255๋กœ ์ •๊ทœํ™”ํ•œ ๊ฑฐ๋ฆฌ ๋ณ€ํ™˜&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;๊ฐ€์šด๋ฐ ์ด๋ฏธ์ง€์—์„œ ํ”ฝ์…€๊ฐ’==255 ํ•ด๋‹น๋ถ€๋ถ„ ์ถ”์ถœ

- ๊ฐ€์šด๋ฐ ์ด๋ฏธ์ง€ : ์ •๊ทœํ™” ํ–ˆ๋Š”๋ฐ ์™ธ๊ณฝ ๊ฒฝ๊ณ„๋กœ๋ถ€ํ„ฐ ๋ฉ€์–ด์งˆ์ˆ˜๋ก ํฐ์ƒ‰์ด ์ž˜ ๋ณด์ธ๋‹น

- ์˜ค๋ฅธ์ชฝ ์ด๋ฏธ์ง€ : ํ”ฝ์…€๊ฐ’==255๋งŒ ์ถ”์ถœ ํ–ˆ์Œ. ์ด๋ฏธ์ง€์˜ ๋ผˆ๋Œ€, ๊ฒฝ๊ณ„์—์„œ ๊ฐ€์žฅ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ๋Š” ๋ถ€๋ถ„ ์ถ”์ถœ

=> ๊ฑฐ๋ฆฌ๋ณ€ํ™˜์„ ํ†ตํ•œ ๋ผˆ๋Œ€ ์ถ”์ถœ

 

 

 

 

2. ๋ ˆ์ด๋ธ”๋ง (Labeling)

: ์—ฐ๊ฒฐ๋œ ์š”์†Œ๋ผ๋ฆฌ ๋ถ„๋ฆฌ

: ์ด๋ฏธ์ง€์—์„œ ํ”ฝ์…€ ๊ฐ’์ด 0์œผ๋กœ ๋Š์–ด์ง€์ง€ ์•Š๋Š” ๋ถ€๋ถ„๋ผ๋ฆฌ ๊ฐ™์€ ๊ฐ’์„ ๋ถ€์—ฌํ•ด์„œ ๋ถ„๋ฆฌ

retval, labels = cv2.connectedComponents(src, labels, connectivity=8, ltype)

: ์ด๋ฏธ์ง€ ์ „์ฒด์—์„œ 0์œผ๋กœ ๋Š์–ด์ง€์ง€ ์•Š๋Š” ๋ถ€๋ถ„๋ผ๋ฆฌ ๊ฐ™์€ ๊ฐ’์„ ๋ถ€์—ฌ

: ์—ฐ๊ฒฐ ์š”์†Œ ๋ ˆ์ด๋ธ”๋ง๊ณผ ๊ฐœ์ˆ˜ ๋ฐ˜ํ™˜

 

- src : ์ž…๋ ฅ ์ด๋ฏธ์ง€, ๋ฐ”์ด๋„ˆ๋ฆฌ ์Šค์ผ€์ผ
- labels(optional) : ๋ ˆ์ด๋ธ”๋ง๋œ ์ž…๋ ฅ ์ด๋ฏธ์ง€์™€ ๊ฐ™์€ ํฌ๊ธฐ์˜ ๋ฐฐ์—ด
- connectivity(optional) : ์—ฐ๊ฒฐ์„ฑ์„ ๊ฒ€์‚ฌํ•  ๋ฐฉํ–ฅ ๊ฐœ์ˆ˜(4, 8 ์ค‘ ์„ ํƒ)
- ltype(optional) : ๊ฒฐ๊ณผ ๋ ˆ์ด๋ธ” ๋ฐฐ์—ด dtype
- retval(optional) : ๋ ˆ์ด๋ธ” ๊ฐœ์ˆ˜

 

retval, labels, stats, centroids = cv2.connectedComponentsWithStats(src, labels, stats, centroids, connectivity, ltype)

: ๋ ˆ์ด๋ธ”๋ง๋œ ๊ฐ์ข… ์ƒํƒœ ์ •๋ณด ๋ฐ˜ํ™˜

 

- stats : N x 5 ํ–‰๋ ฌ (N: ๋ ˆ์ด๋ธ” ๊ฐœ์ˆ˜) [x์ขŒํ‘œ, y์ขŒํ‘œ, ํญ, ๋†’์ด, ๋„ˆ๋น„]
- centroids : ๊ฐ ๋ ˆ์ด๋ธ”์˜ ์ค‘์‹ฌ์  ์ขŒํ‘œ, N x 2 ํ–‰๋ ฌ (N: ๋ ˆ์ด๋ธ” ๊ฐœ์ˆ˜)

# ์—ฐ๊ฒฐ๋œ ์˜์—ญ ๋ ˆ์ด๋ธ”๋ง
import cv2
import numpy as np

# ์ด๋ฏธ์ง€ ์ฝ๊ธฐ
img = cv2.imread('img/shape_donut.JPG')
# ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
img2 = np.zeros_like(img)

# ๊ทธ๋ ˆ์ด ์Šค์ผ€์ผ๊ณผ ๋ฐ”์ด๋„ˆ๋ฆฌ ์Šค์ผ€์ผ ๋ณ€ํ™˜
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, th = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# ์—ฐ๊ฒฐ๋œ ์š”์†Œ ๋ ˆ์ด๋ธ”๋ง ์ ์šฉ ---โ‘ 
cnt, labels = cv2.connectedComponents(th)
#retval, labels, stats, cent = cv2.connectedComponentsWithStats(th)

# ๋ ˆ์ด๋ธ” ๊ฐฏ์ˆ˜ ๋งŒํผ ์ˆœํšŒ
for i in range(cnt):
    # ๋ ˆ์ด๋ธ”์ด ๊ฐ™์€ ์˜์—ญ์— ๋žœ๋คํ•œ ์ƒ‰์ƒ ์ ์šฉ ---โ‘ก
    img2[labels==i] =  [int(j) for j in np.random.randint(0,255, 3)]

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

์—ฐ๊ฒฐ๋œ ๋ถ€๋ถ„๋ผ๋ฆฌ ๊ฐ™์€ ์ƒ‰์ƒ! ์˜ค ์ƒ‰๊น” ๊ณฑ๋‹ค ๊ณ ์™€

 

- ์—ฐ๊ฒฐ๋œ ๋ถ€๋ถ„๋ผ๋ฆฌ ๊ฐ™์€ ์ƒ‰์ƒ์ด ์น ํ•ด์ง

- cv2.connectedComponents() ํ•จ์ˆ˜๋Š” ์ด๋ฏธ์ง€ ์ „์ฒด์—์„œ 0์œผ๋กœ ๋Š์–ด์ง€์ง€ ์•Š๋Š” ๋ถ€๋ถ„๋ผ๋ฆฌ ๊ฐ™์€ ๊ฐ’์„ ๋ถ€์—ฌ

- ๋ฐ˜ํ™˜๋œ ๊ฒฐ๊ณผ๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ๊ฐ™์€ ๊ฐ’๋ผ๋ฆฌ๋Š” ๊ฐ™์€ ์ƒ‰์ƒ

 

 

 

 

 

3. ์ƒ‰ ์ฑ„์šฐ๊ธฐ

retval, img, mask, rect = cv2.floodFill(img, mask, seed, newVal, loDiff, upDiff, flags)
: ์—ฐ์†๋˜๋Š” ์˜์—ญ์— ๊ฐ™์€ ์ƒ‰์ƒ์„ ์ฑ„์›Œ ๋„ฃ๋Š” ๊ธฐ๋Šฅ

 

- img : ์ž…๋ ฅ ์ด๋ฏธ์ง€, 1 ๋˜๋Š” 3์ฑ„๋„
- mask : ์ž…๋ ฅ ์ด๋ฏธ์ง€๋ณด๋‹ค 2 x 2 ํ”ฝ์…€์ด ๋” ํฐ ๋ฐฐ์—ด, 0์ด ์•„๋‹Œ ์˜์—ญ์„ ๋งŒ๋‚˜๋ฉด ์ฑ„์šฐ๊ธฐ ์ค‘์ง€
- seed : ์ฑ„์šฐ๊ธฐ ์‹œ์ž‘ํ•  ์ขŒํ‘œ
- newVal : ์ฑ„์šฐ๊ธฐ์— ์‚ฌ์šฉํ•  ์ƒ‰์ƒ ๊ฐ’
- loDiff, upDiff(optional) : ์ฑ„์šฐ๊ธฐ ์ง„ํ–‰์„ ๊ฒฐ์ •ํ•  ์ตœ์†Œ/์ตœ๋Œ€ ์ฐจ์ด ๊ฐ’
- flags(optional) : ์ฑ„์šฐ๊ธฐ ๋ฐฉ์‹ ์„ ํƒ

  • cv2.FLOODFILL_MASK_ONLY : img๊ฐ€ ์•„๋‹Œ mask์—๋งŒ ์ฑ„์šฐ๊ธฐ ์ ์šฉ
  • cv2.FLOODFILL_FIXED_RANGE : ์ด์›ƒ ํ”ฝ์…€์ด ์•„๋‹Œ seed ํ”ฝ์…€๊ณผ ๋น„๊ต

- retval : ์ฑ„์šฐ๊ธฐ ํ•œ ํ”ฝ์…€์˜ ๊ฐœ์ˆ˜
- rect : ์ฑ„์šฐ๊ธฐ๊ฐ€ ์ด๋ฃจ์–ด์ง„ ์˜์—ญ์„ ๊ฐ์‹ธ๋Š” ์‚ฌ๊ฐํ˜•

 

: img ์ด๋ฏธ์ง€์˜ seed ์ขŒํ‘œ์—์„œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ newVal์˜ ๊ฐ’์œผ๋กœ ์ฑ„์šฐ๊ธฐ๋ฅผ ์‹œ์ž‘

: ์ด์›ƒํ•˜๋Š” ํ”ฝ์…€์— ์ฑ„์šฐ๊ธฐ๋ฅผ ๊ณ„์†ํ•˜๋ ค๋ฉด ํ˜„์žฌ ํ”ฝ์…€์ด ์ด์›ƒ ํ”ฝ์…€์˜ loDiff๋ฅผ ๋บ€ ๊ฐ’๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™๊ณ 

upDiff๋ฅผ ๋”ํ•œ ๊ฐ’๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™๊ธฐ

=> ์ด์›ƒ ํ”ฝ์…€ - loDiff <= ํ˜„์žฌ ํ”ฝ์…€ <= ์ด์›ƒ ํ”ฝ์…€ + upDiff

: (๋งŒ์•ฝ loDiff์™€ upDiff๋ฅผ ์ƒ๋žตํ•˜๋ฉด seed์˜ ํ”ฝ์…€ ๊ฐ’๊ณผ ๊ฐ™์€ ๊ฐ’์„ ๊ฐ–๋Š” ์ด์›ƒ ํ”ฝ์…€๋งŒ ์ฑ„์šฐ๊ธฐ๋ฅผ ์ง„ํ–‰)

: flags์— cv2.FLOODFILL_FIXED_RANGE๊ฐ€ ์ „๋‹ฌ๋˜๋ฉด ์ด์›ƒ ํ”ฝ์…€์ด ์•„๋‹Œ seed ํ”ฝ์…€๊ณผ ๋น„๊ตํ•˜๋ฉฐ ์ƒ‰์„ ์ฑ„์šฐ๊ธฐ

: flags์— cv2.FLOODFILL_MASK_ONLY๊ฐ€ ์ „๋‹ฌ๋˜๋ฉด img์— ์ฑ„์šฐ๊ธฐ๋ฅผ ํ•˜์ง€ ์•Š๊ณ  mask์—๋งŒ ์ฑ„์šฐ๊ธฐ

# ๋งˆ์šฐ์Šค๋กœ ์ƒ‰ ์ฑ„์šฐ๊ธฐ
import cv2
import numpy as np

img = cv2.imread('img/taekwonv1.jpg')
rows, cols = img.shape[:2]
# ๋งˆ์Šคํฌ ์ƒ์„ฑ, ์›๋ž˜ ์ด๋ฏธ์ง€ ๋ณด๋‹ค 2ํ”ฝ์…€ ํฌ๊ฒŒ ---โ‘ 
mask = np.zeros((rows+2, cols+2), np.uint8)
# ์ฑ„์šฐ๊ธฐ์— ์‚ฌ์šฉํ•  ์ƒ‰ ---โ‘ก
newVal = (255,255,255)
# ์ตœ์†Œ ์ตœ๋Œ€ ์ฐจ์ด ๊ฐ’ ---โ‘ข
loDiff, upDiff = (10,10,10), (10,10,10)

# ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
def onMouse(event, x, y, flags, param):
    global mask, img
    if event == cv2.EVENT_LBUTTONDOWN:
        seed = (x,y)
        # ์ƒ‰ ์ฑ„์šฐ๊ธฐ ์ ์šฉ ---โ‘ฃ
        retval = cv2.floodFill(img, mask, seed, newVal, loDiff, upDiff)
        # ์ฑ„์šฐ๊ธฐ ๋ณ€๊ฒฝ ๊ฒฐ๊ณผ ํ‘œ์‹œ ---โ‘ค
        cv2.imshow('img', img)

# ํ™”๋ฉด ์ถœ๋ ฅ
cv2.imshow('img', img)
cv2.setMouseCallback('img', onMouse)
cv2.waitKey(0)
cv2.destroyAllWindows()

ํŠน์ •์˜์—ญ ๋งˆ์šฐ์Šค๋กœ ํฐ์ƒ‰ ์ฑ„์šฐ๊ธฐ

- mask ๋Š” ์›๋ณธ ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋ณด๋‹ค ๋†’์ด, ๋„ˆ๋น„๋ฅผ 2๋ฐฐ ํฌ๊ฒŒ ๋งŒ๋“ค๊ธฐ

- ์ฑ„์šฐ๊ธฐ ์ƒ‰์€ (255, 255, 255) ํฐ์ƒ‰ ์‚ฌ์šฉ

- loDiff์™€ upDiff, ์ด์›ƒํ•œ ํ”ฝ์…€๊ณผ์˜ ์ตœ์†Œ/์ตœ๋Œ€ ์ฐจ์ด ๊ฐ’์„ ๊ฐ 10

 

 

 

 

 

4. ์›Œํ„ฐ์…ฐ๋“œ (Watershed)

: ๊ฐ•๋ฌผ์ด ํ•œ ์ค„๊ธฐ๋กœ ํ๋ฅด๋‹ค๊ฐ€ ๊ฐˆ๋ผ์ง€๋Š” ๊ฒฝ๊ณ„์ธ ๋ถ„์ˆ˜๋ น

: ์ƒ‰ ์ฑ„์šฐ๊ธฐ(flood fill)๊ณผ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ์—ฐ์†๋œ ์˜์—ญ์„ ์ฐพ๋Š” ๊ฒƒ

: seed๋ฅผ ํ•˜๋‚˜๊ฐ€ ์•„๋‹Œ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ณ  ์ด๋ฅผ ๋งˆ์ปค

 

markers = cv2.watershed(img, markers)
- img : ์ž…๋ ฅ ์ด๋ฏธ์ง€
- markers : ๋งˆ์ปค, ์ž…๋ ฅ ์ด๋ฏธ์ง€์™€ ํฌ๊ธฐ๊ฐ€ ๊ฐ™์€ 1์ฐจ์› ๋ฐฐ์—ด(int32)

 

: markers๋Š” ์ž…๋ ฅ ์ด๋ฏธ์ง€์™€ ํ–‰๊ณผ ์—ด ํฌ๊ธฐ๊ฐ€ ๊ฐ™์€ 1์ฐจ์› ๋ฐฐ์—ด๋กœ ์ „๋‹ฌ

: markers์˜ ๊ฐ’์€ ๊ฒฝ๊ณ„๋ฅผ ์ฐพ๊ณ ์ž ํ•˜๋Š” ํ”ฝ์…€ ์˜์—ญ์€ -1์„ ๊ฐ–๊ฒŒ ํ•˜๊ณ 

๋‚˜๋จธ์ง€ ์—ฐ๊ฒฐ๋œ ์˜์—ญ์— ๋Œ€ํ•ด์„œ๋Š” ๋™์ผํ•œ ์ •์ˆ˜ ๊ฐ’์„ ๊ฐ–๊ฒŒ ํ•จ

# ๋งˆ์šฐ์Šค์™€ ์›Œํ„ฐ์…ฐ๋“œ๋กœ ๋ฐฐ๊ฒฝ ๋ถ„๋ฆฌ
import cv2
import numpy as np

img = cv2.imread('img/jadu.jpg')
rows, cols = img.shape[:2]
img_draw = img.copy()

# ๋งˆ์ปค ์ƒ์„ฑ, ๋ชจ๋“  ์š”์†Œ๋Š” 0์œผ๋กœ ์ดˆ๊ธฐํ™” ---โ‘ 
marker = np.zeros((rows, cols), np.int32)
markerId = 1        # ๋งˆ์ปค ์•„์ด๋””๋Š” 1์—์„œ ์‹œ์ž‘
colors = []         # ๋งˆ์ปค ์„ ํƒํ•œ ์˜์—ญ ์ƒ‰์ƒ ์ €์žฅํ•  ๊ณต๊ฐ„
isDragging = False  # ๋“œ๋ž˜๊ทธ ์—ฌ๋ถ€ ํ™•์ธ ๋ณ€์ˆ˜

# ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
def onMouse(event, x, y, flags, param):
    global img_draw, marker, markerId, isDragging
    if event == cv2.EVENT_LBUTTONDOWN:  # ์™ผ์ชฝ ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ ๋‹ค์šด, ๋“œ๋ž˜๊ทธ ์‹œ์ž‘ 
        isDragging = True
        # ๊ฐ ๋งˆ์ปค์˜ ์•„์ด๋””์™€ ํ˜„ ์œ„์น˜์˜ ์ƒ‰์ƒ ๊ฐ’์„ ์Œ์œผ๋กœ ๋งคํ•‘ํ•ด์„œ ์ €์žฅ 
        colors.append((markerId, img[y,x]))
    elif event == cv2.EVENT_MOUSEMOVE:  # ๋งˆ์šฐ์Šค ์›€์ง์ž„
        if isDragging:                  # ๋“œ๋ž˜๊ทธ ์ง„ํ–‰ ์ค‘
            # ๋งˆ์šฐ์Šค ์ขŒํ‘œ์— ํ•ด๋‹นํ•˜๋Š” ๋งˆ์ปค์˜ ์ขŒํ‘œ์— ๋™์ผํ•œ ๋งˆ์ปค ์•„์ด๋””๋กœ ์ฑ„์›Œ ๋„ฃ๊ธฐ ---โ‘ก
            marker[y,x] = markerId
            # ๋งˆ์ปค ํ‘œ์‹œํ•œ ๊ณณ์„ ๋นจ๊ฐ•์ƒ‰์ ์œผ๋กœ ํ‘œ์‹œํ•ด์„œ ์ถœ๋ ฅ
            cv2.circle(img_draw, (x,y), 3, (0,0,255), -1)
            cv2.imshow('watershed', img_draw)
    elif event == cv2.EVENT_LBUTTONUP:  # ์™ผ์ชฝ ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ ์—…
        if isDragging:                  
            isDragging = False          # ๋“œ๋ž˜๊ทธ ์ค‘์ง€
            # ๋‹ค์Œ ๋งˆ์ปค ์„ ํƒ์„ ์œ„ํ•ด ๋งˆ์ปค ์•„์ด๋”” ์ฆ๊ฐ€ ---โ‘ข
            markerId +=1
    elif event == cv2.EVENT_RBUTTONDOWN: # ์˜ค๋ฅธ์ชฝ ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ ๋ˆ„๋ฆ„
            # ๋ชจ์•„ ๋†“์€ ๋งˆ์ปค๋ฅผ ์ด์šฉํ•ด์„œ ์›Œํ„ฐ ์‰๋“œ ์ ์šฉ ---โ‘ฃ
            cv2.watershed(img, marker)
            # ๋งˆ์ปค์— -1๋กœ ํ‘œ์‹œ๋œ ๊ฒฝ๊ณ„๋ฅผ ์ดˆ๋ก์ƒ‰์œผ๋กœ ํ‘œ์‹œ  ---โ‘ค
            img_draw[marker == -1] = (0,255,0)
            for mid, color in colors: # ์„ ํƒํ•œ ๋งˆ์ปค ์•„์ด๋”” ๊ฐฏ์ˆ˜ ๋งŒํผ ๋ฐ˜๋ณต
                # ๊ฐ™์€ ๋งˆ์ปค ์•„์ด๋”” ๊ฐ’์„ ๊ฐ–๋Š” ์˜์—ญ์„ ๋งˆ์ปค ์„ ํƒํ•œ ์ƒ‰์ƒ์œผ๋กœ ์ฑ„์šฐ๊ธฐ ---โ‘ฅ
                img_draw[marker==mid] = color
            cv2.imshow('watershed', img_draw) # ํ‘œ์‹œํ•œ ๊ฒฐ๊ณผ ์ถœ๋ ฅ

# ํ™”๋ฉด ์ถœ๋ ฅ
cv2.imshow('watershed', img)
cv2.setMouseCallback('watershed', onMouse)
cv2.waitKey(0)
cv2.destroyAllWindows()

๋ˆ„๊ตฌ๊ฒŒ~

- 1์€ ๋ฐฐ๊ฒฝ, 2๋Š” ์ „๊ฒฝ

- ์ด๋ฏธ์ง€์˜ ์ „๊ฒฝ ๋ฐฐ๊ฒฝ ๋ถ„๋ฆฌ !

- cv2.watershed(img, marker)

 => ์›Œํ„ฐ์…ฐ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๊ฒฝ๊ณ„์— ํ•ด๋‹นํ•˜๋Š” ์˜์—ญ์€ -1๋กœ ์ฑ„์›Œ์ง€๊ณ  ์ „๊ฒฝ์€ 1, ๋ฐฐ๊ฒฝ์€ 2๋กœ ์ฑ„์›Œ์ง„๋‹ค

 

 

 

 

 

5. ๊ทธ๋žฉ์ปท (Graph Cut)

: ์‚ฌ์šฉ์ž๊ฐ€ ์ „๊ฒฝ(๋ฐฐ๊ฒฝ์ด ์•„๋‹Œ ๋ถ€๋ถ„)์œผ๋กœ ๋ถ„๋ฆฌํ•  ๋ถ€๋ถ„์— ์‚ฌ๊ฐํ˜• ํ‘œ์‹œ๋ฅผ ํ•ด์ฃผ๋ฉด

์ „๊ฒฝ๊ณผ ๋ฐฐ๊ฒฝ์˜ ์ƒ‰์ƒ ๋ถ„ํฌ๋ฅผ ์ถ”์ •ํ•ด์„œ ๋™์ผํ•œ ๋ ˆ์ด๋ธ”์„ ๊ฐ€์ง„ ์—ฐ๊ฒฐ๋œ ์˜์—ญ์—์„œ ์ „๊ฒฝ๊ณผ ๋ฐฐ๊ฒฝ์„ ๋ถ„๋ฆฌ

 

mask, bgdModel, fgdModel = cv2.grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode)
- img : ์ž…๋ ฅ ์ด๋ฏธ์ง€
- mask : ์ž…๋ ฅ ์ด๋ฏธ์ง€์™€ ํฌ๊ธฐ๊ฐ€ ๊ฐ™์€ 1 ์ฑ„๋„ ๋ฐฐ์—ด, ๋ฐฐ๊ฒฝ๊ณผ ์ „๊ฒฝ์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฐ’์„ ์ €์žฅ

  • cv2.GC_BGD : ํ™•์‹คํ•œ ๋ฐฐ๊ฒฝ(0)
  • cv2.GC_FGD : ํ™•์‹คํ•œ ์ „๊ฒฝ(1)
  • cv2.GC_PR_BGD : ์•„๋งˆ๋„ ๋ฐฐ๊ฒฝ(2)
  • cv2.GC_PR_FGD : ์•„๋งˆ๋„ ์ „๊ฒฝ(3)

- rect : ์ „๊ฒฝ์ด ์žˆ์„ ๊ฒƒ์œผ๋กœ ์ถ”์ธก๋˜๋Š” ์˜์—ญ์˜ ์‚ฌ๊ฐํ˜• ์ขŒํ‘œ, ํŠœํ”Œ (x1, y1, x2, y2)
- bgdModel, fgdModel : ํ•จ์ˆ˜ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ž„์‹œ ๋ฐฐ์—ด ๋ฒ„ํผ (์žฌ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์ˆ˜์ •ํ•˜์ง€ ๋ง ๊ฒƒ)
- iterCount : ๋ฐ˜๋ณต ํšŸ์ˆ˜
- mode(optional) : ๋™์ž‘ ๋ฐฉ๋ฒ•

  • cv2.GC_INIT_WITH_RECT : rect์— ์ง€์ •ํ•œ ์ขŒํ‘œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋žฉ์ปท ์ˆ˜ํ–‰
  • cv2.GC_INIT_WITH_MASK : mask์— ์ง€์ •ํ•œ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋žฉ์ปท ์ˆ˜ํ–‰
  • cv2.GC_EVAL : ์žฌ์‹œ๋„

1) mode์— cv2.GC_INIT_WITH_RECT๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ rect์— ์ „๋‹ฌํ•œ ์‚ฌ๊ฐํ˜• ์ขŒํ‘œ๋ฅผ ๊ฐ€์ง€๊ณ  ์ „๊ฒฝ๊ณผ ๋ฐฐ๊ฒฝ์„ ๋ถ„๋ฆฌ

2) ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ mask์— ํ• ๋‹นํ•ด ๋ฐ˜ํ™˜

3) mask์— ํ• ๋‹น๋ฐ›์€ ๊ฐ’์ด 0๊ณผ 1์ด๋ฉด ํ™•์‹คํ•œ ๋ฐฐ๊ฒฝ, ์ „๊ฒฝ์„ ์˜๋ฏธํ•˜๊ณ ,

2์™€ 3์ด๋ฉด ์•„๋งˆ๋„ ๋ฐฐ๊ฒฝ, ์ „๊ฒฝ์ผ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค

4) 1์ฐจ์ ์œผ๋กœ ๋ฐฐ๊ฒฝ๊ณผ ์ „๊ฒฝ์„ ๊ตฌ๋ถ„ํ•œ ๋’ค mode์— cv2.GC_INIT_WITH_MASK๋ฅผ ์ง€์ •ํ•ด์„œ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๋ฉด ์ข€ ๋” ์ •ํ™•ํ•œ mas

5) bgdModel๊ณผ fgdModel์€ ํ•จ์ˆ˜๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์—ฐ์‚ฐ์— ์‚ฌ์šฉํ•˜๋Š” ์ž„์‹œ ๋ฐฐ์—ด๋กœ ๋‹ค์Œ ํ˜ธ์ถœ ์‹œ

์ด์ „ ์—ฐ์‚ฐ์„ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด ์žฌ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๊ทธ ๋‚ด์šฉ์„ ์ˆ˜์ •ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค

# ๋งˆ์šฐ์Šค์™€ ๊ทธ๋žฉ์ปท์œผ๋กœ ๋ฐฐ๊ฒฝ๊ณผ ์ „๊ฒฝ ๋ถ„๋ฆฌ
import cv2
import numpy as np

img = cv2.imread('img/taekwonv1.jpg')
img_draw = img.copy()
mask = np.zeros(img.shape[:2], dtype=np.uint8)  # ๋งˆ์Šคํฌ ์ƒ์„ฑ
rect = [0,0,0,0]    # ์‚ฌ๊ฐํ˜• ์˜์—ญ ์ขŒํ‘œ ์ดˆ๊ธฐํ™”
mode = cv2.GC_EVAL  # ๊ทธ๋žฉ์ปท ์ดˆ๊ธฐ ๋ชจ๋“œ
# ๋ฐฐ๊ฒฝ ๋ฐ ์ „๊ฒฝ ๋ชจ๋ธ ๋ฒ„ํผ
bgdmodel = np.zeros((1,65),np.float64)
fgdmodel = np.zeros((1,65),np.float64)

# ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
def onMouse(event, x, y, flags, param):
    global mouse_mode, rect, mask, mode
    if event == cv2.EVENT_LBUTTONDOWN : # ์™ผ์ชฝ ๋งˆ์šฐ์Šค ๋ˆ„๋ฆ„
        if flags <= 1: # ์•„๋ฌด ํ‚ค๋„ ์•ˆ ๋ˆŒ๋ €์œผ๋ฉด
            mode = cv2.GC_INIT_WITH_RECT # ๋“œ๋ž˜๊ทธ ์‹œ์ž‘, ์‚ฌ๊ฐํ˜• ๋ชจ๋“œ ---โ‘ 
            rect[:2] = x, y # ์‹œ์ž‘ ์ขŒํ‘œ ์ €์žฅ
    # ๋งˆ์šฐ์Šค๊ฐ€ ์›€์ง์ด๊ณ  ์™ผ์ชฝ ๋ฒ„ํŠผ์ด ๋ˆŒ๋Ÿฌ์ง„ ์ƒํƒœ
    elif event == cv2.EVENT_MOUSEMOVE and flags & cv2.EVENT_FLAG_LBUTTON :
        if mode == cv2.GC_INIT_WITH_RECT: # ๋“œ๋ž˜๊ทธ ์ง„ํ–‰ ์ค‘ ---โ‘ก
            img_temp = img.copy()
            # ๋“œ๋ž˜๊ทธ ์‚ฌ๊ฐํ˜• ํ™”๋ฉด์— ํ‘œ์‹œ
            cv2.rectangle(img_temp, (rect[0], rect[1]), (x, y), (0,255,0), 2)
            cv2.imshow('img', img_temp)
        elif flags > 1: # ํ‚ค๊ฐ€ ๋ˆŒ๋Ÿฌ์ง„ ์ƒํƒœ
            mode = cv2.GC_INIT_WITH_MASK    # ๋งˆ์Šคํฌ ๋ชจ๋“œ ---โ‘ข
            if flags & cv2.EVENT_FLAG_CTRLKEY :# ์ปจํŠธ๋กค ํ‚ค, ๋ถ„๋ช…ํ•œ ์ „๊ฒฝ
                # ํฐ์ƒ‰ ์  ํ™”๋ฉด์— ํ‘œ์‹œ
                cv2.circle(img_draw,(x,y),3, (255,255,255),-1)
                # ๋งˆ์Šคํฌ์— GC_FGD๋กœ ์ฑ„์šฐ๊ธฐ      ---โ‘ฃ
                cv2.circle(mask,(x,y),3, cv2.GC_FGD,-1)
            if flags & cv2.EVENT_FLAG_SHIFTKEY : # ์‰ฌํ”„ํŠธํ‚ค, ๋ถ„๋ช…ํ•œ ๋ฐฐ๊ฒฝ
                # ๊ฒ€์ •์ƒ‰ ์  ํ™”๋ฉด์— ํ‘œ์‹œ
                cv2.circle(img_draw,(x,y),3, (0,0,0),-1)
                # ๋งˆ์Šคํฌ์— GC_BGD๋กœ ์ฑ„์šฐ๊ธฐ      ---โ‘ค
                cv2.circle(mask,(x,y),3, cv2.GC_BGD,-1)
            cv2.imshow('img', img_draw) # ๊ทธ๋ ค์ง„ ๋ชจ์Šต ํ™”๋ฉด์— ์ถœ๋ ฅ
    elif event == cv2.EVENT_LBUTTONUP: # ๋งˆ์šฐ์Šค ์™ผ์ชฝ ๋ฒ„ํŠผ ๋—€ ์ƒํƒœ ---โ‘ฅ
        if mode == cv2.GC_INIT_WITH_RECT : # ์‚ฌ๊ฐํ˜• ๊ทธ๋ฆฌ๊ธฐ ์ข…๋ฃŒ
            rect[2:] =x, y # ์‚ฌ๊ฐํ˜• ๋งˆ์ง€๋ง‰ ์ขŒํ‘œ ์ˆ˜์ง‘
            # ์‚ฌ๊ฐํ˜• ๊ทธ๋ ค์„œ ํ™”๋ฉด์— ์ถœ๋ ฅ ---โ‘ฆ
            cv2.rectangle(img_draw, (rect[0], rect[1]), (x, y), (255,0,0), 2)
            cv2.imshow('img', img_draw)
        # ๊ทธ๋žฉ์ปท ์ ์šฉ ---โ‘ง
        cv2.grabCut(img, mask, tuple(rect), bgdmodel, fgdmodel, 1, mode)
        img2 = img.copy()
        # ๋งˆ์Šคํฌ์— ํ™•์‹คํ•œ ๋ฐฐ๊ฒฝ, ์•„๋งˆ๋„ ๋ฐฐ๊ฒฝ์œผ๋กœ ํ‘œ์‹œ๋œ ์˜์—ญ์„ 0์œผ๋กœ ์ฑ„์šฐ๊ธฐ
        img2[(mask==cv2.GC_BGD) | (mask==cv2.GC_PR_BGD)] = 0
        cv2.imshow('grabcut', img2) # ์ตœ์ข… ๊ฒฐ๊ณผ ์ถœ๋ ฅ
        mode = cv2.GC_EVAL # ๊ทธ๋žฉ์ปท ๋ชจ๋“œ ๋ฆฌ์…‹
# ์ดˆ๊ธฐ ํ™”๋ฉด ์ถœ๋ ฅ ๋ฐ ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ ๋“ฑ๋ก
cv2.imshow('img', img)
cv2.setMouseCallback('img', onMouse)
while True:    
    if cv2.waitKey(0) & 0xFF == 27 : # esc
        break
cv2.destroyAllWindows()

๊ทธ๋žฉ์ปท์„ ํ™œ์šฉํ•˜์—ฌ ๋ฐฐ๊ฒฝ์„ ๋ถ„๋ฆฌ

- ๊ทธ๋žฉ์ปท์„ ํ™œ์šฉํ•˜์—ฌ ๋ฐฐ๊ฒฝ์„ ๋ถ„๋ฆฌ

- ๋งˆ์šฐ์Šค๋กœ ๋“œ๋ž˜๊ทธ(์‚ฌ๊ฐํ˜•)ํ•˜์—ฌ ์ „๊ฒฝ ์™ธ๊ณฝ ์˜์—ญ์„ ํ‘œ์‹œ

=> 1์ฐจ์ ์œผ๋กœ ๋ฐฐ๊ฒฝ๊ณผ ์ „๊ฒฝ์ด ๋ถ„๋ฆฌ

- ๋ฐฐ๊ฒฝ์„ ์ถ”๊ฐ€๋กœ ์ œ๊ฑฐํ•˜๊ณ  ์‹ถ์œผ๋ฉด ์›๋ณธ ์ด๋ฏธ์ง€์— ์‰ฌํ”„ํŠธ ํ‚ค๋ฅผ ๋ˆ„๋ฅธ ์ƒํƒœ๋กœ ๋งˆ์šฐ์Šค๋กœ ๊ฒ€์€์ƒ‰ ์„ ์„ ๊ทธ์–ด์ฃผ๊ธฐ

- ์ž˜๋ชป ์ œ๊ฑฐ๋œ ์ „๊ฒฝ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์œผ๋ฉด ์›๋ณธ ์ด๋ฏธ์ง€์— ์ปจํŠธ๋กคํ‚ค๋ฅผ ๋ˆ„๋ฅธ ์ƒํƒœ๋กœ ๋งˆ์šฐ์Šค๋กœ ํฐ์ƒ‰ ์„ ์„ ๊ทธ์–ด์ฃผ๊ธฐ

-  cv2.GC_FGD๋Š” ํ™•์‹คํ•œ ์ „๊ฒฝ, cv2.GC_BGD๋Š” ํ™•์‹คํ•œ ๋ฐฐ๊ฒฝ

# ๋งˆ์Šคํฌ์— ํ™•์‹คํ•œ ๋ฐฐ๊ฒฝ, ์•„๋งˆ๋„ ๋ฐฐ๊ฒฝ์œผ๋กœ ํ‘œ์‹œ๋œ ์˜์—ญ์„ 0์œผ๋กœ ์ฑ„์šฐ๊ธฐ (๋ฐฐ๊ฒฝ์ œ๊ฑฐ)

img2[(mask==cv2.GC_BGD) | (mask==cv2.GC_PR_BGD)] = 0

 

 

 

 

 

6. ํ‰๊ท  ์ด๋™ ํ•„ํ„ฐ

: ๋ฌผ๊ฐ์œผ๋กœ ๊ทธ๋ฆผ์„ ๊ทธ๋ฆฐ ๊ฒƒ๊ณผ ๊ฐ™์ด ์ด๋ฏธ์ง€๋ฅผ ๋ฐ”๊พธ๊ธฐ

 

dst = cv2.pyrMeanShiftFiltering(src, sp, sr, dst, maxLevel, termcrit)
- src : ์ž…๋ ฅ ์ด๋ฏธ์ง€
- sp : ๊ณต๊ฐ„ ์œˆ๋„ ๋ฐ˜์ง€๋ฆ„ ํฌ๊ธฐ
- sr : ์ƒ‰์ƒ ์œˆ๋„ ๋ฐ˜์ง€๋ฆ„ ํฌ๊ธฐ
- maxLevel(optional) : ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ ์ตœ๋Œ€ ๋ ˆ๋ฒจ
- termcrit(optional) : ๋ฐ˜๋ณต ์ค‘์ง€ ์š”๊ฑด

  • cv2.TERM_CRITERIA_EPS : ์ •ํ™•๋„๊ฐ€ ์ตœ์†Œ ์ •ํ™•๋„(epsilon) ๋ณด๋‹ค ์ž‘์•„์ง€๋ฉด ์ค‘์ง€
  • cv2.TERM_CRITERIA_MAX_ITER : ์ตœ๋Œ€ ๋ฐ˜๋ณต ํšŸ์ˆ˜(max_iter)์— ๋„๋‹ฌํ•˜๋ฉด ์ค‘์ง€
  • -> default epsilon=1, max_iter=5

: ๋‚ด๋ถ€์ ์œผ๋กœ ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ์ž‘์€ ์ด๋ฏธ์ง€์˜ ํ‰๊ท  ์ด๋™ ๊ฒฐ๊ณผ๋ฅผ ํฐ ์ด๋ฏธ์ง€์— ์ ์šฉ

: sp ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ํ‰๊ท  ์ด๋™(MeanShift)์— ์‚ฌ์šฉํ•  ์œˆ๋„ ํฌ๊ธฐ,

๋ช‡ ํ”ฝ์…€์”ฉ ๋ฌถ์–ด์„œ ํ‰๊ท ์„ ๋‚ด์–ด ์ด๋™ํ• ์ง€๋ฅผ ๊ฒฐ์ •

sr ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์ƒ‰์ƒ ์œˆ๋„ ํฌ๊ธฐ๋กœ ์ƒ‰์ƒ ๊ฐ’์˜ ์ฐจ์ด ๋ฒ”์œ„๋ฅผ ์ง€์ •

ํ‰๊ท ์„ ๊ณ„์‚ฐํ•  ๋•Œ ๊ฐ’์˜ ์ฐจ์ด๊ฐ€ sr ๊ฐ’์˜ ๋ฒ”์œ„ ์•ˆ์— ์žˆ๋Š” ํ”ฝ์…€๋งŒ์„ ๋Œ€์ƒ

sr์ด ๋„ˆ๋ฌด ์ž‘์œผ๋ฉด ์›๋ณธ๊ณผ ๋ณ„ ์ฐจ์ด๊ฐ€ ์—†๊ณ , ๋„ˆ๋ฌด ํฌ๋ฉด ์›๋ณธ๊ณผ ๋งŽ์ด ๋‹ฌ๋ผ์ง

: maxLevel์€ ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ ์ตœ๋Œ€ ๋ ˆ๋ฒจ

0๋ณด๋‹ค ํฌ๋ฉด ๊ทธ ๊ฐ’๋งŒํผ ์ž‘์€ ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ๋กœ ํ‰๊ท  ์ด๋™ํ•ด์„œ ์–ป์€ ๊ฒฐ๊ณผ๋ฅผ ์ ์šฉ

๊ฐ’์ด ํด์ˆ˜๋ก ์†๋„๊ฐ€ ๋นจ๋ผ์ง€์ง€๋งŒ ์˜์—ญ๊ณผ ์ƒ‰์ƒ์ด ๊ฑฐ์น ์–ด์ง

: termcrit์€ ๋ฐ˜๋ณต์„ ์ค‘์ง€ํ•  ๊ธฐ์ค€์„ ์ง€์ •

# ํ‰๊ท  ์ด๋™ ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜ ํ•„ํ„ฐ
import cv2
import numpy as np

img = cv2.imread('img/taekwonv1.jpg')
# ํŠธ๋ž™๋ฐ” ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
def onChange(x):
    #sp, sr, level ์„ ํƒ ๊ฐ’ ์ˆ˜์ง‘
    sp = cv2.getTrackbarPos('sp', 'img')
    sr = cv2.getTrackbarPos('sr', 'img')
    lv = cv2.getTrackbarPos('lv', 'img')

    # ํ‰๊ท  ์ด๋™ ํ•„ํ„ฐ ์ ์šฉ ---โ‘ 
    mean = cv2.pyrMeanShiftFiltering(img, sp, sr, None, lv)
    # ๋ณ€ํ™˜ ์ด๋ฏธ์ง€ ์ถœ๋ ฅ
    cv2.imshow('img', np.hstack((img, mean)))

# ์ดˆ๊ธฐ ํ™”๋ฉด ์ถœ๋ ฅ
cv2.imshow('img', np.hstack((img, img)))
# ํŠธ๋ž™๋ฐ” ์ด๋ฒคํŠธ ํ•จ์ˆ˜ ์—ฐ๊ฒฐ
cv2.createTrackbar('sp', 'img', 0,100, onChange)
cv2.createTrackbar('sr', 'img', 0,100, onChange)
cv2.createTrackbar('lv', 'img', 0,5, onChange)
cv2.waitKey(0)
cv2.destroyAllWindows()

ํ‰๊ท  ์ด๋™ ํ•„ํ„ฐ ์ ์šฉ ์ด๋ฏธ์ง€

- sp ๋ฅผ ๋†’์ž„ => ํ‰๊ท  ์ด๋™์— ์‚ฌ์šฉํ•  ์œˆ๋„ ํฌ๊ธฐ

- sr ์„ ๋†’์ž„ => ๋„ˆ๋ฌด ํฌ๋ฉด ์›๋ณธ๊ณผ ๋‹ฌ๋ผ์ง

- lr (maxLavel) => ํด์ˆ˜๋ก ์˜์—ญ, ์ƒ‰์ƒ ๊ฑฐ์น ์–ด์ง

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