我有一个包含从.png
创建的灰度图像的2D数组,如下所示:
import cv2
img = cv2.imread("./images/test.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
我想做的是提取一个仅包含包含数据的矩形的子数组-,而忽略图片周围的所有零。
例如,如果输入为:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 175 0 0 0 71 0
0 0 0 12 8 54 0 0
0 0 0 0 255 0 0 0
0 0 0 2 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
然后输出应为:
175 0 0 0 71
0 12 8 54 0
0 0 255 0 0
0 2 0 0 0
我可以向前遍历行以找到第一个非零行,然后向后遍历行以找到记住索引的最后一个非零行-然后对各列重复相同的操作,然后使用该数据提取一个子数组,但是我确保有更合适的做同样的方法,甚至可能有为此目的设计的NumPy函数。
如果要在最短的代码还是最快的执行之间进行选择,那么我会对更快的代码执行更感兴趣。
编辑:
我没有提供最佳示例,因为中间的行/列可能为零,如下所示:
输入:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 175 0 0 0 71 0
0 0 0 12 8 54 0 0
0 0 0 0 255 0 0 0
0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0
0 0 0 0 0 0 0 0
输出:
175 0 0 0 71
0 12 8 54 0
0 0 255 0 0
0 0 0 0 0
0 2 0 0 0
最佳答案
更新
使用opencv函数的这种更简单的方法实际上更快,并且可能比此处其他答案中介绍的其他方法更快。
def crop_fastest(arr):
return cv2.boundingRect(cv2.findNonZero(arr))
这将返回边界框的x,y,宽度和高度。在台式机上,输入旧代码
1000 loops, best of 3: 562 µs per loop
,输入新代码10000 loops, best of 3: 179 µs per loop
。另一个更新
正如Chupo_cro指出的那样,简单地调用
cv2.boundingRect(arr)
会返回相同的结果,这似乎是由于the code in this function在内部进行了转换。上一个答案
可能有更快的方法。此较简单的功能稍快一些。
from scipy import ndimage
def crop_fast(arr):
slice_x, slice_y = ndimage.find_objects(arr>0)[0]
return arr[slice_x, slice_y]
为了比较droooze和本代码的速度,
arr = np.zeros(shape=(50000,6), dtype=np.uint8)
arr[2] = [9,8,0,0,1,1]
arr[1] = [0,3,0,0,1,1]
然后
%timeit crop(arr)
返回1000 loops, best of 3: 1.62 ms per loop
,而%timeit crop_fast(arr)
返回便携式计算机上的1000 loops, best of 3: 979 µs per loop
。也就是说,crop_fast()
花费crop()
约60%的时间。关于python - 从表示图像的数组中排除周围零的最快方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49472962/