简体   繁体   English

读取 Tensorflow 中的 32 位 TIFF 图像

[英]Reading a 32-bit TIFF image in Tensorflow

I need to use Tensorflow's.map() function to read in a 32-bit TIFF images (really DEM rasters).我需要使用 Tensorflow's.map() function 来读取 32 位 TIFF 图像(真正的 DEM 栅格)。 So far I've tried several approaches with no luck.到目前为止,我已经尝试了几种方法,但都没有运气。 The images are all in completely accessible folders that are readable and writeable by any and all users.图像都位于完全可访问的文件夹中,任何和所有用户都可以读取和写入。 Because we need to read in thousands of 32-bit TIFF rasters for training a TF model, the solution needs to be able to be mapped to all entries in a tf.data.Dataset.from_tensor_slices() object.因为我们需要读取数千个 32 位 TIFF 栅格来训练 TF model,所以解决方案需要能够映射到 tf.data.Dataset.from_tensor_slices() object 中的所有条目。

For testing purposes I am using a single band 32-bit floating point raster for a very small portion of the area we're actually interested in.出于测试目的,我对我们实际感兴趣的一小部分区域使用单波段 32 位浮点栅格。

img_path = 'depth.tif'

Attempt 1: Use tfio.experimental.image.decode_tiff()尝试 1:使用 tfio.experimental.image.decode_tiff()

Even when not using with TF Datatet objects this approach is failing.即使不与 TF Datatet 对象一起使用,这种方法也失败了。 Here is a very simple code that doesn't seem to work.这是一个非常简单的代码,似乎不起作用。

import tensorflow_io as tfio

img = tf.io.read_file(img_path)
img_decoded = tfio.experimental.image.decode_tiff(img, index=1)

But I keep receiving the following error:但我不断收到以下错误:

Traceback (most recent call last):
  File "C:\Users\Public\load_tif_dataset_from_dir.py", line 141, in <module>
    img_read = tfio.experimental.image.decode_tiff(img, index=0)
  File "C:\ProgramData\Anaconda3\envs\substrate\lib\site-packages\tensorflow_io\python\experimental\image_ops.py", line 87, in decode_tiff
    return core_ops.io_decode_tiff(contents, index, name=name)
  File "<string>", line 6306, in io_decode_tiff
  File "C:\ProgramData\Anaconda3\envs\substrate\lib\site-packages\tensorflow\python\framework\ops.py", line 7209, in raise_from_not_ok_status
    raise core._status_to_exception(e) from None  # pylint: disable=protected-access
tensorflow.python.framework.errors_impl.InvalidArgumentError: {{function_node __wrapped__IO>DecodeTiff_device_/job:localhost/replica:0/task:0/device:CPU:0}} unable to read directory: 0 [Op:IO>DecodeTiff]

This approach also fails whenever trying to read in TIFF images into TF Dataset objects.每当尝试将 TIFF 图像读入 TF 数据集对象时,这种方法也会失败。

Attempt 2: Use rasterio package with TF.map() function尝试 2:使用光栅 package 和 TF.map() function

I've used rasterio several times in the past to read and write 32-bit TIFF images without any issue, so I would assume this method should work.我过去曾多次使用 rasterio 来读取和写入 32 位 TIFF 图像而没有任何问题,所以我认为这种方法应该可以工作。 To begin I wrote a simple function to parse the images:首先,我编写了一个简单的 function 来解析图像:

import rasterio as rio
def parse_with_rasterio(image_path):
    img = rio.open(image_path)
    dat = img.read(1)
    return dat

This function works as expected when run stand-alone:此 function 在独立运行时按预期工作:

foo = parse_with_rasterio(img_path)
print(foo)
[[-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 ...
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]]

However, when attempting to use it within the.map() function of Tensorflow I receive the following error:但是,当尝试在 Tensorflow 的.map() function 中使用它时,我收到以下错误:

foo = tf.data.Dataset.from_tensor_slices([img_path])
foo_ds = foo.map(
    lambda x: tf.py_function(parse_with_rasterio, [x], Tout=tf.float32)
)
print(foo_ds.element_spec)
TensorSpec(shape=<unknown>, dtype=tf.float32, name=None)

Although I'm not getting any error with using rasterio, the Tensor shape is <unknown> which means I cannot use it as a model input (requires defined dimensions).虽然我在使用 rasterio 时没有遇到任何错误,但张量形状是<unknown> ,这意味着我不能将其用作 model 输入(需要定义尺寸)。

Attempt 3: Use skimage package with TF.map() function尝试 3:使用 skimage package 和 TF.map() function

Creating a parse function that uses skimage functions to parse the image, which can then be called by TF.map() function.创建使用 skimage 函数解析图像的解析 function,然后可以由 TF.map() function 调用。

from skimage import io as skio
def parse_with_skimage(image_path):
    skimage = skio.imread(image_path)
    return skimage

Again, this standalone function works as expected.同样,这个独立的 function 按预期工作。

[[-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 ...
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]]

But there is an issue when running it within the TF.map() function:但是在 TF.map() function 中运行它时会出现问题:

foo = tf.data.Dataset.from_tensor_slices([img_path])
foo_ds = foo.map(
    lambda x: tf.py_function(parse_with_skimage, [x], Tout=tf.float32)
)
print(foo_ds.element_spec)
TensorSpec(shape=<unknown>, dtype=tf.float32, name=None)

Attempt 4: Use cv2 (OpenCV) package with TF.map() function尝试 4:使用 cv2 (OpenCV) package 和 TF.map() function

Created another parse function, this time using cv2 (OpenCV) package to parse the image.创建了另一个解析 function,这次使用 cv2 (OpenCV) package 来解析图像。 This function should be callable by TF.map() function.这个 function 应该可以被 TF.map() function 调用。

def parse_with_opencv(image_path):
    img = cv2.imread(image_path, flags=cv2.IMREAD_ANYDEPTH)
    return img

This function works fine when run standalone.这个 function 在独立运行时工作正常。

img = cv2.imread(img_path, flags=cv2.IMREAD_ANYDEPTH)
print(img)
[[-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 ...
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]
 [-3.4e+38 -3.4e+38 -3.4e+38 ... -3.4e+38 -3.4e+38 -3.4e+38]]

However, similar to the other attempts, it fails to read the image in correctly when used in the TF.map() function.但是,与其他尝试类似,在 TF.map() function 中使用时无法正确读取图像。

ds = tf.data.Dataset.list_files([img_path])
img_ds = ds.map(
    lambda filename: tf.py_function(cv2.imread, [filename], Tout=tf.float32)
)
print(img_ds.element_spec)
TensorSpec(shape=<unknown>, dtype=tf.float32, name=None)

I'm using the following configuration:我正在使用以下配置:

Python version: 3.10.6 Python 版本:3.10.6

Tensorflow version: 2.10 Tensorflow 版本:2.10

As stated earlier, we need to be able to read a 32-bit floating point TIFF image into TF Dataset object for ML model training.如前所述,我们需要能够将 32 位浮点 TIFF 图像读入 TF 数据集 object 以进行 ML model 训练。 Unfortunately the data cannot be simplified to lower precision.不幸的是,无法将数据简化为较低的精度。 Does anybody have a solution to reading 32-bit TIFF images into TF Dataset objects?有人有将 32 位 TIFF 图像读入 TF Dataset 对象的解决方案吗?

It is simple, I guess you to map the path of the image divided as a matrix of values.这很简单,我猜你将 map 图像的路径划分为值矩阵。

import os
import tensorflow as tf
import tensorflow_text as tft

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
None
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
physical_devices = tf.config.experimental.list_physical_devices('GPU')
assert len(physical_devices) > 0, "Not enough GPU hardware devices available"
config = tf.config.experimental.set_memory_growth(physical_devices[0], True)
print(physical_devices)
print(config)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Variables
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
BATCH_SIZE = 1
IMG_SIZE = (32, 32)

PATH = 'F:\\datasets\\downloads\\cats_name'
train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')

train_dataset = tf.keras.utils.image_dataset_from_directory(train_dir,
                                                            shuffle=True,
                                                            batch_size=BATCH_SIZE,
                                                            image_size=IMG_SIZE)

class_names = train_dataset.class_names

print( 'class_names: ' + str( class_names ) )
print( train_dataset )
# <BatchDataset element_spec=(TensorSpec(shape=(None, 32, 32, 3), dtype=tf.float32, name=None), TensorSpec(shape=(None,), dtype=tf.int32, name=None))>

window_size = 6
for d in train_dataset:
    print(d[0])
    dataset = tf.data.Dataset.from_tensors( d[0] )
    dataset = dataset.map(lambda x: tft.sliding_window(x, width=window_size, axis=0)).flat_map(tf.data.Dataset.from_tensor_slices)

input('...')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM