python - Skeletonization with Thinning and Hit-or-miss implementation never stops
问题描述
I'm trying to implement a Skeletonization algorithm with the thinning/hit-or-miss approach as described in https://homepages.inf.ed.ac.uk/rbf/HIPR2/thin.htm .
I want to extract the skeleton o the following image, which I believe is a good image for a test:
https://github.com/TiagoB936/Image-Processing-and-Computer-Vision/blob/master/Skeletonization/x.png
The problem is that my code can't stop running and I'm not finding out the problem.
My code does the following steps:
- Reads the image and binarizes it
Creates 2 main kernels:
[[0,0,0]
[-1,1,-1]
[1,1,1]]
and
[[-1,0,0]
[1,1,0]
[-1,1,1]]
Creates another 6 kernels, each one rotations of 90 degrees of the main kernels
- Applies hit or miss creating 8 outputs images
- Adds these images and subtracts the result of the input image generating an output image
- Verify if the output image is equal to the input image
- The input image turns into the output image
- Repeat while there is no difference between the input and output images
Here is some test code:
import cv2 as cv
import numpy as np
input_image = cv.imread('x.png',0)
_,input_image = cv.threshold(input_image,60,255,cv.THRESH_BINARY)
kernel1 = np.array((
[0, 0, 0],
[-1, 1, -1],
[1, 1, 1]), dtype="int")
kernel2 = np.array((
[-1, 0, 0],
[1, 1, 0],
[-1, 1, -1]), dtype="int")
kernel3 = np.rot90(kernel1)
kernel4 = np.rot90(np.rot90(kernel1))
kernel5 = np.rot90(np.rot90(np.rot90(kernel1)))
kernel6 = np.rot90(kernel2)
kernel7 = np.rot90(np.rot90(kernel2))
kernel8 = np.rot90(np.rot90(np.rot90(kernel2)))
output_image_1 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel1)
output_image_2 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel2)
output_image_3 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel3)
output_image_4 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel4)
output_image_5 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel5)
output_image_6 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel6)
output_image_7 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel7)
output_image_8 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel8)
hit_miss = output_image_1 + output_image_2 + output_image_3 + output_image_4 + output_image_5 + output_image_6 + output_image_7 + output_image_8
output_image = input_image - hit_miss
while not np.array_equal(output_image, input_image):
input_image = output_image
output_image_1 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel1)
output_image_2 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel2)
output_image_3 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel3)
output_image_4 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel4)
output_image_5 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel5)
output_image_6 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel6)
output_image_7 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel7)
output_image_8 = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel8)
hit_miss = output_image_1 + output_image_2 + output_image_3 + output_image_4 + output_image_5 + output_image_6 + output_image_7 + output_image_8
output_image = input_image - hit_miss
cv.imshow("hit_miss", hit_miss)
cv.imshow("out", output_image)
cv.waitKey(0)
cv.destroyAllWindows()
I was expecting to get a thin X image from my input, but the code can't stop running. Am I missing something?
解决方案
您想在应用所有内核之后使用逻辑或,而不是仅仅添加它们。
import cv2 as cv
import numpy as np
img = cv.imread('x.png',0)
_,img = cv.threshold(img,60,255,cv.THRESH_BINARY)
cv.imshow("input", img)
cv.waitKey(0)
cv.destroyAllWindows()
kernel1 = np.array((
[[-1, -1, -1],
[0, 1, 0],
[1, 1, 1]]))
kernel2 = np.array((
[[0, -1, -1],
[1, 1, -1],
[0, 1, 0]]))
kernel3 = np.rot90(kernel1)
kernel4 = np.rot90(kernel2)
kernel5 = np.rot90(np.rot90(kernel1))
kernel6 = np.rot90(np.rot90(kernel2))
kernel7 = np.rot90(np.rot90(np.rot90(kernel1)))
kernel8 = np.rot90(np.rot90(np.rot90(kernel2)))
skel = np.zeros(img.shape,np.uint8)
mask = np.zeros(img.shape,np.uint8)
kernels = [kernel1, kernel2, kernel3, kernel4, kernel5, kernel6, kernel7, kernel8]
while (1):
mask = np.zeros(img.shape,np.uint8)
for kernel in kernels:
out_image = cv.morphologyEx(img, cv.MORPH_HITMISS, kernel)
mask = cv.bitwise_or(out_image, mask)
img = img - mask
if (np.array_equal(img, skel)):
break
skel = img
cv.imshow("out", img)
cv.waitKey(0)
cv.destroyAllWindows()