2016-11-22 158 views
1

我想提取图像蒙版的两个区域的索引/位置,我使用python,opencv2,numpy和scipy的组合。获取python,opencv2,numpy中图像蒙版上的特征位置索引

我有一个二进制mask与图像大小相同。 与

label_im, nb_labels = ndimage.label(mask) 
sizes = ndimage.sum(mask, label_im, range(nb_labels + 1)) 

生成标签和它的尺寸有了这些信息之后,我能提取最大的领域。

比方说,我们有一个10×10矩阵:

1  1  1  0  0  0  0  0  0  0 
1  1  1  0  0  0  0  0  0  0 
1  1  1  0  0  0  0  2  2  0 
0  0  0  0  0  0  0  2  2  0 
0  3  3  3  3  0  0  2  2  0 
0  3  3  3  3  0  0  2  2  0 
0  3  3  3  3  0  0  2  2  0 
0  3  3  3  3  0  0  2  2  0 
0  3  3  3  3  0  0  0  0  0 
0  0  0  0  0  0  0  0  0  0 

我有3个不同的区域(1,2,3),我已经知道了,我需要进一步分析区域2和3(因为这些都是两个最大)。

现在我想找到它们中的像素的索引

  1. 最上面的区域的最左 - 以下标记为(n)的
  2. 最下面的区域的最右侧的 - 与[N]
  3. 以下标

同上矩阵:

1  1  1  0  0  0  0  0  0  0 
1  1  1  0  0  0  0  0  0  0 
1  1  1  0  0  0  0 (2) 2  0 
0  0  0  0  0  0  0  2  2  0 
0 (3) 3  3  3  0  0  2  2  0 
0  3  3  3  3  0  0  2  2  0 
0  3  3  3  3  0  0  2  2  0 
0  3  3  3  3  0  0  2 [2] 0 
0  3  3  3 [3] 0  0  0  0  0 
0  0  0  0  0  0  0  0  0  0 

如何做T的最快方法帽子?

问题1: 我努力与这些矩阵条件的语法。 例如,我尝试:

mask2 = mask[label_im == 2] 

应当再次获得二进制掩码,但只有集合中的小区在其原有的面膜具有2 我不完全相信上述的结果产生。我因此无法进一步处理它。

问题2: 之后,我会做这样的事情找出其中最上边最左边的像素设置的行/列的索引。 与最低点相同。

例如,对于区域2,结果应该是:(像上面的矩阵)

point1-X = 7 
point1-Y = 2 
point2-X = 8 
point2-Y = 7 

其中X代表列,和Y为行

或者是(在索引0处开始)有更好的方法来解决像python/opencv2/numpy/scipy的组合这样的问题吗?

回答

1

NumPy的基于溶液

在输入图像阵列的扁平形式中,topmost leftmost地方将是第一的,而lowermost rightmost将是最后的。所以,有一个诀窍就是将np.nonzero这两个区域的平坦指数取得,并简单地查找minmax指数以分别得到那些预期的输出。最后,我们将使用np.unravel_index来检索与原始2D格式相对应的后行col索引。

因此,一个办法是 -

# Flattend indices for those two regions using the given labels 
idx0 = np.nonzero(a.ravel()==2)[0] 
idx1 = np.nonzero(a.ravel()==3)[0] 

# Get the min, max indices for them. Use np.unravel_index to retrieve 
# back row, col indices corresponding to original format of 2D input. 
idxs = [idx0.min(), idx0.max(), idx1.min(), idx1.max()] 
out = np.column_stack(np.unravel_index(idxs,a.shape)) 

采样运行 - 基于

In [137]: a 
Out[137]: 
array([[1, 1, 1, 0, 0, 0, 0, 0, 0, 0], 
     [1, 1, 1, 0, 0, 0, 0, 0, 0, 0], 
     [1, 1, 1, 0, 0, 0, 0, 2, 2, 0], 
     [0, 0, 0, 0, 0, 0, 0, 2, 2, 0], 
     [0, 3, 3, 3, 3, 0, 0, 2, 2, 0], 
     [0, 3, 3, 3, 3, 0, 0, 2, 2, 0], 
     [0, 3, 3, 3, 3, 0, 0, 2, 2, 0], 
     [0, 3, 3, 3, 3, 0, 0, 2, 2, 0], 
     [0, 3, 3, 3, 3, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) 

In [138]: idx0 = np.nonzero(a.ravel()==2)[0] 
    ...: idx1 = np.nonzero(a.ravel()==3)[0] 
    ...: idxs = [idx0.min(), idx0.max(), idx1.min(), idx1.max()] 
    ...: out = np.column_stack(np.unravel_index(idxs,a.shape)) 
    ...: 

In [139]: out 
Out[139]: 
array([[2, 7], # topmost leftmost of region -1 
     [7, 8], # lowermost rightmost of region -1 
     [4, 1], # topmost leftmost of region -2 
     [8, 4]]) # lowermost rightmost of region -2 

OpenCV的解决方案

的OpenCV的cv2.findContours可以用来查找轮廓,这本身就是一个很好的效果实施。因此,我们将仅限于针对性能导向解决方案的轮廓指标的发现。下面显示的是让topmost leftmostlowermost rightmost排功能,列索引为每个区域 -

def TL_LR(a, label): 
    _,contours,hierarchy = cv2.findContours((a==label).astype('uint8'),\ 
              cv2.RETR_TREE,cv2.RETR_LIST) 
    idx = contours[0].reshape(-1,2) 
    lidx = idx[:,0] + a.shape[1]*idx[:,1] 
    return np.unravel_index([lidx.min(), lidx.max()],a.shape) 

请注意,OpenCV的版本之前3.0,我们只能从cv2.findContours越来越两个输出。因此,对于这些版本,跳过该步骤的_

让我们用它在给定的样本 -

In [188]: TL_LR(a,2) 
Out[188]: (array([2, 7]), array([7, 8])) 

In [189]: TL_LR(a,3) 
Out[189]: (array([4, 8]), array([1, 4])) 

In [190]: out # Output from previous approach 
Out[190]: 
array([[2, 7], 
     [7, 8], 
     [4, 1], 
     [8, 4]]) 
+0

哇!非常感谢你的帮助!它工作完美! –

+0

我第一次尝试你的基于numpy的解决方案,然后用示例图像1920x1080的opencv解决方案。 S1的时间为:0.0529999732971s,S2的时间为:0.0599999427795s,所以这些实现之间的差异并不真正明显。无论如何,谢谢基于opencv的解决方案! –