在cv2-python中检测/避免“JPEG过早结束”

6

我有一组图像保存在文件中(例如每2秒钟保存一次),是由外部程序保存的(无法控制)。当我尝试读取该图像时,有时会在写入时进行读取,因此我会收到OpenCV关于JPEG结束的消息。是否有一种方法可以测试文件是否损坏,如果是,则等待一段时间然后尝试重新读取它?

谢谢...


https://docs.python.org/2/tutorial/errors.html# 可能会有所帮助。 - ρss
1
我非常确定它不会引发异常。所以那行不通... - Omer
4个回答

22
我稍微研究了一下这个“错误”,它似乎是C语言中的一个警告,而Python无法正确检测。这是一个非常棘手的问题,因为图像不完整。检测图像是否以b'\xff\xd9'字符正确结束似乎有效:

我对这个“错误”进行了一些调查,发现它是C语言中的一个警告,而Python无法正确检测。这是一个非常棘手的问题,因为图像不完整。检测图像是否以b'\xff\xd9'字符正确结束似乎有效:

with open(os.path.join(path, file), 'rb') as f:
    check_chars = f.read()[-2:]
if check_chars != b'\xff\xd9':
    print('Not complete image')
else:
    imrgb = cv2.imread(os.path.join(path, file), 1)

3
我遇到的解决办法是将文件作为二进制数据读取,然后将其转换为numpy.array:
img = None

while True:
    with open(image_path, 'rb') as img_bin:
        buff = StringIO.StringIO()
        buff.write(img_bin.read())
        buff.seek(0)
        temp_img = numpy.array(PIL.Image.open(buff), dtype=numpy.uint8)
        img = cv2.cvtColor(temp_img, cv2.COLOR_RGB2BGR)

    if img is not None:
        break

3
这个片段可能会帮助你检测和修复出现"Premature Ending Error"的图片。
简单来说,它检查图像是否以十六进制数'D9'结尾。如果没有,使用OpenCV读取并保存图像将会恢复适当的格式。
with open( img_path, 'rb') as im :
        im.seek(-2,2)
        if im.read() == b'\xff\xd9':
            print('Image OK :', img_name) 
        else: 
            # fix image
            img = cv2.imread(img_path)
            cv2.imwrite( img_path, img)
            print('FIXED corrupted image :', img_name)           

source: this repo


這對我來說可行,並且不需要任何額外的套件。 - AljoSt

3

我认为下面的解决方案更加优雅,且简洁明了。尽管需要安装skimage包。

from skimage import io
try:
    _ = io.imread(path)
    img = cv2.imread(path)
    # Do stuff with img
except Exception as e:
    print(e)
    return False

事实证明,skimage捕获了异常而opencv没有。因此,在使用opencv之前,使用skimage.io读取图像可以解决这个问题。
来源:这篇中等文章

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