【问题标题】:Python equivalent of label2idx MATLAB function相当于 label2idx MATLAB 函数的 Python
【发布时间】:2019-06-25 09:03:18
【问题描述】:

在python中有没有label2idx()函数的库实现?

我希望将超像素从标签表示中提取为 label2idx() 函数准确返回的格式。

label2idx 函数:https://in.mathworks.com/help/images/ref/label2idx.html

【问题讨论】:

  • 您可能正在寻找np.where(label_arr == label_value)
  • @norok2 不完全是。我必须遍历所有标签值并基本上实现 label2idx。我对更简洁、更快速代码的库实现很感兴趣。
  • 你是对的,你必须先.ravel() label_arr 并循环遍历标签值。

标签: python matlab numpy


【解决方案1】:

给定一个标签数组 label_arr,其中包含从 1max(label_arr) 的所有标签,您可以这样做:

def label2idx(label_arr):
    return [
        np.where(label_arr.ravel() == i)[0]
        for i in range(1, np.max(label_arr) + 1)]

如果你想放宽所有标签被包含的要求,你可以添加一个简单的if,即:

def label2idx(label_arr):
    return [
        np.where(label_arr.ravel() == i)[0]
            if i in label_arr else np.array([], dtype=int)
        for i in range(1, np.max(label_arr) + 1)]

只是为了复制 MATLAB 文档中的示例:

import numpy as np
import scipy as sp
import scipy.ndimage

struct_arr = np.array(
    [[1, 1, 1, 0, 0, 0, 0, 0],
     [1, 1, 1, 0, 1, 1, 0, 0],
     [1, 1, 1, 0, 1, 1, 0, 0],
     [1, 1, 1, 0, 0, 0, 0, 0],
     [1, 1, 1, 0, 0, 0, 1, 0],
     [1, 1, 1, 0, 0, 0, 1, 0],
     [1, 1, 1, 0, 0, 1, 1, 0],
     [1, 1, 1, 0, 0, 0, 0, 0]])

label_arr, num_labels = sp.ndimage.label(struct_arr)
# label_arr:
# [[1 1 1 0 0 0 0 0]
#  [1 1 1 0 2 2 0 0]
#  [1 1 1 0 2 2 0 0]
#  [1 1 1 0 0 0 0 0]
#  [1 1 1 0 0 0 3 0]
#  [1 1 1 0 0 0 3 0]
#  [1 1 1 0 0 3 3 0]
#  [1 1 1 0 0 0 0 0]]

def label2idx(label_arr):
    return [
        np.where(label_arr.ravel() == i)[0]
        for i in range(1, np.max(label_arr) + 1)]

pixel_idxs = label2idx(label_arr)

for pixel_idx in pixel_idxs:
    print(pixel_idx)

# [ 0  1  2  8  9 10 16 17 18 24 25 26 32 33 34 40 41 42 48 49 50 56 57 58]
# [12 13 20 21]
# [38 46 53 54]

请注意,由于 MATLAB 和 NumPy 之间的差异,您不会得到完全相同的结果,特别是:

  • MATLAB:FORTRAN 风格的矩阵索引和基于 1 的索引
  • Python+NumPy:C 风格的矩阵索引和基于 0 的索引

如果您想获得与 MATLAB 中相同的数字,您可以改用它(注意额外的 .T+ 1):

def label2idx_MATLAB(label_arr):
    return [
        np.where(label_arr.T.ravel() == i)[0] + 1
        for i in range(1, np.max(label_arr) + 1)]

【讨论】:

    【解决方案2】:

    MATLAB 的 label2idx 在给定标记图像的情况下输出扁平索引(按列排序)。

    我们可以使用scikit-image's 内置regionprops 从标记的图像中获取这些索引。 Scikit-image 还为我们提供了一个内置功能来获取标记的图像,因此使用同一个包即可。实现看起来像这样 -

    from skimage.measure import label,regionprops
    
    def label2idx(L):
        # Get region-properties for all labels
        props = regionprops(L)
    
        # Get XY coordinates/indices for each label
        indices = [p.coords for p in props]
    
        # Get flattened-indices for each label, similar to MATLAB version
        # Note that this is row-major ordered.
        flattened_indices = [np.ravel_multi_index(idx.T,L.shape) for idx in indices]
        return indices, flattened_indices
    

    示例运行 -

    # Input array
    In [62]: a
    Out[62]: 
    array([[1, 1, 1, 0, 0, 0, 0, 0],
           [1, 1, 1, 0, 1, 1, 0, 0],
           [1, 1, 1, 0, 1, 1, 0, 0],
           [1, 1, 1, 0, 0, 0, 0, 0],
           [1, 1, 1, 0, 0, 0, 1, 0],
           [1, 1, 1, 0, 0, 0, 1, 0],
           [1, 1, 1, 0, 0, 1, 1, 0],
           [1, 1, 1, 0, 0, 0, 0, 0]])
    
    # Get labeled image
    In [63]: L = label(a)
    
    In [64]: idx,flat_idx = label2idx(L)
    
    In [65]: flat_idx
    Out[65]: 
    [array([ 0,  1,  2,  8,  9, 10, 16, 17, 18, 24, 25, 26, 32, 33, 34, 40, 41,
            42, 48, 49, 50, 56, 57, 58]),
     array([12, 13, 20, 21]),
     array([38, 46, 53, 54])]
    

    如果您需要像 MATLAB 中那样以列优先顺序排列的索引,只需转置图像,然后输入 -

    In [5]: idx,flat_idx = label2idx(L.T)
    
    In [6]: flat_idx
    Out[6]: 
    [array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
            17, 18, 19, 20, 21, 22, 23]),
     array([33, 34, 41, 42]),
     array([46, 52, 53, 54])]
    

    请注意,索引仍然从 0 开始,不像在 MATLAB 中它从 1 开始。

    使用 SciPy 获取标记图像的替代方法

    SciPy 还内置了获取标签图像的功能:scipy.ndimage.label -

    from scipy.ndimage import label
    
    L = label(a)[0]
    

    【讨论】:

    • 我认为这可以使用np.where()以更简单(可能更快)的方式解决
    • 这不是 MATLAB 文档中的预期行为。 MATLAB 函数返回一个 cell 数组 - 它是像素 ID 的集合(以列为主的线性索引)。
    • @AnshKhurana Python 或 NumPy 没有任何元胞数组的概念。最接近的和基于 NumPy 的将是作为数组的索引列表,这就是我们在这里得到的。您是否期待任何其他类型的输出格式?
    • @AnshKhurana 如果您需要以列为主的排序方式,只需转置标记的图像,然后将其提供给建议的解决方案。在帖子中添加了相同的示例代码。
    猜你喜欢
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    相关资源
    最近更新 更多