在 Tensorflow 中检测损坏的图像

Jos*_*osh 6 python tensorflow

我无法在数据集中找到一些有问题的图像。

我的模型开始训练,但出现以下错误:

tensorflow.python.framework.errors_impl.InvalidArgumentError: Invalid PNG data, size 135347
         [[{{node case/cond/cond_jpeg/decode_image/cond_jpeg/cond_png/DecodePng}} = DecodePng[channels=3, dtype=DT_UINT8, _device="/device:CPU:0"](case/cond/cond_jpeg/decode_image/cond_jpeg/cond_png/cond_gif/DecodeGif/Switch:1, ^case/Assert/AssertGuard/Merge)]]
         [[node IteratorGetNext (defined at object_detection/model_main.py:105)  = IteratorGetNext[output_shapes=[[24], [24,300,300,3], [24,2], [24,3], [24,100], [24,100,4], [24,100,2], [24,100,2], [24,100], [24,100], [24,100], [24]], output_types=[DT_INT32, DT_FLOAT, DT_INT32, DT_INT32, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_INT32, DT_BOOL, DT_FLOAT, DT_INT32], _device="/job:localhost/replica:0/task:0/device:CPU:0"](IteratorV2)]]
Run Code Online (Sandbox Code Playgroud)

因此,我编写了一个小脚本,在生成 TFRecords 之前运行该脚本以尝试捕获任何有问题的图像。这基本上是教程代码,但批量大小为 1。这是我能想到的尝试捕获错误的最简单方法。

def preprocess_image(image):
    image = tf.image.decode_png(image, channels=3)
    image = tf.image.resize_images(image, [192, 192])
    image /= 255.0  # normalize to [0,1] range

    return image

def load_and_preprocess_image(path):
    image = tf.read_file(path)
    return preprocess_image(image)

mobile_net = tf.keras.applications.MobileNetV2(input_shape=(192, 192, 3), include_top=False)
mobile_net.trainable=False

path_ds = tf.data.Dataset.from_tensor_slices(images)

image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=4)

def change_range(image):
    return (2*image-1)

keras_ds = image_ds.map(change_range)
keras_ds = keras_ds.batch(1)

for i, batch in tqdm(enumerate(iter(keras_ds))):
    try:
        feature_map_batch = mobile_net(batch)
    except KeyboardInterrupt:
        break
    except:
        print(images[i])
Run Code Online (Sandbox Code Playgroud)

这正式崩溃,但没有正确处理异常。它只是抛出异常并崩溃。所以两个问题:

我已经隔离了一个失败的图像,但是 OpenCV、SciPy、Matplotlib 和 Skimage 都打开了它。例如,我试过这个:

import scipy
images = images[1258:]
print(scipy.misc.imread(images[0]))

import matplotlib.pyplot as plt
print(plt.imread(images[0]))

import cv2
print(cv2.imread(images[0]))

import skimage
print(skimage.io.imread(images[0]))

... try to run inference in Tensorflow
Run Code Online (Sandbox Code Playgroud)

我打印出四个矩阵。我假设这些库都使用 libpng 或类似的东西。

然后图像 1258 使 Tensorflow 崩溃。查看 DecodePng,看起来它实际上是在崩溃 TF png

我意识到我可能可以编写自己的数据加载器,但这似乎是废话。

编辑:

这也可以作为一个片段:

tf.enable_eager_execution()

for i, image in enumerate(images):
    try:
        with tf.gfile.GFile(image, 'rb') as fid:
            image_data = fid.read()

        image_tensor = tf.image.decode_png(
                        image_data,
                        channels=3,
                        name=None
                    )
    except:
        print("Failed: ", i, image_tensor)
Run Code Online (Sandbox Code Playgroud)

Meh*_*tün 5

打开一个新的 python 文件。复制下面的代码。指定你的图片所在的目录。并运行代码。Corrupt JPEG data: premature end of data segment您可以在列表中看到消息(如果您有损坏的文件)。

from os import listdir
import cv2

#for filename in listdir('C:/tensorflow/models/research/object_detection/images/train'):
for filename in listdir(yourDirectory):
  if filename.endswith(".jpg"):
    print(yourDirectory+filename)
    #cv2.imread('C:/tensorflow/models/research/object_detection/images/train/'+filename)
    cv2.imread(yourDirectory+filename)
Run Code Online (Sandbox Code Playgroud)

您可以在列表中找到损坏的文件


Jos*_*osh 4

对这个问题的一个相当晚且出乎意料的自我回答。

事实证明,问题(很可能)是 RAM 损坏造成的。在 Linux 中发生了一些奇怪的事情(例如文件系统变为只读以及 Firefox 中的随机选项卡崩溃)后,我决定运行 Memtest。我安装了 2x8GB DIMM。事实证明,在 4GB 标记附近(两根内存条上)都有一个坏块,这意味着只有 (a) 当系统负载相当高时和 (b) 如果超过 8GB 利用率左右时,才会弹出错误。我还检查了硬盘是否损坏等问题,但它是一个相当新的 SSD。我之前曾在使用相同系统的 Windows 上进行过非常零星和随机的重启,但我再次认为这只是 Microsoft 强制更新。

所以我把这个贴在这里供后代使用。如果您看到奇怪的事情,例如图像以不可重复的方式损坏,则需要花费几分钟来运行 Memtest 作为健全性检查。严重的错误应该会在 30 秒内弹出,值得运行一整夜(多次)来仔细检查。

上面发布的解决方案仍然有用,我仍然不相信 TF 推出自己的 PNG 加载器,但始终值得检查您的硬件!

  • 请注意,这不是一个解决方案,而是一个特殊情况。 (2认同)