使用数据框进行图像预处理

时间:2021-03-17 23:39:31

标签: python image-processing keras

我在一个 cvs 文件中有大约 1000 张图像。通过执行以下操作,我已经设法将这些图像放入我的 Python 程序中:

df = pd.read_csv("./Testes_small.csv")

# Creates the dataframe 
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):   # range de 0 a 31
    image = imgs[i]
    plt.imshow(image)
    plt.show()

所以现在我有了 train_generator 类型的 python.keras.preprocessing.image.DataframeIterator 变量,它的大小是 (32,224,224,3)。

在函数 ImageDataGenerator 中,我想使用自己的预处理函数来调整图像大小。我想这样做是因为我有一些矩形图像,在调整大小时会丢失其比例。

每个示例这些图像之前(上图)和之后(下图)调整大小:Before resizing enter image description here 很明显第二张图片变形了

我找到了这个函数(这是对前一个线程的回答):

def resize_image(self, image: Image, length: int) -> Image:
    """
    Resize an image to a square. Can make an image bigger to make it fit or smaller if it doesn't fit. It also crops
    part of the image.

    :param self:
    :param image: Image to resize.
    :param length: Width and height of the output image.
    :return: Return the resized image.
    """

    """
    Resizing strategy : 
     1) We resize the smallest side to the desired dimension (e.g. 1080)
     2) We crop the other side so as to make it fit with the same length as the smallest side (e.g. 1080)
    """
    if image.size[0] < image.size[1]:
        # The image is in portrait mode. Height is bigger than width.

        # This makes the width fit the LENGTH in pixels while conserving the ration.
        resized_image = image.resize((length, int(image.size[1] * (length / image.size[0]))))

        # Amount of pixel to lose in total on the height of the image.
        required_loss = (resized_image.size[1] - length)

        # Crop the height of the image so as to keep the center part.
        resized_image = resized_image.crop(
            box=(0, required_loss / 2, length, resized_image.size[1] - required_loss / 2))

        # We now have a length*length pixels image.
        return resized_image
    else:
        # This image is in landscape mode or already squared. The width is bigger than the heihgt.

        # This makes the height fit the LENGTH in pixels while conserving the ration.
        resized_image = image.resize((int(image.size[0] * (length / image.size[1])), length))

        # Amount of pixel to lose in total on the width of the image.
        required_loss = resized_image.size[0] - length

        # Crop the width of the image so as to keep 1080 pixels of the center part.
        resized_image = resized_image.crop(
            box=(required_loss / 2, 0, resized_image.size[0] - required_loss / 2, length))

        # We now have a length*length pixels image.
        return resized_image

我试图像这样插入它 img_datagen = ImageDataGenerator(rescale=1./255, preprocessing_function = resize_image 但它不起作用,因为我没有给出 im。你对我该怎么做有什么想法吗?

1 个答案:

答案 0 :(得分:0)

检查 documentation 以向 ImageDataGenerator 提供自定义函数。它说并引用,

"preprocessing_function: 将应用于每个输入的函数。该函数将在图像调整大小和增强后运行。该函数应采用一个参数:一个图像(Numpy 张量,等级为 3) , 并且应该输出一个形状相同的 Numpy 张量。"

从上述文档中我们可以注意到以下几点:

这个函数什么时候执行:

  • 调整图像大小后。
  • 在任何必须完成的数据增强之后。

函数参数要求:

  • 只有一个参数。
  • 此参数仅适用于一张 numpy 图像。
  • 图像应该是等级 3 的 numpy 张量

函数输出要求:

  • 一张输出图像。
  • 应该与输入的形状相同

最后一点对于您的问题非常重要。由于您的函数正在调整图像大小,因此输出的形状与输入的形状不同,因此您不能直接执行此操作。

完成此操作的另一种方法是在传递给 ImageDataGenerator 之前调整数据集的大小。