python - 将 Python 数组分割成由单个单元格或更少单元格连接的独特区域?

标签 python arrays image-processing numpy scipy

我有一个 numpy 数组,我希望将其分割成具有唯一 ID 的离散区域,如下所示:

Example array

通常对于这样的事情,我会使用 scipy.ndimage.label 为离散的 blob 生成唯一的 id,但在这种情况下,我有几个非常大的连续区域,我也希望将它们分割成较小的独特区域,理想情况下,当它们仅通过 1 个单元宽的连接连接到它们的邻居时。为了说明这一点,这里有一个示例数组,我在运行 scipy.ndimage.label 时得到的结果,以及我想要的结果:

import numpy as np
import scipy.ndimage as ndimage
import matplotlib.pyplot as plt

# Sample study area array
example_array = np.array([[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
                          [0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1],
                          [0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1],
                          [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
                          [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1],
                          [1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1],
                          [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1],
                          [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
                          [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0],
                          [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0],
                          [1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0],
                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

# Identify discrete regions and assign unique IDs
current_output, num_ids = ndimage.label(example_array, structure=np.ones((3,3)))

# Plot outputs
plt.imshow(example_array, cmap="spectral", interpolation='nearest')
plt.imshow(current_output, cmap="spectral", interpolation='nearest')

Outputs and expected outputs

细胞的具体编号和划分并不重要;任何类似于上面最后一个情节的东西都可以。到目前为止,我最好的尝试是使用形态学图像处理来首先腐 eclipse 我的阵列,运行 scipy.ndimage.label 然后扩张,但这有一个不幸的副作用,即消除所有单细胞区域或变薄线性特征(其中有很多)。

非常感谢任何想法!

最佳答案

最简单的做法可能是在 SciPy 标记之前应用以下预处理内核(以 2,2 为原点,“?”可以是 0 或 1):

IF |? 1 ?| OR |? 0 ?| THEN origin(x,y) == 0
   |0 1 0|    |1 1 1|
   |? 1 ?|    |? 0 ?|

实现:

import numpy as np
import scipy.ndimage as ndimage
import matplotlib.pyplot as plt

# Sample study area array
example_array = np.array([[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
                          [0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1],
                          [0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1],
                          [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
                          [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1],
                          [1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1],
                          [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1],
                          [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
                          [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0],
                          [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0],
                          [1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0],
                          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

# Get array shape
row_count, column_count = example_array.shape

# Iterate through kernel origins
for (x,y), value in np.ndenumerate(example_array):

    # Skip first and last rows and columns because kernel would be out of bounds
    if not (x == 0 
         or x == row_count-1 
         or y == 0 
         or y == column_count-1):

        # Extract kernel
        kernel = example_array[x-1:x+2, y-1:y+2]
      
        # Apply IF |? 1 ?| OR |? 0 ?| THEN origin(x,y) == 0
        #          |0 1 0|    |1 1 1|
        #          |? 1 ?|    |? 0 ?|
        if ((kernel[1,0:3]).all() == 1 and kernel[0,1] == 0 and kernel[2,1] == 0 
            or (kernel[0:3,1]).all() == 1 and kernel[1,0] == 0 and kernel[1,2] == 0):
            example_array[x,y] = 0
                
# Identify discrete regions and assign unique IDs
current_output, num_ids = ndimage.label(example_array, structure=np.ones((3,3)))

# Plot outputs
plt.imshow(example_array, cmap="spectral", interpolation='nearest')
plt.imshow(current_output, cmap="spectral", interpolation='nearest')

结果: enter image description here

关于python - 将 Python 数组分割成由单个单元格或更少单元格连接的独特区域?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29245667/

相关文章:

python - 在二维中扩展 numpy 数组的最简单方法是什么?

python - 快速查找二维数组中的多个最大值

arrays - 从值字典数组中检索键

arrays - 按最后一个字母对单词数组进行排序

c++ - 从给定的图像数据中提取像素数据。需要帮助理解代码

python - 如何从表单的扫描图像中提取数据?

python - join() 参数必须是 str 或字节,而不是 'dict' -- 在 Django 中创建具有多表继承的表单

python - 如何绘制系数错误的函数?

python - 如何在 Python 中使用 IDL 可视化例程

python - 通过 opencv 和 python 实时跟踪对象