小图像的骨架化(细化)没有给出预期的结果 - python
skeletonization (thinning) of small images not giving expected results - python
我正在尝试实现小图像的骨架化。但我没有得到预期的结果。我也尝试了 thin()
和 medial_axis()
,但似乎没有任何效果。我怀疑这个问题是由于图像的分辨率太低而导致的。这是代码:
import cv2
from numpy import asarray
import numpy as np
# open image
file = "66.png"
img_grey = cv2.imread(file, cv2.IMREAD_GRAYSCALE)
afterMedian = cv2.medianBlur(img_grey, 3)
thresh = 140
# threshold the image
img_binary = cv2.threshold(afterMedian, thresh, 255, cv2.THRESH_BINARY)[1]
# make binary image
arr = asarray(img_binary)
binaryArr = np.zeros(asarray(img_binary).shape)
for i in range(0, arr.shape[0]):
for j in range(0, arr.shape[1]):
if arr[i][j] == 255:
binaryArr[i][j] = 1
else:
binaryArr[i][j] = 0
# perform skeletonization
from skimage.morphology import skeletonize
cv2.imshow("binary arr", binaryArr)
backgroundSkeleton = skeletonize(binaryArr)
# convert to non-binary image
bSkeleton = np.zeros(arr.shape)
for i in range(0, arr.shape[0]):
for j in range(0, arr.shape[1]):
if backgroundSkeleton[i][j] == 0:
bSkeleton[i][j] = 0
else:
bSkeleton[i][j] = 255
cv2.imshow("background skeleton", bSkeleton)
cv2.waitKey(0)
结果是:
我期待更多这样的东西:
这也适用于类似的形状:
期望:
我做错了什么吗?或者它真的不可能用这么小的图片,因为我尝试在更大的图像上进行骨架化并且效果很好。原始图片:
这里似乎 scikit-image 比 cv2 更好。
由于包定义了 Bit 函数,如果你正在玩 BW 图像,那么试试这个准备使用的代码:
skeletonize
注意:如果进程传递了图像细节,那么在尝试其他 functions:again 使用 skimage morphology functions to enhance details which in such case your code will be work on bigger area of images too. You could look here.
之前,不要先对输入进行上采样
您可以尝试 DIPlib 中的框架 (dip.EuclideanSkeleton
):
import numpy as np
import diplib as dip
import cv2
file = "66.png"
img_grey = cv2.imread(file, cv2.IMREAD_GRAYSCALE)
afterMedian = cv2.medianBlur(img_grey, 3)
thresh = 140
bin = afterMedian > thresh
sk = dip.EuclideanSkeleton(bin, endPixelCondition='three neighbors')
dip.viewer.Show(bin)
dip.viewer.Show(sk)
dip.viewer.Spin()
endPixelCondition
输入参数可用于调整保留或删除的分支数。 'three neighbors'
是产生最多分支的选项。
上面的代码也产生了朝向图像角落的分支。使用 'two neighbors'
可以防止这种情况,但也会产生较少的指向对象的分支。另一种防止它的方法是设置edgeCondition='object'
,但在这种情况下,对象周围的环在图像边界上变成正方形。
要将 DIPlib 图像 sk
转换回 NumPy 数组,请执行
sk = np.array(sk)
sk
现在是布尔 NumPy 数组(值 True
和 False
)。要创建与 OpenCV 兼容的数组,只需转换为 np.uint8
并乘以 255:
sk = np.array(sk, dtype=np.uint8)
sk *= 255
请注意,在处理 NumPy 数组时,您通常不需要遍历所有像素。事实上,尽量避免这样做是值得的,因为 Python 中的循环非常慢。
我正在尝试实现小图像的骨架化。但我没有得到预期的结果。我也尝试了 thin()
和 medial_axis()
,但似乎没有任何效果。我怀疑这个问题是由于图像的分辨率太低而导致的。这是代码:
import cv2
from numpy import asarray
import numpy as np
# open image
file = "66.png"
img_grey = cv2.imread(file, cv2.IMREAD_GRAYSCALE)
afterMedian = cv2.medianBlur(img_grey, 3)
thresh = 140
# threshold the image
img_binary = cv2.threshold(afterMedian, thresh, 255, cv2.THRESH_BINARY)[1]
# make binary image
arr = asarray(img_binary)
binaryArr = np.zeros(asarray(img_binary).shape)
for i in range(0, arr.shape[0]):
for j in range(0, arr.shape[1]):
if arr[i][j] == 255:
binaryArr[i][j] = 1
else:
binaryArr[i][j] = 0
# perform skeletonization
from skimage.morphology import skeletonize
cv2.imshow("binary arr", binaryArr)
backgroundSkeleton = skeletonize(binaryArr)
# convert to non-binary image
bSkeleton = np.zeros(arr.shape)
for i in range(0, arr.shape[0]):
for j in range(0, arr.shape[1]):
if backgroundSkeleton[i][j] == 0:
bSkeleton[i][j] = 0
else:
bSkeleton[i][j] = 255
cv2.imshow("background skeleton", bSkeleton)
cv2.waitKey(0)
结果是:
我期待更多这样的东西:
这也适用于类似的形状:
期望:
我做错了什么吗?或者它真的不可能用这么小的图片,因为我尝试在更大的图像上进行骨架化并且效果很好。原始图片:
这里似乎 scikit-image 比 cv2 更好。 由于包定义了 Bit 函数,如果你正在玩 BW 图像,那么试试这个准备使用的代码: skeletonize
注意:如果进程传递了图像细节,那么在尝试其他 functions:again 使用 skimage morphology functions to enhance details which in such case your code will be work on bigger area of images too. You could look here.
之前,不要先对输入进行上采样您可以尝试 DIPlib 中的框架 (dip.EuclideanSkeleton
):
import numpy as np
import diplib as dip
import cv2
file = "66.png"
img_grey = cv2.imread(file, cv2.IMREAD_GRAYSCALE)
afterMedian = cv2.medianBlur(img_grey, 3)
thresh = 140
bin = afterMedian > thresh
sk = dip.EuclideanSkeleton(bin, endPixelCondition='three neighbors')
dip.viewer.Show(bin)
dip.viewer.Show(sk)
dip.viewer.Spin()
endPixelCondition
输入参数可用于调整保留或删除的分支数。 'three neighbors'
是产生最多分支的选项。
上面的代码也产生了朝向图像角落的分支。使用 'two neighbors'
可以防止这种情况,但也会产生较少的指向对象的分支。另一种防止它的方法是设置edgeCondition='object'
,但在这种情况下,对象周围的环在图像边界上变成正方形。
要将 DIPlib 图像 sk
转换回 NumPy 数组,请执行
sk = np.array(sk)
sk
现在是布尔 NumPy 数组(值 True
和 False
)。要创建与 OpenCV 兼容的数组,只需转换为 np.uint8
并乘以 255:
sk = np.array(sk, dtype=np.uint8)
sk *= 255
请注意,在处理 NumPy 数组时,您通常不需要遍历所有像素。事实上,尽量避免这样做是值得的,因为 Python 中的循环非常慢。