将两个立体图像传递给 Keras 中的损失函数的最干净、最有效的方法是什么?

What's the cleanest and most efficient way to pass two stereo images to a loss function in Keras?

首先,我为什么要使用 Keras?我尽量保持高水平,这并不意味着我害怕低水平的 TensorFlow;我只是想看看在保持代码尽可能简单易读的同时我能走多远。

我需要我的 Keras 模型(使用 Keras 函数 API 自定义构建)从立体对中读取左图像并最小化需要访问右图像和左图像的损失函数。我想将数据存储在 tf.data.Dataset.

我尝试了什么:

  1. 将数据集读取为 (left image, right image),即形状为 ((W, H, 3), (W, H, 3)) 的张量,然后使用函数闭包:定义一个 keras_loss(left_images) 即 returns 一个 loss(y_true, y_pred) ,其中 y_true 是一个 tf.Tensor,它包含正确的图像。这种方法的问题是 left_imagestf.data.Dataset 并且 Tensorflow 抱怨(这是正确的)我正在尝试对数据集而不是张量进行操作。
  2. 将数据集读取为 (left image, (left image, right image)),这应该使 y_true 成为具有形状 ((W, H, 3), (W, H, 3))tf.Tensor,同时包含右图像和左图像。这种方法的问题是它......不起作用并引发以下错误:

    ValueError: Error when checking model target: the list of Numpy arrays 
    that you are passing to your model is not the size the model expected. 
    Expected to see 1 array(s), for inputs ['tf_op_layer_resize/ResizeBilinear'] 
    but instead got the following list of 2 arrays: [<tf.Tensor 'args_1:0' 
    shape=(None, 512, 256, 3) dtype=float32>, <tf.Tensor 'args_2:0' 
    shape=(None, 512, 256, 3) dtype=float32>]...
    

所以,有什么我没有考虑到的吗?我阅读了文档,没有发现什么被视为 y_pred 和什么被视为 y_true,也没有发现如何巧妙地将数据集转换为张量而不将其全部加载到内存中。

我的模型是这样设计的:

 def my_model(input_shape):
     width = input_shape[0]
     height = input_shape[1]
     inputs = tf.keras.Input(shape=input_shape)
     # < a few more layers >
     outputs = tf.image.resize(tf.nn.sigmoid(tf.slice(disp6, [0, 0, 0, 0], [-1, -1, -1, 2])), tf.Variable([width, height]))
     model = tf.keras.Model(inputs=inputs, outputs=outputs)
     return model

我的数据集是这样构建的(在案例 2 中,而在案例 1 中只有函数 read_stereo_pair_from_line() 发生了变化):

def read_img_from_file(file_name):
    img = tf.io.read_file(file_name)
    # convert the compressed string to a 3D uint8 tensor
    img = tf.image.decode_png(img, channels=3)
    # Use `convert_image_dtype` to convert to floats in the [0,1] range.
    img = tf.image.convert_image_dtype(img, tf.float32)
    # resize the image to the desired size.
    return tf.image.resize(img, [args.input_width, args.input_height])


def read_stereo_pair_from_line(line):
    split_line = tf.strings.split(line, ' ')
    return read_img_from_file(split_line[0]), (read_img_from_file(split_line[0]), read_img_from_file(split_line[1]))

# Dataset loading
list_ds = tf.data.TextLineDataset('test/files.txt')
images_ds = list_ds.map(lambda x: read_stereo_pair_from_line(x))
images_ds = images_ds.batch(1)

已解决。我只需要将数据集读取为 (left image, [left image, right image]) 而不是 (left image, (left image, right image)) 即使第二项成为列表而不是元组。然后我可以访问图像 input_r = y_true[:, 1, :, :]input_l = y_true[:, 0, :, :]