I have a binary image, and I used the skeleton method in the Skimage library to extract skeleton lines. However, there are many burrs on both edges, and I want to remove and delete these burrs.
This is skeletonized images by two different methods
Original Images
my python script is:
import skimage as ski
import skimage.io as io
import matplotlib.pyplot as plt
import numpy as np
from skimage.morphology import skeletonize
import matplotlib
matplotlib.rc("font",family='Microsoft YaHei')
image_path=r"./1089_8.jpg"
image=io.imread(image_path,as_gray=True)
skeleton1=skeletonize(image,method='zhang')
skeleton2=skeletonize(image,method='lee')
fig,axes=plt.subplots(nrows=1,ncols=3,figsize=(8, 4), sharex=True, sharey=True)
ax=axes.ravel()
ax[0].imshow(image, cmap=plt.cm.gray)
ax[0].axis('off')
ax[0].set_title('original', fontsize=20)
ax[1].imshow(skeleton1, cmap=plt.cm.gray)
ax[1].axis('off')
ax[1].set_title('Zhang_method', fontsize=20)
ax[2].imshow(skeleton2,cmap=plt.cm.gray)
ax[2].axis('off')
ax[2].set_title('lee_method',fontsize=20)
fig.tight_layout()
plt.show()
I want to remove and delete these burrs. Then calculate the length of binary images.
My Desired Outcome
The result should look like figure (c).
3
The main problem with your input image is that you consider it binary, while in reality it is only “almost binary”:
You are working with a JPEG image, JPEG usually uses lossy compression and thus will have compression artefacts. You will not see these compression artefacts with your bare eye, but they will nevertheless interfere with the skeletonization algorithm.
Here is a contrast-enhanced version of your given image:
As you can see, there are a lot of tiny gray regions around the white structures. These are the ones responsible for the burrs that you struggle with.
Proposed solution
A quick fix: Make your image truly binary, e.g. by replacing
image=io.imread(image_path,as_gray=True)
with
# Threshold image: values > 127 become 1, values ≤ 127 become 0
image = (io.imread(image_path, as_gray=True) > 127).astype(np.uint8)
and thus applying a threshold before applying skeletonize()
.
This, for me, results in the following skeleton for Zhang’s method:
And for Lee’s method, I get:
You will still need to deal with a few burrs and the second “arm” in your desired length calculation; however, I would not consider this as the task of the skeletonization approach, as these are actual parts of the structure in your image rather than artefacts.
Here is the full code to reproduce the results from above:
import skimage.io as io
from skimage.morphology import skeletonize
import numpy as np
# TODO: Adjust input and output paths as necessary
in_path = "stackoverflow/OlfxVca1.jpg"
out_path_zhang = "stackoverflow/zhang.png"
out_path_lee = "stackoverflow/lee.png"
# Threshold image: values > 127 become 1, values ≤ 127 become 0
image = (io.imread(in_path, as_gray=True) > 127).astype(np.uint8)
skeleton_zhang = skeletonize(image, method="zhang").astype(np.uint8)
skeleton_lee = skeletonize(image, method="lee").astype(np.uint8)
io.imsave("stackoverflow/zhang.png", skeleton_zhang * 255)
io.imsave("stackoverflow/lee.png", skeleton_lee * 255)
5