是否可以清理skimage中的等高线图?

时间:2016-08-11 14:02:10

标签: scikit-image

今天早上我有这个想法,我发现scikit-image可能可以解决问题。简单来说,我想删除轮廓光栅图像中的水平标签和其他不必要的特征,并获得轮廓线的位置。

喜欢这张图片: contour image with features to be removed

但是看了一会儿后,我不确定是否可以做到。我的考虑如下:

1)find_contours可以找到轮廓线,但我认为还包括所有其他功能(箭头和标签)。

2)关闭可能会删除标签,但我发现轮廓线也被删除了,我认为这是因为它们只是细线,如果使用关闭功能,亮区域将被连接。

3)箭头主要与轮廓线连接,因此这些特征不能视为单个对象。它们可能是最难移除的部分。

我想得到的帮助是知道是否可以删除标签和箭头以获得skimage中的等高线。如果是这样,我会继续学习这个包。

1 个答案:

答案 0 :(得分:2)

以下是您问题的部分解决方案。基本思想是将互连线的网络视为图形,并删除该图的小边缘,因为它们(大部分)对应于箭头和标签。第一步是计算二值化阶段的骨架。

Detected contours

当然结果并不完美,你可以调整下面脚本的不同参数来找到你认为最好的解决方案。如果您需要在大量图像上重复此分割,您还可以尝试手动选择要保留的图形边缘作为训练集,并使用机器学习算法对要保留的边缘进行分类(使用边缘的特征,例如长度,其他连接边的数量,方向,直线度......)。

import numpy as np
import matplotlib.pyplot as plt
from skimage import io, morphology
from scipy import ndimage

def skel_to_graph(skel):
    """
    Transform skeleton into its branches and nodes, by counting the number
    of neighbors of each pixel in the skeleton
    """
    convolve_skel = 3**skel.ndim * ndimage.uniform_filter(skel.astype(np.float))
    neighbors = np.copy(skel.astype(np.uint8))
    skel = skel.astype(np.bool)
    neighbors[skel] = convolve_skel[skel] - 1
    edges = morphology.label(np.logical_or(neighbors == 2, neighbors ==1),
                            background=0)
    nodes = morphology.label(np.logical_and(np.not_equal(neighbors, 2),
                                            neighbors > 0), background=0)
    length_edges = np.bincount(edges.ravel())
    return nodes, edges, length_edges

# Open image and threshold
image = io.imread('contours.png')
im = image < 200
im = morphology.binary_closing(im, np.ones((5, 5)))

# Remove small connected components (small arrows)
only_big = morphology.remove_small_objects(im, 400)

# Skeletonize to get 1-pixel-thick lines
skel = morphology.skeletonize(only_big)
skel_big = morphology.remove_small_objects(skel, 30, connectivity=2)
nodes, edges, length_edges = skel_to_graph(skel_big)

# Keep only long branches of the skeleton
# The threshold can be adjusted
threshold = 35
long_edges = (length_edges < threshold)[edges]
edges[long_edges] = 0

# Visualize results
plt.figure(figsize=(10, 10))
plt.imshow(image, cmap='gray', interpolation='nearest')
plt.contour(edges > 0, [0.5], colors='red', linewidths=[2])
plt.axis('off')
plt.tight_layout()
plt.show()