简体   繁体   English

如何重塑3D numpy数组?

[英]How to reshape a 3D numpy array?

I have a list of numpy arrays which are actually input images to my CNN. 我有一个numpy数组的列表,这些数组实际上是我的CNN的输入图像。 However size of each of my image is not cosistent, and my CNN takes only images which are of dimension 224X224. 但是,我的每个图像的大小都不一致,并且我的CNN仅拍摄尺寸为224X224的图像。 How do I reshape each of my image into the given dimension? 如何将每个图像重塑为给定尺寸? print(train_images[key].reshape(224, 224,3))

gives me an output 给我一个输出

ValueError: total size of new array must be unchanged I would be very grateful if anybody could help me with this. ValueError: total size of new array must be unchanged如果有人可以帮助我,我将非常感激。

Here are a few ways I know to achieve this: 我知道几种实现此目的的方法:

  1. Since you're using python, you can use cv2.resize() , to resize the image to 224x224. 由于您使用的是python,因此可以使用cv2.resize()将图像调整为224x224。 The problem here is going to be distortions. 这里的问题将是失真。
  2. Scale the image to adjust to one of the required sizes (W=224 or H=224) and trim off whatever is extra. 缩放图像以调整为所需大小之一(W = 224或H = 224),并修剪掉多余的部分。 There is a loss of information here. 这里缺少信息。
  3. If you have the larger image, and a bounding box, use some delta to bounding box to maintain the aspect ratio and then resize down to the required size. 如果您有较大的图像和一个边框,请使用一定数量的边框来保持纵横比,然后将其调整为所需的尺寸。

When you reshape a numpy array, the produce of the dimensions must match. 重塑numpy数组时,尺寸的产生必须匹配。 If not, it'll throw a ValueError as you've got. 如果没有,它将抛出ValueError There's no solution using reshape to solve your problem, AFAIK. 没有使用reshape来解决您的问题的解决方案AFAIK。

New array should have the same amount of values when you are reshaping. 重塑时,新数组应具有相同数量的值。 What you need is cropping the picture (if it is bigger than 224x224) and padding (if it is smaller than 224x224) or resizing on both occasions. 您需要的是裁剪图片(如果大于224x224)和填充(如果小于224x224)或两种情况都需要调整大小。

Cropping is simply slicing with correct indexes: 裁剪只是对具有正确索引的切片:

def crop(np_img, size):
    v_start = round((np_img.shape[0] - size[0]) / 2)
    h_start = round((np_img.shape[1] - size[1]) / 2)
    return np_img[v_start:v_start+size[1], h_start:h_start+size[0],:]

Padding is slightly more complex, this will create a zeros array in desired shape and plug in the values of image inside: 填充稍微复杂一点,这将创建所需形状的零点数组,并插入其中的image值:

def pad_image(np_img, size):
    v_start = round((size[0] - np_img.shape[0]) / 2)
    h_start = round((size[1] - np_img.shape[1]) / 2)

    result = np.zeros(size)
    result[v_start:v_start+np_img.shape[1], h_start:h_start+np_img.shape[0], :] = np_img

    return result

You can also use np.pad function for it: 您也可以使用np.pad函数:

def pad_image(np_img, size):
    v_dif = size[0] - np_img.shape[0]
    h_dif = size[1] - np_img.shape[1]
    return np.lib.pad(np_img, ((v_dif, 0), (h_dif, 0), (0, 0)), 'constant', constant_values=(0))

You may realize padding is a bit different in two functions, I didn't want to over complicate the problem and just padded top and left on the second function. 您可能意识到填充在两个函数中有些不同,我不想让问题变得复杂,只需在第二个函数的顶部和左侧填充。 Did the both sides in first one since it was easier to calculate. 双方都在第一个中进行,因为它更容易计算。

And finally for resizing, you better use another library. 最后,为了调整大小,最好使用另一个库。 You can use scipy.misc.imresize , its pretty straightforward. 您可以使用scipy.misc.imresize ,它非常简单。 This should do it: 应该这样做:

imresize(np_img, size)

The standard way is to resize the image such that the smaller side is equal to 224 and then crop the image to 224x224. 标准方法是调整图像大小,使较小的一面等于224,然后将图像裁剪为224x224。 Resizing the image to 224x224 may distort the image and can lead to erroneous training. 将图像调整为224x224的尺寸可能会使图像失真,并可能导致错误的训练。 For example, a circle might become an ellipse if the image is not a square. 例如,如果图像不是正方形,则圆形可能会变成椭圆形。 It is important to maintain the original aspect ratio. 保持原始宽高比很重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM