首页 文章

Tensorflow - 有没有办法实现张量方式的图像剪切/旋转/平移?

提问于
浏览
4

我正在尝试进行不同类型的(图像)数据增强来训练我的神经网络 .

我知道tf.image提供了一些增强功能,但它们太简单了 - 例如,我只能将图像旋转90度,而不是任何程度 .

我也知道tf.keras.preprocessing.image提供随机旋转,随机剪切,随机移位和随机缩放 . 但是这些方法只能应用于numpy数组,而不是张量 .

我知道我可以先读取图像,使用tf.keras.preprocessing.image中的函数进行扩充,然后将这些扩充的numpy数组转换为张量 .

但是,我只是想知道是否有一种方法可以实现张量增强,因此我不需要打扰“图像文件 - >张量 - > numpy数组 - >张量”程序 .


Update for those who want to know how to apply your transform:

有关详细的源代码,您可能需要检查tf.contrib.image.transformtf.contrib.image.matrices_to_flat_transforms .

这是我的代码:

def transformImg(imgIn,forward_transform):
    t = tf.contrib.image.matrices_to_flat_transforms(tf.linalg.inv(forward_transform))
    # please notice that forward_transform must be a float matrix,
    # e.g. [[2.0,0,0],[0,1.0,0],[0,0,1]] will work
    # but [[2,0,0],[0,1,0],[0,0,1]] will not
    imgOut = tf.contrib.image.transform(imgIn, t, interpolation="BILINEAR",name=None)
    return imgOut

基本上,上面的代码正在做

enter image description here
imgIn 中的每个点(x,y) .

例如,与x轴平行的shear transform

enter image description here

因此,我们可以像这样实现剪切变换(使用上面定义的 transformImg() ):

def shear_transform_example(filename,shear_lambda):
    image_string = tf.read_file(filename)
    image_decoded = tf.image.decode_jpeg(image_string, channels=3)
    img = transformImg(image_decoded, [[1.0,shear_lambda,0],[0,1.0,0],[0,0,1.0]])
    return img
img = shear_transform_example("white_square.jpg",0.1)

原图:
enter image description here

改造后:
enter image description here

(请注意 img 是张量,不包括将张量转换为图像文件的代码 . )

P.S.

以上代码适用于tensorflow 1.10.1,可能不适用于将来的版本 .

说实话,我真的不知道他们为什么设计tf.contrib.image.transform,我们必须使用另一个函数(tf.linalg.inv)来获得我们想要的东西 . 我真的希望他们可以改变tf.contrib.image.transform在a more intuitive way中工作 .

2 回答

  • 2

    看看tf.contrib.image.transform . 它可以将一般投影变换应用于图像 .

    您还需要查看tf.contrib.image.matrices_to_flat_transforms将您的仿射矩阵转换为 tf.contrib.image.transform 接受的投影格式 .

  • 0

    我通常使用 tf.data.DatasetDataset.maptf.py_func . Dataset.prefetch 意味着您可能需要重新考虑多个GPU的操作,但以下在单GPU系统上适用于我 .

    为简单起见,我'll assume you have all your images on disk in separate files, though it can easily be adapted for zip archives or other formats like hdf5 (won' t工作 .tar 文件 - 不知道为什么,但我怀疑它无论如何都是个好主意 . )

    import tensorflow as tf
    from PIL import Image
    
    
    def map_tf(path_tensor, label_tensor):
        # path_tensor and label_tensor correspond to a single example
    
        def map_np(path_str):
            # path_str is just a normal string here
            image = np.array(Image.load(path_str), dtype=np.uint8)
            image = any_cv2_or_numpy_augmentations(image)
            return image,
    
        image, = tf.py_func(
            map_np, (path_tensor,), Tout=(tf.uint8,), stateful=False)
        # any tensorflow operations here.
        image = tf.cast(image, tf.float32) / 255
    
        image.set_shape((224, 224, 3))
        return image, label
    
    
    paths, labels = load_image_paths_and_labels()
    dataset = tf.data.Dataset.from_tensor_slices((paths, labels))
    if is_training:
        shuffle_buffer = len(paths)  # full shuffling - can be shorter
        dataset = dataset.shuffle(shuffle_buffer).repeat()
    dataset = dataset.map(map_tf_fn, num_parallel_calls=8)
    dataset = dataset.batch(batch_size)
    
    dataset = dataset.prefetch(1)
    # play with the following if you want - not finalized API, and only in
    # more recent version of tensorflow
    # dataset = dataset.apply(tf.contrib.data.prefetch_to_device('/gpu:0'))
    
    image_batch, label_batch = dataset.make_one_shot_iterator().get_next()
    

    您也可以在tensorflow中进行解码并直接在 py_func 中使用 any_cv2_or_numpy_augmentations (尽管您不会注意到性能差异 .

    检查this answer以获取更多选项 .

相关问题