Skimage skeletonize或OpenCV实现是否尊重网格?

2024-09-28 16:20:53 发布

您现在位置:Python中文网/ 问答频道 /正文

假设一条直线以直角相交

RightAngles

你想把它骨架化,得到(你希望的)十字形。相反,使用sklearn.morphology.skeletonize获得以下图像:

Holey Cross

让我们称之为“多孔十字架”

另一方面,您拥有OpenCV和OpenCV skeletonize功能,这些功能在互联网上的几个博客中随处可见,并在下面给出了答案:

def skeletonize(bin: numpy.ndarray, erosion_shape=cv2.MORPH_RECT, kernel_sz: Union[int, Tuple[int, int]] = 3):
    kernel_sz = fix_kernel(kernel_sz)
    kernel = cv2.getStructuringElement(erosion_shape, kernel_sz)

    thresh = bin.copy()
    skeleton = numpy.zeros_like(bin)
    eroded = numpy.zeros_like(bin)
    carry = numpy.zeros_like(bin)

    while (True):
        cv2.erode(thresh, kernel, dst=eroded)
        cv2.dilate(eroded, kernel, dst=carry)
        cv2.subtract(thresh, carry, dst=carry)
        cv2.bitwise_or(skeleton, carry, dst=skeleton)
        thresh, eroded = eroded, thresh

        if cv2.countNonZero(thresh) == 0:
            return skeleton

这将产生以下结果:

Gap Cross


因此,浮动的基本OpenCV骨架化函数存在一些错误或错误,不能使用结构化形状修改Skimage骨架化

有没有办法在python中获得骨架化的十字/加号形状


Tags: numpybinzeroscv2kernelopencv骨架skeleton
1条回答
网友
1楼 · 发布于 2024-09-28 16:20:53

正如我在评论中指出的,可以通过拟合hough线来清理骨架化图像中的交叉点:

enter image description here

#!/usr/bin/env python
"""
https://stackoverflow.com/q/66995948/2912349
"""
import numpy as np
import matplotlib.pyplot as plt

from skimage.morphology import skeletonize
from skimage.transform import probabilistic_hough_line
from skimage.draw import line as get_line_pixels

img = np.zeros((20, 20))
img[4:16, 6:14] = 1
img[:, 10] = 1
img[10, :] = 1

skel = skeletonize(img)

lines = probabilistic_hough_line(skel, line_length=10)

# hough_line() returns the start and endpoint of the fitted lines;
# we need all pixels covered by that line;
cleaned = np.zeros_like(img)
for ((r0, c0), (r1, c1)) in lines:
    rr, cc = get_line_pixels(r0, c0, r1, c1)
    cleaned[rr, cc] = 1

fig, axes = plt.subplots(1, 3, sharex=True, sharey=True)
axes[0].imshow(img, cmap='gray')
axes[0].set_title('Raw')
axes[1].imshow(skel, cmap='gray')
axes[1].set_title('Skeleton')
axes[2].imshow(cleaned, cmap='gray')
axes[2].set_title('Hough lines')
plt.show()

如果要强制进行水平或垂直拟合,lines可以进行简单过滤,以排除非水平线和非垂直线:

for ((r0, c0), (r1, c1)) in lines:
    if (r0 == r1) or (c0 == c1):
        ...

相关问题 更多 >