【问题标题】:Skimage skeletonize or OpenCV implementation that respects a grid?尊重网格的 Skimage 骨架化或 OpenCV 实现?
【发布时间】:2021-07-03 20:22:23
【问题描述】:

假设有一条线以直角相交。

并且您希望将其骨架化以获得(您希望)十字形。相反,使用sklearn.morphology.skeletonize 会获得以下图像:

我们称它为“有洞的十字架”。

另一方面,您有 OpenCV 和 OpenCV 骨架化功能,该功能在互联网上的几个博客和答案中流传:

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

这会产生以下结果:


因此,浮动的基本 OpenCV 骨架化功能有问题或不正确,并且 Skimage 骨架化无法使用结构化形状进行修改。

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

【问题讨论】:

  • 看起来 sn-p 通过morphology 近似于skeleton。您是否尝试过 OpenCV 的扩展图像处理模块上的“细化”功能?你可以这样称呼它:skeleton = cv2.ximgproc.thinning(inputImage, None, algorithmCode) 其中algorithmCode01。有关the docs 的更多信息。
  • @eldesgraciado 谢谢,我明天试试
  • scikit-image 也有多种方法,它们在这样的图像上给出截然不同的结果(拥有源图像会有所帮助)。试试morphology.skeletonize(image, method='lee')morphology.medial_axis(image)morphology.thin(image)。在我的尝试中,虽然没有一个完美的十字架。但是我的测试图像和你的有点不同。
  • 在骨架化时很难正确进行交叉,因为您希望该方法考虑一些相当非本地的特征。值得注意的是,在您的示例中,您的中心框高 8 像素,因此中间像素的选择不明确。对我们人类来说,这种选择是显而易见的,因为纤细的手臂向外延伸。骨架化后,我通常会通过fitting hough lines 解决此类问题。
  • @Juan thinned 成功了

标签: python opencv scikit-image mathematical-morphology


【解决方案1】:

当我注意到CMET中时,您可以通过拟合Hough线清理骨架图像中的交叉点:

#!/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):
        ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 2012-05-26
    • 2015-05-09
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多