问题描述
我想从图像中提取矩形 ROI。 图像包含单个连接的非零部分。
我需要它在运行时高效。
我在想:
有更好的方法吗?
我的代码:
import numpy as np
from PIL import Image
def first_last_nonzero(boolean_vector):
first = last = -1
for idx,val in enumerate(boolean_vector):
if val == True and first == -1:
first = idx
if val == False and first != -1:
last = idx
return first,last
然后创建一个图像:
np_im = np.array([[ 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 255 154 251 60 0 0 0]
[ 0 0 0 0 4 66 0 0 255 0 0 0]
[ 0 0 0 0 0 0 0 134 48 0 0 0]
[ 0 0 0 0 0 0 236 70 0 0 0 0]
[ 0 0 0 0 1 255 0 0 0 0 0 0]
[ 0 0 0 0 255 24 24 24 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0]])
然后在每个轴的总和上运行我们的函数:
y_start,y_end = first_last_nonzero(np.sum(np_im,1)>0)
x_start,x_end = first_last_nonzero(np.sum(np_im,0)>0)
cropped_np_im = np_im[y_start:y_end,x_start:x_end]
# show the cropped image
Image.fromarray(cropped_np_im).show()
这行得通,但可能有很多不必要的计算。 有一个更好的方法吗?或者更像pythonic的方式?
解决方法
您可以使用这篇文章中的功能: Numpy: How to find first non-zero value in every column of a numpy array?
def first_nonzero(arr,axis,invalid_val=-1):
mask = arr!=0
return np.where(mask.any(axis=axis),mask.argmax(axis=axis),invalid_val)
def last_nonzero(arr,invalid_val=-1):
mask = arr!=0
val = arr.shape[axis] - np.flip(mask,axis=axis).argmax(axis=axis) - 1
return np.where(mask.any(axis=axis),val,invalid_val)
arr = np.array([
[0,1,1],[0,0],0] ])
y_Min,y_Max,x_Min,x_Max = (0,0)
y_Min = first_nonzero(arr,axis = 0,invalid_val = -1)
y_Min = (y_Min[y_Min >= 0]).min()
x_Min = first_nonzero(arr,axis = 1,invalid_val = -1)
x_Min = (x_Min[x_Min >= 0]).min()
y_Max = last_nonzero(arr,invalid_val = -1)
y_Max = (y_Max[y_Max >= 0]).max()
x_Max = last_nonzero(arr,invalid_val = -1)
x_Max = (x_Max[x_Max >= 0]).max()
print(x_Min)
print(y_Min)
print(x_Max)
print(y_Max)
对于我的这个例子,代码将返回 1,5,4。 作为 Python 的一般经验法则:不惜一切代价尝试避免循环。根据我自己的经验,这句话在 100 个案例中有 99 个是正确的