【问题标题】:Resize a image while keeping its ratio using Python使用 Python 在保持比例的同时调整图像大小
【发布时间】:2021-06-12 03:15:13
【问题描述】:

我有一个关于使用 python 对某些图像进行预处理的问题。我找到的大多数答案都使用 Java,我需要使用 Python。

我有一个包含 2050 张图像的训练集,我想将它们的大小调整为 224 x 224,以便稍后将它们提供给卷积神经网络 (CNN)。最大的问题是我不能在不丢失图像比例的情况下做到这一点。并非所有图像的大小都相同。例如,我有 1000 x 700 像素和 700 x 600 像素的图像。

我的想法是使用周围像素的平均值来填充图像较小的一侧。但我真的不知道如何将它与我已经拥有的东西结合起来。我听说过 cv2 库,但我一直无法让它工作。

我的代码如下:

training_set = pd.DataFrame({'Images': training_imgs,'Labels': training_labels})

 
train_dataGen = ImageDataGenerator(rescale=1./255)

train_generator = train_dataGen .flow_from_dataframe(
      dataframe = training_set, directory="",
      x_col="Images", y_col="Labels", 
      class_mode="categorical", 
      target_size=(224,224), batch_size=32)

## Steps to plot the images
imgs, labels = next(train_generator)

for i in range(batch_size):   
    image = imgs[i]
    plt.imshow(image)
    plt.show()

【问题讨论】:

标签: python image-processing


【解决方案1】:

你快完成了。如果你使用 keras,这里不需要 opencv。

image = imgs[i,:,:,:] # batch_size, height, width, channels
print(np.shape(image) # should be (224,224) in case your image is grayscale
plt.imshow(image)
plt.show()

这将显示您调整大小的图像并打印它的形状。如果要更改调整大小方法的插值方法,可以查看documentation。默认情况下它是双线性的,我认为这就是您要寻找的。​​p>

编辑 0:如果您想创建自定义函数以对图像进行任何类型的预处理(调整大小等),您可以在 ImageDataGenerator 方法中定义 preprocessing_function。该函数适用于批次中的每张图片。

import cv2

def preprocess(image):
   # feel free to define your own function here
   # be sure this function returns an image

   processed_image = cv2.resize(image, dsize=(224,224)) 

   return processed_image

train_dataGen = ImageDataGenerator(preprocessing_function=preprocess,
                                   rescale=1./255)

【讨论】:

  • 我已经看到了,但是所有的插值方法仍然会使一些图像被拉伸并且看起来不像原始图像。所以我的想法是创建一个方法,然后将其插入我已有的方法中
【解决方案2】:

这是我根据您的描述编写的调整大小程序:

from PIL import Image
import math

def ResizeImage(Img, SourceWidth, SourceHeight, DestinationWidth, DestinationHeight, Average=True):
    tmp = [None] * DestinationWidth * DestinationHeight
    x_ratio = SourceWidth / float(DestinationWidth); y_ratio = SourceHeight / float(DestinationHeight)
    for i in range(0, DestinationWidth):
         for j in range(0, DestinationHeight):
             if Average:
                 tmp[i*DestinationWidth+j] = AverageOfSurrounding(Img, math.floor(j*x_ratio), math.floor(i*y_ratio))
             else:
                 tmp[i*DestinationWidth+j] = Img.getpixel((math.floor(j*x_ratio),math.floor(i*y_ratio)))
    im2 = Image.new(Img.mode, (DestinationWidth,DestinationHeight))
    im2.putdata(tmp)
    return im2

def AverageOfSurrounding(Img, x, y):
    if (x == 0):  # Left
        if (y == 0): # Bottom left
            p1 = Img.getpixel((x,y)); p2 = Img.getpixel((x+1,y)); p3 = Img.getpixel((x+1,y+1)); p4 = Img.getpixel((x,y+1))
            return (int((p1[0]+p2[0]+p3[0]+p4[0])/4), int((p1[1]+p2[1]+p3[1]+p4[1])/4), int((p1[2]+p2[2]+p3[2]+p4[2])/4), int((p1[3]+p2[3]+p3[3]+p4[3])/4))
        elif (y == Img.height): # Top left
            p1 = Img.getpixel((x,y)); p2 = Img.getpixel((x+1,y)); p3 = Img.getpixel((x+1,y-1)); p4 = Img.getpixel((x,y-1))
            return (int((p1[0]+p2[0]+p3[0]+p4[0])/4), int((p1[1]+p2[1]+p3[1]+p4[1])/4), int((p1[2]+p2[2]+p3[2]+p4[2])/4), int((p1[3]+p2[3]+p3[3]+p4[3])/4))
        else:
            p1 = Img.getpixel((x,y)); p2 = Img.getpixel((x+1,y)); p3 = Img.getpixel((x+1,y+1)); p4 = Img.getpixel((x,y+1)); p5 = Img.getpixel((x,y-1)); p6 = Img.getpixel((x+1,y-1))
            return (int((p1[0]+p2[0]+p3[0]+p4[0]+p5[0]+p6[0])/6), int((p1[1]+p2[1]+p3[1]+p4[1]+p5[1]+p6[1])/6), int((p1[2]+p2[2]+p3[2]+p4[2]+p5[2]+p6[2])/6), int((p1[3]+p2[3]+p3[3]+p4[3]+p5[3]+p6[3])/6))
    elif (x == Img.width):  # Right
        if (y == 0): # Bottom Right
            p1 = Img.getpixel((x,y)); p2 = Img.getpixel((x-1,y)); p3 = Img.getpixel((x-1,y+1)); p4 = Img.getpixel((x,y+1))
            return (int((p1[0]+p2[0]+p3[0]+p4[0])/4), int((p1[1]+p2[1]+p3[1]+p4[1])/4), int((p1[2]+p2[2]+p3[2]+p4[2])/4), int((p1[3]+p2[3]+p3[3]+p4[3])/4))
        elif (y == Img.height): # Top Right
            p1 = Img.getpixel((x,y)); p2 = Img.getpixel((x-1,y)); p3 = Img.getpixel((x-1,y-1)); p4 = Img.getpixel((x,y-1))
            return (int((p1[0]+p2[0]+p3[0]+p4[0])/4), int((p1[1]+p2[1]+p3[1]+p4[1])/4), int((p1[2]+p2[2]+p3[2]+p4[2])/4), int((p1[3]+p2[3]+p3[3]+p4[3])/4))
        else:
            p1 = Img.getpixel((x,y)); p2 = Img.getpixel((x-1,y)); p3 = Img.getpixel((x-1,y+1)); p4 = Img.getpixel((x,y+1)); p5 = Img.getpixel((x,y-1)); p6 = Img.getpixel((x-1,y-1))
            return (int((p1[0]+p2[0]+p3[0]+p4[0]+p5[0]+p6[0])/6), int((p1[1]+p2[1]+p3[1]+p4[1]+p5[1]+p6[1])/6), int((p1[2]+p2[2]+p3[2]+p4[2]+p5[2]+p6[2])/6), int((p1[3]+p2[3]+p3[3]+p4[3]+p5[3]+p6[3])/6))
    else:
        p1 = Img.getpixel((x-1,y+1)); p2 = Img.getpixel((x,y+1)); p3 = Img.getpixel((x+1,y+1))
        p4 = Img.getpixel((x-1,y)); p5 = Img.getpixel((x,y)); p6 = Img.getpixel((x+1,y))
        p7 = Img.getpixel((x-1,y-1)); p8 = Img.getpixel((x,y-1)); p9 = Img.getpixel((x+1,y-1))
        A = (p1[0]+p2[0]+p3[0]+p4[0]+p5[0]+p6[0]+p7[0]+p8[0]+p9[0])/9
        R = (p1[1]+p2[1]+p3[1]+p4[1]+p5[1]+p6[1]+p7[1]+p8[1]+p9[1])/9
        G = (p1[2]+p2[2]+p3[2]+p4[2]+p5[2]+p6[2]+p7[2]+p8[2]+p9[2])/9
        B = (p1[3]+p2[3]+p3[3]+p4[3]+p5[3]+p6[3]+p7[3]+p8[3]+p9[3])/9
        return (int(A), int(R), int(G), int(B))

im = Image.open("MyImage.png")
im = ResizeImage(im, im.width, im.height, 224, 224, False) 
im.show()

我使用了 Pillow 库,因为它对于像这样的小任务非常有效,而 cv2 感觉就像用火箭筒射击鼠标。

编辑:如果您想锁定 x 和 y 的图像比率(比率 = SourceWidth/SourceHeight),您可以轻松地为此编辑代码,并可能对额外的像素使用零像素填充。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-17
    • 2023-01-09
    • 1970-01-01
    • 2012-10-19
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    相关资源
    最近更新 更多