Scipy旋转和缩放图像而不更改其尺寸 [英] Scipy rotate and zoom an image without changing its dimensions

查看:1733
本文介绍了Scipy旋转和缩放图像而不更改其尺寸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于我的神经网络,我希望通过向我的图像添加小的随机旋转和缩放来增加我的训练数据。我遇到的问题是scipy在应用旋转和缩放时会改变图像的大小。如果图像的一部分超出边界,我需要剪切边缘。我的所有图片大小必须相同。

  def loadImageData(img,distort = False):
c,fn = img
img = scipy.ndimage.imread(fn,True)

如果扭曲:
img = scipy.ndimage.zoom(img,1 + 0.05 * rnd() ,mode ='constant')
img = scipy.ndimage.rotate(img,10 * rnd(),mode ='constant')
print(img.shape)

img = img - np.min(img)
img = img / np.max(img)
img = np.reshape(img,(1,* img.shape))

y = np.zeros(ncats)
y [c] = 1
return(img,y)


解决方案



物联网更复杂的


For my neural network I want to augment my training data by adding small random rotations and zooms to my images. The issue I am having is that scipy is changing the size of my images when it applies the rotations and zooms. I need to to just clip the edges if part of the image goes out of bounds. All of my images must be the same size.

def loadImageData(img, distort = False):
    c, fn = img
    img = scipy.ndimage.imread(fn, True)

    if distort:
        img = scipy.ndimage.zoom(img, 1 + 0.05 * rnd(), mode = 'constant')
        img = scipy.ndimage.rotate(img, 10 * rnd(), mode = 'constant')
        print(img.shape)

    img = img - np.min(img)
    img = img / np.max(img)
    img = np.reshape(img, (1, *img.shape))

    y = np.zeros(ncats)
    y[c] = 1
    return (img, y)

解决方案

scipy.ndimage.rotate accepts a reshape= parameter:

reshape : bool, optional

If reshape is true, the output shape is adapted so that the input array is contained completely in the output. Default is True.

So to "clip" the edges you can simply call scipy.ndimage.rotate(img, ..., reshape=False).

from scipy.ndimage import rotate
from scipy.misc import face
from matplotlib import pyplot as plt

img = face()
rot = rotate(img, 30, reshape=False)

fig, ax = plt.subplots(1, 2)
ax[0].imshow(img)
ax[1].imshow(rot)

Things are more complicated for scipy.ndimage.zoom.

A naive method would be to zoom the entire input array, then use slice indexing and/or zero-padding to make the output the same size as your input. However, in cases where you're increasing the size of the image it's wasteful to interpolate pixels that are only going to get clipped off at the edges anyway.

Instead you could index only the part of the input that will fall within the bounds of the output array before you apply zoom:

import numpy as np
from scipy.ndimage import zoom


def clipped_zoom(img, zoom_factor, **kwargs):

    h, w = img.shape[:2]

    # For multichannel images we don't want to apply the zoom factor to the RGB
    # dimension, so instead we create a tuple of zoom factors, one per array
    # dimension, with 1's for any trailing dimensions after the width and height.
    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.round(h / zoom_factor))
        zw = int(np.round(w / zoom_factor))
        top = (h - zh) // 2
        left = (w - zw) // 2

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

        # `out` might still be slightly larger than `img` due to rounding, so
        # trim off any extra pixels at the edges
        trim_top = ((out.shape[0] - h) // 2)
        trim_left = ((out.shape[1] - w) // 2)
        out = out[trim_top:trim_top+h, trim_left:trim_left+w]

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

For example:

zm1 = clipped_zoom(img, 0.5)
zm2 = clipped_zoom(img, 1.5)

fig, ax = plt.subplots(1, 3)
ax[0].imshow(img)
ax[1].imshow(zm1)
ax[2].imshow(zm2)

这篇关于Scipy旋转和缩放图像而不更改其尺寸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆