python 使用SciPy进行图像缩放-尺寸错误

iezvtpos  于 2022-11-21  发布在  Python
关注(0)|答案(1)|浏览(155)

此问题答案中的代码对某些缩放因子值产生错误。
正如@kg_sYy在注解中提到的,“* int(np.round(h * zoom_factor))中的舍入有时会导致生成的图像比目标小1个像素。然后计算得到-1作为diff,您得到的图像像素大小为1用于输出。更改为np.ceil()而不是np.round()似乎可以修复它。*”但是,更改为np.ceil()并不能修复错误。
例如,zoom_factor = 1.1317和图像shape (331, 331, 3)导致zoomed_img的大小为一个像素。
还有哪种舍入函数可以解决此问题?为什么会出现此问题?

svgewumm

svgewumm1#

为什么它变成了一个像素

您所链接的代码假设:
out由于舍入可能仍略大于img,因此请修剪掉边缘的任何多余像素
然后不做任何检查就进行修剪。当out实际上小于img时,缩放后的图像变成1个像素(正如注解中提到的,由于舍入错误)。然后以下计算失败:

trim_top = ((out.shape[0] - h) // 2)
trim_left = ((out.shape[1] - w) // 2)

由于新图像实际上小于(h, w),因此trim_toptrim_left实际上是负数(根据经验为-1)。
最后的修剪实际上是:

out = out[-1: h - 1, -1: w - 1]

这只是右下角的像素[-1,-1]。

如何修复

  • 确保out等于或大于img。使用ceil() * 应该 * 可以处理这个问题。(看看是否可以找到out仍然小于img的任何图像大小和缩放因子。)
  • 在尝试修剪out之前,请检查它是否确实大于img
  • 在修剪时处理可能的圆角。
def clipped_zoom(img, zoom_factor, **kwargs):
    h, w = img.shape[:2]

    zoom_tuple = (zoom_factor,) * 2 + (1,) * (img.ndim - 2)

    # Zooming out
    if zoom_factor < 1:

        # Bounding box of the zoomed-out image within the output array
        zh = int(np.round(h * zoom_factor))
        zw = int(np.round(w * zoom_factor))
        top = (h - zh) // 2
        left = (w - zw) // 2

        # Zero-padding
        out = np.zeros_like(img)
        out[top:top+zh, left:left+zw] = zoom(img, zoom_tuple, **kwargs)

    # Zooming in
    elif zoom_factor > 1:

        # Bounding box of the zoomed-in region within the input array
        zh = int(np.ceil(h / zoom_factor))
        zw = int(np.ceil(w / zoom_factor))

        top = (h - zh) // 2
        left = (w - zw) // 2

        out = zoom(img[top: top + zh, left: left + zw], zoom_tuple, **kwargs)

        # >>> Check out against img before trying to trim
        # >>> trim safely, accounting for rounding

        if out.shape[0] > h:
            h_diff = out.shape[0] - h
            trim_top = h_diff // 2
            trim_bottom = h_diff - trim_top
            out = out[trim_top: out.shape[0] - trim_bottom, :]

        if out.shape[1] > w:
            w_diff = out.shape[1] - w
            trim_left = w_diff // 2
            trim_right = w_diff - trim_left
            out = out[:, trim_left: out.shape[1] - trim_right]     

    # If zoom_factor == 1, just return the input array
    else:
        out = img
    return out

相关问题