【问题标题】:Working with webp and jpeg images have different number of channels使用 webp 和 jpeg 图像具有不同数量的通道
【发布时间】:2021-08-07 14:25:32
【问题描述】:

我正在处理计算机视觉项目,我的图像是 webp 和 jpeg 的组合。我正在使用 tensorflow '2.3.2'
你可以这样想我的目录:

IMAGES
 |-img1.jpeg
 |-img2.webp

对于阅读 webp,我使用 tfio.image.decode_webp,在阅读 jpeg 时,我使用 tf.image.decode_jpeg(img, channels=3)。这是代码:

def load(file_path):
    img = tf.io.read_file(file_path)
    extension = tf.strings.split(file_path,sep=".")    
    if extension[-1] == "webp" :
        img = tfio.image.decode_webp(img)
    else :
        img = tf.image.decode_jpeg(img, channels=3)
    #img preprocess here
    return img

def create_dataset(df,batch_size):
    image = df["image_path"]
    # I'm working on MultiTaskLearning so I have multiple targets
    target1 = df["target1"].to_numpy()
    target2 = df["target2"].to_numpy()
    
    ds = tf.data.Dataset.from_tensor_slices((image,target1,target2))
    ds = ds.map(lambda image, target1,target2: (load(image),  {"target1":target1, "target2":target2}), num_parallel_calls=tf.data.experimental.AUTOTUNE)
    
    ds = ds.batch(batch_size)
    ds = ds.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
    return ds

dataset = create_dataset(df,100)

问题是,webp 被转换为 4 通道(RGBA)张量,其中解码 jpeg 位于 3 通道(RGB)中。这会在我的数据集中造成不一致,因为该模型仅包含 3 通道图像。

我能想到的一个解决方案是通过this 将我所有的 webp 转换为 jpeg。但是有没有更好的解决方案呢?比如在 TensorFlow 中将 4 通道转换为 3 通道,或者在 TensorFlow 中将 webp 读取为 3 通道,或者我可以将解决方案放入我的 python 脚本中的其他任何东西?

【问题讨论】:

  • 如果你想用jpegwebp 训练一个模型,那么你需要为两者创建相同的输入层布局。无需转换图像,只需在 load 之后转换 img 张量即​​可。已经有一个很好的答案解释了如何在 SO:stackoverflow.com/a/58748986/1622937 上对 numpy 数组进行 RGBA>RGB 转换(提示:img.numpy()
  • 感谢您的建议。您提出的解决方案似乎非常好。但是当我尝试应用它时,它会提高AttributeError: 'Tensor' object has no attribute 'numpy'。我认为这与 tensorflow 急切执行无法正常工作有关。即使没有 numpy,在图像解码步骤后打印 tensor.shape (None,None,None)
  • 我已经用我使用的更多代码更新了问题
  • 您可以使用tfio.experimental.color.rgba_to_rgb。它应该在图形模式下工作。您应该注意,此方法仅获取 RGBA 图像的 RGB 部分。如果您的图像没有透明度,那就足够了。
  • @Lescurel 将其调整为从 rgba 到 rgb 的正确转换应该相当简单。我去试试……

标签: python tensorflow


【解决方案1】:

如果您想用 *.jpeg*.webp 图像训练单个模型,那么您应该为两者创建相同的输入层布局。

为此,您基本上需要将 RGB 转换为 RGBA 或(我会做的)RGBA 到 RGB。如果您想简单地删除 alpha 通道,您可以使用 tensorflow 的 rgba_to_rgb(如 @Lescurel pointed out in the comments)。

但是alpha compositing 的 RBGA 到 RGB 转换不是很复杂,你可以直接在调用load 得到的张量上进行操作。

这是针对this SO 问题提出的numpy implementation 的张量流改编:

def rgba2rgb(rgba, background=(255,255,255)):
    row, col, ch = tf.shape(rgba)
    if ch == 3:
        return rgba
    assert ch == 4, 'RGBA image has 4 channels.'
    r, g, b, a = tf.unstack(tf.cast(rgba, tf.float32), axis=-1)
    a =  tf.cast(a, tf.float32) / 255.0
    R, G, B = background
    r = r * a + (1.0 - a) * R
    g = g * a + (1.0 - a) * G
    b = b * a + (1.0 - a) * B
    rgb = tf.stack([r,g,b], axis=-1)
    return tf.cast(rgb, tf.uint8)

使用它可以避免在张量上调用 .numpy()potential issues related to that

所以基本上rgba2rgb(load(image)) 应该可以解决问题。

【讨论】:

  • 谢谢,当我在没有数据集类的情况下一次性读取所有图像时,此解决方案有效。但是当我将它应用到 create_dataset 这样的函数时:ds = ds.map(lambda image, target1,target2: (rgba2rgb(load(image)), {"target1":target1, "target2":target2}),num_parallel_calls=tf.data.experimental.AUTOTUNE)。当我从我的模型调用预测函数时,它会引发AssertionError: RGBA image has 4 channels.(创建数据集时没有错误)。断言前print(ch)None
  • hmm,此问题与 RBGA>RGB 转换无关。要确认这一点,只需在 load 函数中的 return 语句之前添加一个 print(img)。我的猜测是它会打印出类似(None, None, None) 的东西。我不在安装了 tf 的系统上,所以我只是在这里猜测,但问题可能出在:ds = tf.data.Dataset.from_tensor_slices((image,target1,target2))
  • print(img) show Tensor("resize/Squeeze:0", shape=(224, 224, None), dtype=float32) 可能 ch 是 None 因为它可以是 3 或 4。但奇怪的是,即使我将 rgba2rgb 放在 @ 内,它仍然会引发相同的错误987654343@函数。
  • 我明白了。我已经更新了我的答案(注意装饰器@tf.function),以便将 rgba2rbg 转换为可调用的 tf 图并在运行时访问形状(tf.shape(..
  • 我使用你的新 rgba2rgb 并将 @tf.function 放在上面,它会引发此错误 OperatorNotAllowedInGraphError: iterating over 'tf.Tensor' is not allowed: AutoGraph did convert this function. This might indicate you are trying to use an unsupported feature.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-15
  • 2019-07-20
  • 1970-01-01
  • 2021-03-22
  • 2021-04-05
  • 2018-08-12
相关资源
最近更新 更多