本篇内容介绍了“Python怎么实现标记数组的连通域”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
连通域标记
通过label函数,可以对数组中的连通区域进行标注,效果如下
from scipy.ndimage import label import numpy as np a = np.array([[0,0,1,1,0,0], [0,0,0,1,0,0], [1,1,0,0,1,0], [0,0,0,1,0,0]]) labels, N = label(a) print(labels) ''' [[0 0 1 1 0 0] [0 0 0 1 0 0] [2 2 0 0 3 0] [0 0 0 4 0 0]] ''' print(N) 4
其中,
a是一个二值矩阵,经过
label标记后,其相连通的部分分别被标上了序号。可以更直观地用图像显示一下
import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(121) plt.imshow(a) ax = fig.add_subplot(122) plt.imshow(labels) plt.show()
structure参数
在label函数中,还有一个用于规范何为“连通”的参数,即structure,其数据类型为二值数组,其维度与输入的input相同。
在上面的示例中,连通域1,3,4尽管没有上下左右的联系,但在对角线上是有交集的,通过调整structure参数,可以提供一种将这三个区域连在一起的连通域方案。
stru = np.ones([3,3]) bLab, bN = label(a, stru) print(bLab) ‘'‘ [[0 0 1 1 0 0] [0 0 0 1 0 0] [2 2 0 0 1 0] [0 0 0 1 0 0]] '‘'
可见,这次只选出了两组连通域。
操作连通域
scipy.ndimage提供了labeled_comprehension函数,其功能大致相当于[func(input[labels == i]) for i in index],即从已经做好连。通域标记的数组中,取出序号为index所在区域的值,参数如下
labeled_comprehension(input, labels, index, func, out_dtype, default, pass_positions=False)
其中input为输入数组;labels是已经做好的连通域标记;index为将要挑选进行操作的连通域序号;func为具体的操作函数;out_dtype为输出数据类型;default表示,当index不存在于连通域标记中时的输出值,下面做一个示例
from scipy.ndimage import labeled_comprehension labeled_comprehension(a, labels, [1,2,3,4], sum, int, 0) # array([3, 2, 1, 1])
连通域序号为1,2,3,4的区域,分别有3,2,1,1个元素,而且所有元素都是1,所以求和之后的值为[3, 2, 1, 1]。
定位连通域
scipy.ndimage中的find_objects函数可以返回连通域的切片范围。
from scipy.ndimage import find_objects axis = find_objects(labels) for x,y in axis: print(x, y) ''' slice(0, 2, None) slice(2, 4, None) slice(2, 3, None) slice(0, 2, None) slice(2, 3, None) slice(4, 5, None) slice(3, 4, None) slice(3, 4, None) ''''
如果根据这个对原数组进行切片,就可以得到其对应的标记区域
for x,y in axis: print(labels[x,y]) print("--------") ''' [[1 1] [0 1]] -------- [[2 2]] -------- [[3]] -------- [[4]] -------- '''