如何自定义ImageDataGenerator以修改目标变量值?
我有一个图像数据集,并带有表示面部关键点的坐标.因为我想扩充数据集,所以我正在寻找一种实现ImageDataGenerator的方法,以根据图像变换来修改目标变量(例如,如果图像水平翻转,则x坐标应设置为image_width-x或如果要填充图像,则x坐标应设置为x-填充.
I have a dataset of images annotated with coordinates representing facial keypoints. As I would like to augment the dataset, I am looking for a way to implement the ImageDataGenerator to modify the target variables according to image transformation (for example, if the image is flipped horizontally, the x coordinates should be set to image_width - x or if the image is padded, the x coordinates should be set to x - padding.
对于任何可以说明任何类似示例的建议或资源,我将不胜感激.
I would be thankful for any suggestion or resource that might illustrate any similar example.
谢谢
Niko
最简单,最明显的方法是修改Keras代码(您可以找到此处).但是,尽管没有很好的记录,Keras确实提供了一个优雅的API 来处理此问题.
The easiest and most obvious way is to modify the Keras code (you can find full implementation of ImageDataGenerator
in here). However, Keras does provide an elegant API to deal with this, although it is not very well documented.
我们需要编写一个新的Keras生成器,该生成器继承自 Iterator
类. Iterator
类本身只是来自 Sequence
的便捷子类,有关详细教程,请参见这里.
We would need to write a new Keras generator, inheriting from Iterator
class. The Iterator
class itself is just a convenient child class from Sequence
, a detailed tutorial of which can be found here.
from keras.preprocessing.image import Iterator, ImageDataGenerator
class MyIterator(Iterator):
"""This is a toy example of a wrapper around ImageDataGenerator"""
def __init__(self, n, batch_size, shuffle, seed, **kwargs):
super().__init__(n, batch_size, shuffle, seed)
# Load any data you need here (CSV, HDF5, raw stuffs). The code
# below is just a pseudo-code for demonstration purpose.
input_images = ...
ground_truth = ...
# Here is our beloved image augmentator <3
self.generator = ImageDataGenerator(**kwargs)
def _get_batches_of_transformed_samples(self, index_array):
"""Gets a batch of transformed samples from array of indices"""
# Get a batch of image data
batch_x = input_images[index_array].copy()
batch_y = ground_truth[index_array].copy()
# Transform the inputs and correct the outputs accordingly
for i, (x, y) in enumerate(zip(batch_x, batch_y)):
transform_params = self.generator.get_random_transform(x.shape)
batch_x[i] = self.generator.apply_transform(x, transform_params)
batch_y[i] = process_outputs_accordingly(y, transform_params)
return batch_x, batch_y
为什么我们要从Keras迭代器继承?
建议让您的生成器继承自 keras.utils.Sequence
(也是其他类的基类).它允许在多个线程之间并行加载数据.
Why we inherit from Keras Iterator?
It is recommended to have your generators inherited from keras.utils.Sequence
(also the base class of other classes). It allows the data be loaded in parallel between several threads.
您可以使用方法flow
,flow_from_directory
和flow_from_dataframe
编写自定义生成器-Keras API的核心功能.
You can write a custom generator with methods flow
, flow_from_directory
, and flow_from_dataframe
--- core functions of Keras API.