Tensorflow: Filter中的3D张量(图像的)形状有None。

huangapple go评论66阅读模式
英文:

Tensorflow: Shape of 3D tensor (of an image) in Filter has None

问题

以下是您要翻译的部分:

I am following [this tutorial][1] on [tensorflow.org][2].

I have folder images with two folders cat and dog in it. Following above tutorial I am trying to convert .jpg and ..png images to features (NumPy array) for modeling.

Problem

After processing the images to tensors I found that some images were converted to tensor with shape (28, 28, 4). So I added condition to filter out such tensors. This logic works while explicitly looping each tensor, using for loop, after converting it to numpy array, but same logic does not work when used with filter.

Please help me fix this filter() I went through [filter()][3] documentation and could not find any solution.

Source code

import tensorflow as tf
import os

print("TensorFlow version:", tf.__version__)

def process_image(file_path_tensor):
    parts = tf.strings.split(file_path_tensor, os.sep)
    label = parts[-2]

    image = tf.io.read_file(file_path_tensor)
    image = tf.image.decode_jpeg(image)
    image = tf.image.resize(image, [128, 128])
    image = tf.image.convert_image_dtype(image, tf.float32)
    image = image / 255

    return image, label


def check_shape(x, y):
    print("\nShape received in filter():", x.shape)
    d1, d2, d3 = x.shape
    return d3 == 3


images_ds = tf.data.Dataset.list_files("./images/*/*", shuffle=True)

file_path = next(iter(images_ds))
image, label = process_image(file_path)

print("Shape:", image.shape)
print("Class label:", label.numpy().decode())

# ETL pipeline.
X_y_tensors = (
    images_ds
    .map(process_image)   # Extra and Transform
    .filter(check_shape)  # Filter
    .as_numpy_iterator()  # Load
)

print("\nTechnique 1:")
print("Final X count:", len(list(X_y_tensors)))


X_y_tensors = images_ds.map(process_image)

count = 0
for x, y in X_y_tensors:
    d1, d2, d3 = x.shape
    if d3 > 3:
        continue
    count += 1

print("\nTechnique 2:")
print("Final X count:", count)

Output

TensorFlow version: 2.6.0
Shape: (128, 128, 3)
Class label: cat

Shape received in filter(): (128, 128, None)

Technique 1:
Final X count: 0

Technique 2:
Final X count: 123
```

As it can be seen,

1. Count is 0 when _Technique 1_ is used to filter tensors, since the shape of the tensor received is `(128, 128, None)`.
1. Count is 123 (image count after filtering) when _Technique 2_ is used.

I do not think [this][5] is an issue since I am **not using batches**.

[Full code with dataset][4]

[1]: https://www.tensorflow.org/guide/data#preprocessing_data
[2]: https://www.tensorflow.org/
[3]: https://www.tensorflow.org/api_docs/python/tf/data/Dataset#filter
[4]: https://github.com/DheemanthBhat/tensorflow-image-pipeline
[5]: https://stackoverflow.com/questions/58331837/filter-data-in-tensorflow

<details>
<summary>英文:</summary>

I am following [this tutorial][1] on [tensorflow.org][2].

I have folder _images_ with two folders _cat_ and _dog_ in it. Following above tutorial I am trying to convert .jpg and .png images to features (NumPy array) for modeling.  

### Problem

After processing the images to tensors I found that some images were converted to tensor with shape `(28, 28, 4)`. So I added condition to filter out such tensors. This logic works while explicitly looping each tensor, using `for` loop, after converting it to numpy array, but same logic does not work when used with `filter`.

Please help me fix this `filter()` I went through [`filter()`][3] documentation and could not find any solution.

### Source code

```python
import tensorflow as tf
import os

print(&quot;TensorFlow version:&quot;, tf.__version__)

def process_image(file_path_tensor):
    parts = tf.strings.split(file_path_tensor, os.sep)
    label = parts[-2]

    image = tf.io.read_file(file_path_tensor)
    image = tf.image.decode_jpeg(image)
    image = tf.image.resize(image, [128, 128])
    image = tf.image.convert_image_dtype(image, tf.float32)
    image = image / 255

    return image, label


def check_shape(x, y):
    print(&quot;\nShape received in filter():&quot;, x.shape)
    d1, d2, d3 = x.shape
    return d3 == 3


images_ds = tf.data.Dataset.list_files(&quot;./images/*/*&quot;, shuffle=True)

file_path = next(iter(images_ds))
image, label = process_image(file_path)

print(&quot;Shape:&quot;, image.shape)
print(&quot;Class label:&quot;, label.numpy().decode())

# ETL pipeline.
X_y_tensors = (
    images_ds
    .map(process_image)   # Extra and Transform
    .filter(check_shape)  # Filter
    .as_numpy_iterator()  # Load
)

print(&quot;\nTechnique 1:&quot;)
print(&quot;Final X count:&quot;, len(list(X_y_tensors)))


X_y_tensors = images_ds.map(process_image)

count = 0
for x, y in X_y_tensors:
    d1, d2, d3 = x.shape
    if d3 &gt; 3:
        continue
    count += 1

print(&quot;\nTechnique 2:&quot;)
print(&quot;Final X count:&quot;, count)
```

### Output
```
TensorFlow version: 2.6.0
Shape: (128, 128, 3)
Class label: cat

Shape received in filter(): (128, 128, None)

Technique 1:
Final X count: 0

Technique 2:
Final X count: 123
```

As it can be seen,

1. Count is 0 when _Technique 1_ is used to filter tensors, since the shape of the tensor received is `(128, 128, None)`.
1. Count is 123 (image count after filtering) when _Technique 2_ is used.

I do not think [this][5] is an issue since I am **not using batches**.

[Full code with dataset][4]

[1]: https://www.tensorflow.org/guide/data#preprocessing_data
[2]: https://www.tensorflow.org/
[3]: https://www.tensorflow.org/api_docs/python/tf/data/Dataset#filter
[4]: https://github.com/DheemanthBhat/tensorflow-image-pipeline
[5]: https://stackoverflow.com/questions/58331837/filter-data-in-tensorflow

</details>


# 答案1
**得分**: 0

问题与`filter()`无关,而是由`decode_jpeg()`引起的。将`tf.io.decode_jpeg()`的[`channels`][1]参数设置为3。

数字3表示图像的RGB颜色通道。

解决方案

```python
import tensorflow as tf
import os

print("TensorFlow版本:", tf.__version__)

def process_image(file_path_tensor):
    parts = tf.strings.split(file_path_tensor, os.sep)
    label = parts[-2]

    image = tf.io.read_file(file_path_tensor)
    image = tf.image.decode_jpeg(image, channels=3)
    image = tf.image.resize(image, [128, 128])
    image = tf.image.convert_image_dtype(image, tf.float32)
    image = image / 255

    return image, label


def check_shape(x, y):
    print("\n在filter()中接收到的形状:", x.shape)
    d1, d2, d3 = x.shape
    return d3 == 3


images_ds = tf.data.Dataset.list_files("./images/*/*", shuffle=True)

file_path = next(iter(images_ds))
image, label = process_image(file_path)

print("形状:", image.shape)
print("类别标签:", label.numpy().decode())

# ETL流水线。
X_y_tensors = (
    images_ds
    .map(process_image)   # 提取和转换
    .filter(check_shape)  # 过滤
    .as_numpy_iterator()  # 载入
)

print("\n技巧 1:")
print("最终 X 计数:", len(list(X_y_tensors)))


X_y_tensors = images_ds.map(process_image)

count = 0
for x, y in X_y_tensors:
    d1, d2, d3 = x.shape
    if d3 > 3:
        continue
    count += 1

print("\n技巧 2:")
print("最终 X 计数:", count)
```

输出

```python
TensorFlow版本: 2.6.0
形状: (128, 128, 3)
类别标签: 猫

在filter()中接收到的形状: (128, 128, 3)

技巧 1:
最终 X 计数: 129

技巧 2:
最终 X 计数: 129
```

[1]: https://www.tensorflow.org/api_docs/python/tf/io/decode_jpeg#args


<details>
<summary>英文:</summary>

Okay. So the problem is not related to `filter()` its caused by `decode_jpeg()`. Set [`channels`][1] parameter of `tf.io.decode_jpeg()` to value 3. 

Three indicates RGB color channels of an image.

### Solution

```python
import tensorflow as tf
import os

print(&quot;TensorFlow version:&quot;, tf.__version__)

def process_image(file_path_tensor):
    parts = tf.strings.split(file_path_tensor, os.sep)
    label = parts[-2]

    image = tf.io.read_file(file_path_tensor)
    image = tf.image.decode_jpeg(image, channels=3)
    image = tf.image.resize(image, [128, 128])
    image = tf.image.convert_image_dtype(image, tf.float32)
    image = image / 255

    return image, label


def check_shape(x, y):
    print(&quot;\nShape received in filter():&quot;, x.shape)
    d1, d2, d3 = x.shape
    return d3 == 3


images_ds = tf.data.Dataset.list_files(&quot;./images/*/*&quot;, shuffle=True)

file_path = next(iter(images_ds))
image, label = process_image(file_path)

print(&quot;Shape:&quot;, image.shape)
print(&quot;Class label:&quot;, label.numpy().decode())

# ETL pipeline.
X_y_tensors = (
    images_ds
    .map(process_image)   # Extra and Transform
    .filter(check_shape)  # Filter
    .as_numpy_iterator()  # Load
)

print(&quot;\nTechnique 1:&quot;)
print(&quot;Final X count:&quot;, len(list(X_y_tensors)))


X_y_tensors = images_ds.map(process_image)

count = 0
for x, y in X_y_tensors:
    d1, d2, d3 = x.shape
    if d3 &gt; 3:
        continue
    count += 1

print(&quot;\nTechnique 2:&quot;)
print(&quot;Final X count:&quot;, count)
```

Output

```
TensorFlow version: 2.6.0
Shape: (128, 128, 3)
Class label: cat

Shape received in filter(): (128, 128, 3)

Technique 1:
Final X count: 129

Technique 2:
Final X count: 129
```

[1]: https://www.tensorflow.org/api_docs/python/tf/io/decode_jpeg#args

</details>



huangapple
  • 本文由 发表于 2023年2月18日 22:03:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75493853.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定