在Tensorflow中检测损坏的图像

9
我是一名有用的助手,可以为您进行文本翻译。以下是您需要翻译的内容:

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

我的模型开始训练,但我遇到了以下错误:

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)]]

我写了一个小脚本,在生成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])

这个程序会崩溃,但异常没有被正确处理。它只是抛出异常并崩溃。所以有两个问题: 我已经分离出一个失败的图像,但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

我打印出了四个矩阵。我认为这些库都使用了libpng或类似的东西。
当处理第1258张图片时,Tensorflow崩溃了。查看DecodePng source,看起来实际上是TF png library导致了崩溃。
我意识到我可能可以编写自己的数据加载器,但那似乎有点麻烦。
编辑:
这也可以作为片段工作:
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)

你尝试过使用decode_raw而不是decode_png吗? - Sharky
这可以用来加载文件,但是它加载的不是图像,而是将原始字节作为1D张量加载。 - Josh
img = tf.decode_raw('image_raw', tf.uint8) img = tf.reshape(img, img_shape) 这样行吗? - Sharky
不行,因为PNG图像是压缩的(而且还有一个头部)。数组的形状每次都会改变 - 并且在加载图像之前无法确定img_shape - Josh
我非常确定这应该可以工作,特别是在将图像形状转换为记录时显式存储。 example_features = {'height': tf.FixedLenFeature((), tf.int64) 此外,我想你可以尝试使用 tf.Assert 来捕获异常。 - Sharky
我认为 decode_png 在某个时候仍然会被调用,到那时一切都会崩溃。不过,我找到了一些示例代码,可以快速确定 TFRecord 是否损坏,这是一个很好的转换后检查。 - Josh
2个回答

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)

You can find the corrupt file in the list


4
这个问题最终发现是(很可能)由于坏的内存条引起的。在Linux中出现了一些奇怪的事情,比如文件系统变为只读状态和Firefox的随机崩溃。我决定运行Memtest。我安装了2x8GB的内存条。结果发现,在大约8GB的利用率下,仅当系统负载较高时才会出现错误,并且两根内存条都在大约4GB的位置附近有一个坏块。我还检查了诸如坏硬盘之类的问题,但它是一款相当新的SSD。我以前在使用同样的系统时经常遇到非常零散和随机的Windows重启,但我认为这只是微软强制更新而已。

因此,我在此发布此问题供后人参考。如果您看到一些奇怪的事情,比如图像以不可重复的方式损坏,请花几分钟运行Memtest作为实用性检查。严重错误应该会在30秒内出现,值得在过夜期间运行(多次通过),以进行双重检查。

以上发布的解决方案仍然有用,我仍然不确定TF是否应该自己滚动PNG加载程序,但检查您的硬件始终是值得的!


谢谢。我也遇到了这个问题,在训练过程中图像损坏了。但是如果我之后搜索该图像,那么磁盘上的图像仍然是损坏的。你认为这可能仍然是内存的问题吗? - elgehelge
2
请注意,这不是一个解决方案,而是一个特殊情况。 - gvd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接