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

[v0.21]์˜์ƒ์ฒ˜๋ฆฌ_๋ชจํด๋กœ์ง€(Morphology) ์—ฐ์‚ฐ ๋ณธ๋ฌธ

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

[v0.21]์˜์ƒ์ฒ˜๋ฆฌ_๋ชจํด๋กœ์ง€(Morphology) ์—ฐ์‚ฐ

์ง•์ง•์•ŒํŒŒ์นด 2022. 1. 11. 01:35
728x90
๋ฐ˜์‘ํ˜•

220110 ์ž‘์„ฑ

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

https://bkshin.tistory.com/entry/OpenCV-19-%EB%AA%A8%ED%8F%B4%EB%A1%9C%EC%A7%80Morphology-%EC%97%B0%EC%82%B0-%EC%B9%A8%EC%8B%9D-%ED%8C%BD%EC%B0%BD-%EC%97%B4%EB%A6%BC-%EB%8B%AB%ED%9E%98-%EA%B7%B8%EB%A0%88%EB%94%94%EC%96%B8%ED%8A%B8-%ED%83%91%ED%96%87-%EB%B8%94%EB%9E%99%ED%96%87?category=1148027 

 

OpenCV - 19. ๋ชจํด๋กœ์ง€(Morphology) ์—ฐ์‚ฐ (์นจ์‹, ํŒฝ์ฐฝ, ์—ด๋ฆผ, ๋‹ซํž˜, ๊ทธ๋ ˆ๋””์–ธํŠธ, ํƒ‘ํ–‡, ๋ธ”๋ž™ํ–‡)

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

bkshin.tistory.com

 

 

 

 

๋ชจํด๋กœ์ง€(morphology)

: 'ํ˜•ํƒœํ•™'

: ์˜์ƒ ๋ถ„์•ผ์—์„œ ๋…ธ์ด์ฆˆ ์ œ๊ฑฐ, ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ, ๋Š์–ด์ง„ ์„  ์ด์–ด ๋ถ™์ด๊ธฐ ๋“ฑ ํ˜•ํƒœํ•™์  ์—ฐ์‚ฐ

: ๋ชจํด๋กœ์ง€ ์—ฐ์‚ฐ์€ ๊ฒ€์€์ƒ‰๊ณผ ํฐ์ƒ‰์œผ๋กœ๋งŒ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ(binary) ์ด๋ฏธ์ง€์— ์ ์šฉ

์นจ์‹, ํŒฝ์ฐฝ, ์—ด๋ฆผ, ๋‹ซํž˜

 

 

 

1. ์นจ์‹ ์—ฐ์‚ฐ (Erode)

: ์ด๋ฏธ์ง€๋ฅผ ๊นŽ์•„ ๋‚ด๋Š” ์—ฐ์‚ฐ

: ์ž‘์€ ๋ฌผ์ฒด๋Š” ์•„์˜ˆ ์—†์• ๋ฒ„๋ฆฌ๋ฏ€๋กœ ๋…ธ์ด์ฆˆ ์ œ๊ฑฐ ํšจ๊ณผ

์›๋ž˜๋Š” ๋–จ์–ด์ ธ ์žˆ๋Š” ๋ฌผ์ฒด์ธ๋ฐ ๊ฒน์ณ ์žˆ๋Š” ๊ฒƒ์„ ์„œ๋กœ ๋–ผ์–ด๋‚ด๋Š” ๋ฐ๋„ ํšจ๊ณผ

: ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„(structuring element kernel)์ด๋ผ๋Š” 0๊ณผ 1๋กœ ๊ตฌ์„ฑ๋œ ์ปค๋„์ด ํ•„์š”

: ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„์€ 1์ด ์ฑ„์›Œ์ง„ ๋ชจ์–‘์— ๋”ฐ๋ผ ์‚ฌ๊ฐํ˜•, ํƒ€์›ํ˜•, ์‹ญ์žํ˜• ๋“ฑ์œผ๋กœ ์‚ฌ์šฉ

: ์ž…๋ ฅ ์ด๋ฏธ์ง€์— ์ ์šฉํ•ด์„œ 1๋กœ ์ฑ„์›Œ์ง„ ์˜์—ญ์„ ์˜จ์ „ํžˆ ์˜ฌ๋ ค ๋†“์„ ์ˆ˜ ์—†์œผ๋ฉด

ํ•ด๋‹น ํ”ฝ์…€์„ 0์œผ๋กœ ๋ณ€๊ฒฝ

์ถœ์ฒ˜: http://blog.daum.net/shksjy/314

- ์‹ญ์žํ˜• ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„๋กœ ์นจ์‹ ์—ฐ์‚ฐ์„ ํ•˜๋Š” ๊ณผ์ •

: A ์ด๋ฏธ์ง€์—์„œ ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ์€ 0์ด๊ณ , ํ•˜๋Š˜์ƒ‰ ์ „๊ฒฝ์€ 1

: B๋Š” ์‹ญ์žํ˜• ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„

: ์‹ญ์žํ˜• ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„์˜ ์ค‘์‹ฌ๋ถ€(๋นจ๊ฐ„ ์  ๋ถ€๋ถ„)๋Š” A ์ด๋ฏธ์ง€์˜ ํŒŒ๋ž€์ƒ‰ ๋ถ€๋ถ„์„ ์ญ‰ ํ›‘๋Š”๋‹ค

: ํ•œ ์นธ ํ•œ ์นธ ํ›‘์œผ๋ฉด์„œ ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„์ด A ์ด๋ฏธ์ง€์˜ ํ•˜๋Š˜์ƒ‰ ๋ถ€๋ถ„๊ณผ ์™„์ „ํžˆ ๊ฒน์น˜์ง€ ์•Š์„ ๋•Œ๋Š” 0์œผ๋กœ ๋ณ€๊ฒฝ

: ์™„์ „ํžˆ ๊ฒน์น˜๋ฉด 1๋กœ ๊ทธ๋Œ€๋กœ

 

cv2.getStructuringElement(shape, ksize, anchor)

: ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„ ์ƒ์„ฑ์„ ์œ„ํ•œ ํ•จ์ˆ˜

- shape : ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„ ๋ชจ์–‘

  • cv2.MORPH_RECT : ์‚ฌ๊ฐํ˜•
  • cv2.MORPH_EPLIPSE: ํƒ€์›ํ˜•
  • cv2.MORPH_CROSS : ์‹ญ์žํ˜•

- ksize : ์ปค๋„ ํฌ๊ธฐ

- anchor(optional) : ๊ตฌ์กฐํ™” ์š”์†Œ์˜ ๊ธฐ์ค€์ , cv2.MORPH_CROSS์—๋งŒ ์˜๋ฏธ ์žˆ์œผ๋ฉฐ ๊ธฐ๋ณธ ๊ฐ’์€ ์ค‘์‹ฌ์  (-1, -1)

 

dst = cv2.erode(src, kernel, anchor, iterations, borderType, borderValue)

: ์นจ์‹ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜

- src : ์ž…๋ ฅ ์˜์ƒ, ๋ฐ”์ด๋„ˆ๋ฆฌ

- kernel : ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„

- anchor(optional) : cv2.getStructuringElement()์™€ ๋™์ผ 

- iterations(optional) : ์นจ์‹ ์—ฐ์‚ฐ ์ ์šฉ ๋ฐ˜๋ณต ํšŸ์ˆ˜

- boderType(optional) : ์™ธ๊ณฝ ์˜์—ญ ๋ณด์ • ๋ฐฉ๋ฒ•

- boderValue(optional) : ์™ธ๊ณฝ ์˜์—ญ ๋ณด์ • ๊ฐ’

# ์นจ์‹ ์—ฐ์‚ฐ (morph_erode.py)

import cv2
import numpy as np

img = cv2.imread('img/morphology.JPG')

# ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„, ์‚ฌ๊ฐํ˜• (3x3) ์ƒ์„ฑ ---โ‘ 
k = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
# ์นจ์‹ ์—ฐ์‚ฐ ์ ์šฉ ---โ‘ก
erosion = cv2.erode(img, k)

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

์นจ์‹ ์—ฐ์‚ฐ์„ ์œ„ํ•œ ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„์€ 3 x 3์˜ ์‚ฌ๊ฐํ˜• ๋ชจ์–‘์œผ๋กœ ์ƒ์„ฑ

- ๊ฐ€๋Š˜์–ด์ง„๋‹น

=> ์นจ์‹์€ ์–ด๋‘์šด ๋ถ€๋ถ„์˜ ๋…ธ์ด์ฆˆ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ํšจ๊ณผ

 

 

 

 

2. ํŒฝ์ฐฝ ์—ฐ์‚ฐ (Dilatation)

: ์นจ์‹๊ณผ ๋ฐ˜๋Œ€๋กœ ๋ฌผ์ฒด์˜ ์ฃผ๋ณ€์„ ํ™•์žฅํ•˜๋Š” ์—ฐ์‚ฐ

: ์™„์ „ํžˆ ๊ฒน์น˜์ง€ ์•Š์œผ๋ฉด 1๋กœ ๋ณ€๊ฒฝ

์™„์ „ํžˆ ๊ฒน์น˜์ง€ ์•Š์œผ๋ฉด 1๋กœ ๋ณ€๊ฒฝ

dst = cv2.dilate(src, kernel, dst, anchor, iterations, bordeType, borderValue)

: ๋ชจ๋“  ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” cv2.erode()์™€ ๋™์ผ

# ํŒฝ์ฐฝ ์—ฐ์‚ฐ
import cv2
import numpy as np

img = cv2.imread('img/dilate.JPG')

# ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„, ์‚ฌ๊ฐํ˜• (3x3) ์ƒ์„ฑ ---โ‘ 
k = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
# ํŒฝ์ฐฝ ์—ฐ์‚ฐ ์ ์šฉ ---โ‘ก
dst = cv2.dilate(img, k)

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

 ๋ฌผ์ฒด์˜ ์ฃผ๋ณ€์„ ํ™•์žฅํ•˜๋Š” ํŒฝ์ฐฝ ์—ฐ์‚ฐ

- ๊ฒ€์ • ๋…ธ์ด์ฆˆ ์—†์–ด์ง

- ์™œ๋ƒ๋ฉด ํฐ์ƒ‰์ด ๋ฐ”๊นฅ, ์•ˆ์œผ๋กœ ํŒฝ์ฐฝ๋˜์–ด ๋šฑ๋•ก์ด๊ฐ€ ๋จ

=> ํŒฝ์ฐฝ์€ ๋ฐ์€ ๋ถ€๋ถ„์˜ ๋…ธ์ด์ฆˆ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ํšจ๊ณผ

 

 

 

 

3. ์—ด๋ฆผ, ๋‹ซํž˜, ๊ทธ๋ ˆ๋””์–ธํŠธ, ํƒ‘ํ–‡, ๋ธ”๋ž™ํ–‡ ์—ฐ์‚ฐ

1) ์—ด๋ฆผ(opening) ์—ฐ์‚ฐ

: ์นจ์‹ ์—ฐ์‚ฐ ํ›„ ํŒฝ์ฐฝ ์—ฐ์‚ฐ์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ

: ์ฃผ๋ณ€๋ณด๋‹ค ๋ฐ์€ ๋…ธ์ด์ฆˆ๋ฅผ ์ œ๊ฑฐ

: ๋…๋ฆฝ๋œ ๊ฐœ์ฒด๋ฅผ ๋ถ„๋ฆฌํ•˜๊ฑฐ๋‚˜ ๋Œ์ถœ๋œ ๋ชจ์–‘์„ ์ œ๊ฑฐํ•˜๋Š” ๋ฐ ํšจ๊ณผ์ 

 

2) ๋‹ซํž˜(closing) ์—ฐ์‚ฐ

: ํŒฝ์ฐฝ ์—ฐ์‚ฐ ํ›„ ์นจ์‹ ์—ฐ์‚ฐ์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ

: ์ฃผ๋ณ€๋ณด๋‹ค ์–ด๋‘์šด ๋…ธ์ด์ฆˆ๋ฅผ ์ œ๊ฑฐ

: ํšจ๊ณผ์ ์ด๋ฉด์„œ ๋Š์–ด์ ธ ๋ณด์ด๋Š” ๊ฐœ์ฒด๋ฅผ ์—ฐ๊ฒฐํ•˜๊ฑฐ๋‚˜ ๊ตฌ๋ฉ์„ ๋ฉ”์šฐ๋Š” ๋ฐ ํšจ๊ณผ์ 

 

3) ๊ทธ๋ ˆ๋””์–ธํŠธ(gradient) ์—ฐ์‚ฐ

: ํŒฝ์ฐฝ ์—ฐ์‚ฐ์„ ์ ์šฉํ•œ ์ด๋ฏธ์ง€์—์„œ ์นจ์‹ ์—ฐ์‚ฐ์„ ์ ์šฉํ•œ ์ด๋ฏธ์ง€๋ฅผ ๋นผ๋ฉด ๊ฒฝ๊ณ„ ํ”ฝ์…€๋งŒ ์–ป๊ฒŒ ๋จ

: ๊ทธ๋ ˆ๋””์–ธํŠธ = ํŒฝ์ฐฝ - ์นจ์‹

 

4) ํƒ‘ํ–‡(top hat)

: ์›๋ณธ์—์„œ ์—ด๋ฆผ ์—ฐ์‚ฐ ์ ์šฉ ๊ฒฐ๊ณผ๋ฅผ ๋นผ๋ฉด ๊ฐ’์ด ํฌ๊ฒŒ ํŠ€๋Š” ๋ฐ์€ ์˜์—ญ์„ ๊ฐ•์กฐ

: ํƒ‘ํ–‡ = ์›๋ณธ - ์—ด๋ฆผ

 

5) ๋ธ”๋ž™ํ–‡(black hat) ์—ฐ์‚ฐ

: ๋‹ซํž˜ ์—ฐ์‚ฐ ์ ์šฉ ๊ฒฐ๊ณผ์—์„œ ์›๋ณธ์„ ๋นผ๋ฉด ์–ด๋‘์šด ๋ถ€๋ถ„์„ ๊ฐ•์กฐ

: ๋ธ”๋ž™ํ–‡ = ๋‹ซํž˜ - ์›๋ณธ

 

dst = cv2.morphologyEx(src, op, kernel, dst, anchor, iteration, borderType, borderValue)
- src : ์ž…๋ ฅ ์˜์ƒ
- op : ๋ชจํด๋กœ์ง€ ์—ฐ์‚ฐ ์ข…๋ฅ˜

  • cv2.MORPH_OPEN : ์—ด๋ฆผ ์—ฐ์‚ฐ
  • cv2.MORPH_COLSE : ๋‹ซํž˜ ์—ฐ์‚ฐ
  • cv2.MORPH_GRADIENT : ๊ทธ๋ ˆ๋””์–ธํŠธ ์—ฐ์‚ฐ
  • cv2.MORPH_TOPHAT : ํƒ‘ํ–‡ ์—ฐ์‚ฐ
  • cv2.MORPH_BLACKHAT : ๋ธ”๋ž™ํ–‡ ์—ฐ์‚ฐ

- kernel : ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„
- dst(optional) : ๊ฒฐ๊ณผ ์˜์ƒ
- anchor(optional) : ์ปค๋„์˜ ๊ธฐ์ค€์ 

- iteration(optional) : ์—ฐ์‚ฐ ๋ฐ˜๋ณต ํšŸ์ˆ˜

- borderType(optional) : ์™ธ๊ณฝ ์˜์—ญ ๋ณด์ • ๋ฐฉ๋ฒ•

- borderValue(optional) : ์™ธ๊ณฝ ์˜์—ญ ๋ณด์ • ๊ฐ’

# ์—ด๋ฆผ๊ณผ ๋‹ซํž˜ ์—ฐ์‚ฐ์œผ๋กœ ๋…ธ์ด์ฆˆ ์ œ๊ฑฐ
import cv2
import numpy as np

img1 = cv2.imread('img/morphology.JPG', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('img/dilate.JPG', cv2.IMREAD_GRAYSCALE)    

# ----------img resize---------------------
img1 = cv2.resize(img1, dsize = (288, 234))

# ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„, ์‚ฌ๊ฐํ˜• (5x5) ์ƒ์„ฑ ---โ‘ 
k = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
# ์—ด๋ฆผ ์—ฐ์‚ฐ ์ ์šฉ ---โ‘ก
opening = cv2.morphologyEx(img1, cv2.MORPH_OPEN, k)
# ๋‹ซํž˜ ์—ฐ์‚ฐ ์ ์šฉ ---โ‘ข
closing = cv2.morphologyEx(img2, cv2.MORPH_CLOSE, k)

# ๊ฒฐ๊ณผ ์ถœ๋ ฅ
merged1 = np.hstack((img1, opening))
merged2 = np.hstack((img2, closing))
merged3 = np.vstack((merged1, merged2))
cv2.imshow('opening, closing', merged3)
cv2.waitKey(0)
cv2.destroyAllWindows()

์—ด๋ฆผ๊ณผ ๋‹ซํž˜ ์—ฐ์‚ฐ์œผ๋กœ ๋…ธ์ด์ฆˆ ์ œ๊ฑฐ

- ์™„์ „ ๊น”๋”!

 

 

 

+) ํŒฝ์ฐฝ ์—ฐ์‚ฐ์—์„œ ์นจ์‹ ์—ฐ์‚ฐ์„ ๋บ€ ๊ทธ๋ ˆ๋””์–ธํŠธ ์—ฐ์‚ฐ

# ๋ชจํด๋กœ์ง€ ๊ทธ๋ ˆ์ด์–ธํŠธ
import cv2
import numpy as np

img = cv2.imread('img/heart.JPG')

# ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„, ์‚ฌ๊ฐํ˜• (3x3) ์ƒ์„ฑ ---โ‘ 
k = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
# ์—ด๋ฆผ ์—ฐ์‚ฐ ์ ์šฉ ---โ‘ก
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, k)

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

 ๊ฒฝ๊ณ„๋ฅผ ๊ฒ€์ถœ

 

 

 

 

+) ํƒ‘ํ–‡, ๋ธ”๋ž™ํ–‡ ์—ฐ์‚ฐ ์ ์šฉ

# ๋ชจํด๋กœ์ง€ ํƒ‘ํ–‡, ๋ธ”๋ž™ํ–‡ ์—ฐ์‚ฐ
import cv2
import numpy as np

img = cv2.imread('img/moon_gray.jpeg')

# ๊ตฌ์กฐํ™” ์š”์†Œ ์ปค๋„, ์‚ฌ๊ฐํ˜• (5x5) ์ƒ์„ฑ ---โ‘ 
k = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
# ํƒ‘ํ–‡ ์—ฐ์‚ฐ ์ ์šฉ ---โ‘ก
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, k)
# ๋ธ”๋žซํ–‡ ์—ฐ์‚ฐ ์ ์šฉ ---โ‘ข
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, k)

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

                                        ํƒ‘ํ–‡ ์—ฐ์‚ฐ                       ๋ธ”๋ž™ํ–‡ ์—ฐ์‚ฐ

- ํƒ‘ํ–‡์€ ๋‹ญ์˜ ๋ฐ์€ ๋ถ€๋ถ„ ๊ฐ•์กฐ

- ๋ธ”๋ž™ํ–‡์€ ๋‹ฌ์˜ ์–ด๋‘์šด ๋ถ€๋ถ„ ๊ฐ•์กฐ

 

 

 

 

 

 

์ถ”์–ต..

๊ทธ๋ฆผ๊ทธ๋ฆฌ๋Š๋ผ ํ˜ผ๋‚ฌ๋„น

 

 

 

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