๐ ๋ณธ ์์ ๋ Window10์ VSCode, Python3.11.0๋ก ์์ฑ๋์์ต๋๋ค.
Skeletonization์ ์ด๋ฏธ์ง ์ฒ๋ฆฌ์์ ๊ฐ์ฒด์ ํํ๋ฅผ ๋จ์ํํ์ฌ ๊ทธ ๊ตฌ์กฐ๋ฅผ ๋ํ๋ด๋ ๊ธฐ๋ฒ์ด๋ค.
์ด ๊ณผ์ ์ ์ฃผ๋ก ์ด์ง ์ด๋ฏธ์ง์์ ์ฌ์ฉ๋๋ฉฐ, ๊ฐ์ฒด์ ์ค๊ณฝ์ ์ ์ ์งํ๋ฉด์ ๋๊ป๋ฅผ ์ค์ฌ์ ์ ์ ํํ๋ก ํํํ๋ค.
import cv2
import numpy as np
def skeletonize(img):
""" OpenCV function to return a skeletonized version of img, a Mat object"""
# hat tip to http://felix.abecassis.me/2011/09/opencv-morphological-skeleton/
img = img.copy() # don't clobber original
skel = img.copy()
skel[:,:] = 0
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3))
while True:
eroded = cv2.morphologyEx(img, cv2.MORPH_ERODE, kernel)
temp = cv2.morphologyEx(eroded, cv2.MORPH_DILATE, kernel)
temp = cv2.subtract(img, temp)
skel = cv2.bitwise_or(skel, temp)
img[:,:] = eroded[:,:]
if cv2.countNonZero(img) == 0:
break
return skel
# ์ด๋ฏธ์ง ์ฝ๊ธฐ
image = cv2.imread('human.png', cv2.IMREAD_GRAYSCALE)
h,w = image.shape
# resize
image = cv2.resize(image,(int(w//2),int(h//2)),interpolation=cv2.INTER_LANCZOS4)
# ์ค์ผ๋ ํ ๋์ด์ฆ ์ํ
skeleton = skeletonize(image)
# ๊ฒฐ๊ณผ ์ถ๋ ฅ
cv2.imshow('Original Image', image)
cv2.imshow('Skeleton', skeleton)
cv2.waitKey(0)
cv2.destroyAllWindows()
Skeletonization ์๊ณ ๋ฆฌ์ฆ์ ๋ํ์ ์ผ๋ก Zhang-Suen ์๊ณ ๋ฆฌ์ฆ๊ณผ Guo-Hall ์๊ณ ๋ฆฌ์ฆ์ด ์๋ค.
Zhang-Suen
Zhang-Suen ์๊ณ ๋ฆฌ์ฆ์ ๋ฐ๋ณต์ ์ธ ํํํ์ ์ฐ์ฐ์ ํตํด ์ค์ผ๋ ํค์ ์์ฑํ๋ค.
import numpy as np
import cv2
from numba import jit,prange
@jit
def thinning_iteration(im, iter):
I, M = im.copy(), np.zeros(im.shape, np.uint8)
for i in prange(1, im.shape[0] - 1):
for j in prange(1, im.shape[1] - 1):
p2 = I[i-1, j]
p3 = I[i-1, j+1]
p4 = I[i, j+1]
p5 = I[i+1, j+1]
p6 = I[i+1, j]
p7 = I[i+1, j-1]
p8 = I[i, j-1]
p9 = I[i-1, j-1]
A = (p2 == 0 and p3 == 1) + (p3 == 0 and p4 == 1) + \
(p4 == 0 and p5 == 1) + (p5 == 0 and p6 == 1) + \
(p6 == 0 and p7 == 1) + (p7 == 0 and p8 == 1) + \
(p8 == 0 and p9 == 1) + (p9 == 0 and p2 == 1)
B = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9
m1 = p2 * p4 * p6 if iter == 0 else p2 * p4 * p8
m2 = p4 * p6 * p8 if iter == 0 else p2 * p6 * p8
if A == 1 and B >= 2 and B <= 6 and m1 == 0 and m2 == 0:
M[i, j] = 1
return I & ~M
def thinning(src):
dst = src.copy() // 255
prev = np.zeros(src.shape, np.uint8)
diff = None
while True:
dst = thinning_iteration(dst, 0)
dst = thinning_iteration(dst, 1)
diff = np.abs(dst - prev)
prev = dst.copy()
if np.sum(diff) == 0:
break
return dst * 255
# ์ด๋ฏธ์ง ์ฝ๊ธฐ
image = cv2.imread('h.png', cv2.IMREAD_GRAYSCALE)
h, w = image.shape
# resize
image = cv2.resize(image, (int(w // 2), int(h // 2)), interpolation=cv2.INTER_LANCZOS4)
# ์ด์งํ
_, bw2 = cv2.threshold(image, 10, 255, cv2.THRESH_BINARY)
# Zhang-Suen ์ค์ผ๋ ํคํ ์ํ
bw2 = thinning(bw2)
# ๊ฒฐ๊ณผ ์ถ๋ ฅ
cv2.imshow("original",image)
cv2.imshow('Skeleton', bw2) # ์ค์ผ๋ ํค์ 0-255 ๋ฒ์๋ก ๋ณํ
cv2.waitKey(0)
cv2.destroyAllWindows()
Guo-Hall
Guo-Hall ์๊ณ ๋ฆฌ์ฆ์ Zhang-Suen๊ณผ ์ ์ฌํ๋, ๋ ๊ฐ์ ๋ฐ๋ณต ๋จ๊ณ๋ก ์ด๋ฃจ์ด์ ธ ์๊ณ , ๊ฐ ๋จ๊ณ์์ ๋ ๋ง์ ์กฐ๊ฑด์ ๊ณ ๋ คํ์ฌ ํฝ์ ์ ์ ๊ฑฐํ๋ฏ๋ก, ๋ ์ ๊ตํ ์ค์ผ๋ ํค์ ์์ฑํ ์ ์๋ค.
# pip install thinning-py3
import cv2
import thinning
from copy import copy
img = cv2.imread("h.png",cv2.IMREAD_GRAYSCALE)
img_ = copy(img)
thinned = thinning.guo_hall_thinning(img_)
cv2.imshow("original",img)
cv2.imshow("guohall",thinned)
cv2.waitKey(0)
cv2.destroyAllWindows()
์ด๋ฟ๋ง ์๋๋ผ Skeletonization์ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์๋ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ์ ๊ณต๋๋ค.
import cv2
from skimage.morphology import skeletonize
import numpy as np
image = cv2.imread('h.png', cv2.IMREAD_GRAYSCALE)
ske = skeletonize(image)
skeleton_uint8 = (ske * 255).astype(np.uint8)
cv2.imshow("original",image)
cv2.imshow('Skeleton', skeleton_uint8) # ์ค์ผ๋ ํค์ 0-255 ๋ฒ์๋ก ๋ณํ
cv2.waitKey(0)
cv2.destroyAllWindows()
'AI > Computer Vision' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Computer Vision] ์ด๋ฏธ์ง ์ ์ฌ๋ (0) | 2024.09.21 |
---|---|
[Computer Vision] Segmentation (0) | 2024.09.19 |
[Computer Vision] Depth (0) | 2024.09.15 |
[Computer Vision] Trapped-ball Segmentation (0) | 2024.09.14 |
[Computer Vision] IoU(Intersection over Union) (0) | 2024.09.12 |