ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

二进制2D矩阵的python轮廓

2019-07-01 06:45:50  阅读:141  来源: 互联网

标签:python algorithm numpy contour


我想计算二进制NxM矩阵中形状周围的凸包.凸包算法需要一个坐标列表,所以我采用numpy.argwhere(im)来获得所有形状点坐标.然而,大多数这些点对凸包没有贡献(它们位于形状的内侧).因为凸包计算时间至少与它作为输入得到的点数成正比,所以我设计了一个想法,即预先过滤过多的无用点,只传递那些跨越轮廓的点.这个想法非常简单,对于二进制NxM矩阵中的每一行,我只采用最小和最大索引.例如:

im = np.array([[1,1,1,0],
              [1,0,1,1],
              [1,1,0,1],
              [0,0,0,0],
              [0,1,1,1]], dtype=np.bool)
outline = somefunc(im)

然后应该读取大纲(在元组中或作为5×2 numpy数组,我不介意):

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

在这个形状(im)周围紧密的任何凸包必须是这些点的一个子集(轮廓).换句话说,如果“somefunc()”在过滤内部点方面是有效的,那么它节省了凸包计算的时间.

我有代码执行上述技巧,但我希望有人有一个更聪明(读取更快)的方法,因为我需要多次运行它.我的代码是:

# I have a 2D binary field. random for the purpose of demonstration.
import numpy as np
im = np.random.random((320,360)) > 0.9

# This is my algorithm so far. Notice that coords is sorted.
coords = np.argwhere(im)
left = np.roll(coords[:,0], 1, axis=0) != coords[:,0]
outline = np.vstack([coords[left], coords[left[1:]], coords[-1]])

我的另一个想法是使用Python的reduce(),所以我只需要在coords列表上运行一次.但我很难找到一个好的减少功能.

任何帮助将不胜感激!

编辑

与此同时,我发现了一种从直接转到轮廓的更快捷方式.至少对于大图像,这明显更快.在显然没有外部解决方案的情况下,我将其作为这个问题的解决方案.

不过,如果有人知道更快的方法,请说出来:)

解决方法:

如果没有可接受的答案,我会发布我最好的工作代码作为解决方案.

def outline(im):
    ''' Input binary 2D (NxM) image. Ouput array (2xK) of K (y,x) coordinates
        where 0 <= K <= 2*M.
    '''
    topbottom = np.empty((1,2*im.shape[1]), dtype=np.uint16)
    topbottom[0,0:im.shape[1]] = np.argmax(im, axis=0)
    topbottom[0,im.shape[1]:] = (im.shape[0]-1)-np.argmax(np.flipud(im), axis=0)
    mask      = np.tile(np.any(im, axis=0), (2,))
    xvalues   = np.tile(np.arange(im.shape[1]), (1,2))
    return np.vstack([topbottom,xvalues])[:,mask].T

标签:python,algorithm,numpy,contour
来源: https://codeday.me/bug/20190701/1344212.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有