Tensorflow 的 Tiff 解决方法

Tiff workaround for Tensorflow

我需要构建一个数据加载器来训练 CNN 使用 tensorflow 进行语义分割。图像是 3 通道 tiff 训练图像和 1 通道(灰度)tiff 掩码。

到目前为止,我关注了 this example。他们写了一个函数

def parse_image(img_path: str) -> dict:
    image = tf.io.read_file(img_path)
    image = tf.image.decode_jpeg(image, channels=3)
    image = tf.image.convert_image_dtype(image, tf.uint8)
    mask_path = tf.strings.regex_replace(img_path, "images", "annotations")
    mask_path = tf.strings.regex_replace(mask_path, "jpg", "png")
    mask = tf.io.read_file(mask_path)
    mask = tf.image.decode_png(mask, channels=1)
    mask = tf.where(mask == 255, np.dtype('uint8').type(0), mask)

    return {'image': image, 'segmentation_mask': mask}

适用于 jpeg 和 png 图像。但是,对于 tiff,必须使用 tfio.experimental.image.decode_tiff(image),这是非常有限的,在我的情况下不起作用。它吐出很多错误,例如

TIFFReadDirectory: Warning, Unknown field with tag 42112 (0xa480) encountered.

中所述,我可以使用 cv2PIL 等包。

我尝试实现如下:

import cv2
def parse_image(img_path: str) -> dict:
    # read image
    image = cv2.imread(img_path)
    image = tf.convert_to_tensor(image, tf.uint8)
    # read mask
    mask_path = tf.strings.regex_replace(img_path, "X", "y")
    mask_path = tf.strings.regex_replace(mask_path, "X.tif", "y.tif")
    mask = cv2.imread(mask_path)
    mask = tf.convert_to_tensor(mask, tf.uint8)
    return {"image": image, "segmentation_mask": mask}

然而,这只会导致

TypeError: in user code:

    <ipython-input-46-41b06b3732aa>:6 parse_image  *
        image = cv2.imread(img_path)

    TypeError: Can't convert object of type 'Tensor' to 'str' for 'filename'

我想在这个函数中使用非tensorflow函数会出现更多问题

因为我看过一些关于 tensorflow 和 tiff 的类似问题的旧帖子,我想知道在此期间是否有解决方法?例如,一些与 tensorflow 的其余部分兼容并可以读取 tiff 数据的自定义函数?

如果您仍然愿意使用 opencv,那么您可以将阅读功能包装在 tf.numpy_function 中。在包裹在 tf.numpy_function 中的函数范围内,您处理 numpy 数组,因此在调用 cv2.imread.[=21= 之前需要将 numpy 字节串表示转换为常规 python 字符串]

import tensorflow as tf
import cv2

def parse_with_opencv(image_path):
    return cv2.imread(image_path.decode('UTF-8'))

img_path = ["/path/to/image.tif"]

ds = tf.data.Dataset.from_tensor_slices(img_path).map(
    lambda x: tf.numpy_function(parse_with_opencv, [x], Tout=tf.uint8)
) 

处理 tf.numpy_function 有时会有点令人沮丧,因为错误消息可能有些晦涩难懂。


另一种选择是使用 decode_tiff function from the tfio module。它与 TensorFlow 操作兼容。当然它有局限性。

一个例子:

import tensorflow as tf
import tensorflow_io as tfio

def parse_image(image_path):
    filecontent = tf.io.read_file(image_path)
    img = tfio.experimental.image.decode_tiff(filecontent)
    return img

img_path = ["/path/to/image.tif"]

ds = tf.data.Dataset.from_tensor_slices(img_path).map(parse_image)