二进制二维矩阵的python轮廓
我想计算二进制 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)
那么轮廓应该读作(在元组中或作为 5x2 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(),所以我只需要运行一次坐标列表。但我很难找到一个好的归约函数。
任何帮助将不胜感激!
编辑
与此同时,我找到了一种更快的方法从 im
直接转到 outline
。至少对于大图像来说,这要快得多。在显然缺乏外部解决方案的情况下,我将其作为该问题的解决方案。
不过,如果有人知道更快的方法,请说出来:)
I want to calculate a convex hull around a shape in a binary NxM matrix. The convex hull algorithm expects a list of coordinates, so I take numpy.argwhere(im) to have all shape point coordinates. However, most of those points are not contributing to the convex hull (they lie on the inside of the shape). Because convex hull computation time is at least proportional to the number of points that it gets as input, I devised an idea to filter the plethora of useless points on beforehand and only pass those that span the outline. The idea is quite simple, that for each row in the binary NxM matrix I take only the minimal and maximal indices. So for example:
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)
Then outline should read (in tuples or as a 5x2 numpy array, I don't mind):
[(0,0),(0,2),(1,0),(1,3),(2,0),(2,3),(4,1),(4,3)]
Any convex hull tight around this shape (im), must a subset of these points (outline). In other words, if "somefunc()" is efficient in filtering the inside points then it saves time for the convex hull computation.
I have code that does the above trick, but I am hoping someone has a more clever (read faster) approach since I need to run it many many times. The code I have is:
# 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]])
Another idea I had was to use Python's reduce() so I'd need to run over the list of coords only once. But I have difficulty finding a good reducing function.
Any help would greatly be appreciated!
edit
In the meanwhile I have found a faster way to go from im
directly to outline
. At least with large images this is significantly faster. In the apparent absence of an external solution I am positing it as the solution to this question.
Still, if somebody knows an even faster method, please speak up :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在没有可接受的答案的情况下,我发布了我最好的工作代码作为解决方案。
In the absence of an acceptable answer I post my best working code as the solution.
这个作业似乎完成了与你最后两个步骤相同的事情:
但是不知道它是否更快。
This assignment seems to accomplish the same thing as your last two steps:
Don't know if it's any faster, however.
对于更通用的解决方案,您可以使用某种边缘检测方法来仅查找边缘点。我相信(Google..)NumPy 有内置的 sobel 过滤器,它可以做到这一点。
For more general solution, you could use somekind of edge detection method to find only the edge points. I believe (Google..) that NumPy has built-in sobel filter, which will do that.