【问题标题】:Tiff workaround for TensorflowTensorflow 的 Tiff 解决方法
【发布时间】:2021-06-30 23:45:31
【问题描述】:

我需要构建一个数据加载器来训练 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.

this answer 中所述,我可以使用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 和 tiff 类似问题的旧帖子,我想知道在此期间是否有解决方法?例如,一些与 tensorflow 的其余部分兼容并且可以读取 tiff 数据的自定义函数?

【问题讨论】:

  • 你传递给 parse_image 的具体内容是什么?它应该是一个字符串,而你以某种方式传递了一个张量流张量,那是你的问题。
  • @Dr.Snoopy 用作train_dataset = tf.data.Dataset.list_files( "/some/path" + "/*.tif", seed = 12) train_dataset = train_dataset.map(parse_image) 所以,是的,传递了一个张量。不过,我不知道如何使它成为一个字符串。另外,我认为理想的解决方案是拥有更复杂的.image.decode_tiff 函数。如果那不可能,我将不得不找出如何使张量成为字符串。例如,This 不起作用...

标签: python tensorflow tiff


【解决方案1】:

如果您仍然愿意改用opencv,那么您可以将阅读功能包装在tf.numpy_function 中。在 tf.numpy_function 中包裹的函数范围内,您处理的是 numpy 数组,因此在调用 cv2.imread 之前需要将 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 有时有点令人沮丧,因为错误消息可能有点神秘。


另一种选择是使用tfio module 中的decode_tiff 函数。它与 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) 

【讨论】:

  • 我尝试使用tfio.experimental.image.decode_tiff,但我遇到了一些问题,因为我的图像直接来自osgeo.gdal,而TIFFReadDirectory 不知道一些标签(请参阅我的问题,我有数百个错误和警告因为那些标签)。不过,我认为如果您有“常规”TIFF,这将是最好的解决方案。无论如何,我在此期间切换到 PNG,这让一切变得更容易。不过感谢您的帮助!
  • 我读你的问题有点太快了,所以我也添加了opencv 方法。
猜你喜欢
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多