我建议使用cv2.resize
,因为它比scipy.ndimage.zoom
快得多,可能是因为支持更简单的插值方法。
对于一张480x640的图像:
cv2.resize
花费约2毫秒
scipy.ndimage.zoom
花费约500毫秒
scipy.ndimage.zoom(...,order=0)
花费约175毫秒
如果你正在实时进行数据增强,这种速度提升是非常宝贵的,因为它意味着在更短的时间内进行更多的实验。
这里是一个使用cv2.resize
的clipped_zoom
版本。
def cv2_clipped_zoom(img, zoom_factor=0):
"""
Center zoom in/out of the given image and returning an enlarged/shrinked view of
the image without changing dimensions
------
Args:
img : ndarray
Image array
zoom_factor : float
amount of zoom as a ratio [0 to Inf). Default 0.
------
Returns:
result: ndarray
numpy ndarray of the same shape of the input img zoomed by the specified factor.
"""
if zoom_factor == 0:
return img
height, width = img.shape[:2]
new_height, new_width = int(height * zoom_factor), int(width * zoom_factor)
y1, x1 = max(0, new_height - height) // 2, max(0, new_width - width) // 2
y2, x2 = y1 + height, x1 + width
bbox = np.array([y1,x1,y2,x2])
bbox = (bbox / zoom_factor).astype(np.int)
y1, x1, y2, x2 = bbox
cropped_img = img[y1:y2, x1:x2]
resize_height, resize_width = min(new_height, height), min(new_width, width)
pad_height1, pad_width1 = (height - resize_height) // 2, (width - resize_width) //2
pad_height2, pad_width2 = (height - resize_height) - pad_height1, (width - resize_width) - pad_width1
pad_spec = [(pad_height1, pad_height2), (pad_width1, pad_width2)] + [(0,0)] * (img.ndim - 2)
result = cv2.resize(cropped_img, (resize_width, resize_height))
result = np.pad(result, pad_spec, mode='constant')
assert result.shape[0] == height and result.shape[1] == width
return result
scipy.ndimage.zoom
太慢了(不知道为什么),所以你的函数对于一个(480,640)的图像需要大约500毫秒。 - MohamedEzzzoom_factor > 1
时,我计算缩放区域的边界框时存在错误,现在已经修复。clipped_zoom
将关键字参数传递给scipy.ndimage.zoom
,因此如果三次样条插值太慢,可以传递order=0
。我不怀疑cv2.resize
更快,但 OpenCV 是一个庞大的依赖项,而 OP 正在寻求基于 scipy 的解决方案。 - ali_mint(np.round(h * zoom_factor))
中的四舍五入似乎有时会导致生成的图像比目标小1个像素。然后计算得到-1作为差异,输出的图像像素大小为1。改用np.ceil()
而不是np.round()
似乎可以解决这个问题。 - kg_sYy