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

问题描述 投票:0回答:5

我从外部程序(无法控制它)将图像流保存到文件中(例如每 2 秒一次)。当我尝试读取该图像时,有时会在写入时读取该图像,因此我从 OpenCV 收到有关 JPEG 结尾的消息。有没有办法测试文件是否损坏,如果是则等待一段时间然后尝试重新读取它?

谢谢...

python opencv
5个回答
22
投票

我对这个“错误”进行了一些研究,它似乎是 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
投票

我发现下面的解决方案更加优雅且不那么冗长。尽管如此,它需要 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 读取图像应该可以解决问题。

来源:此媒体帖子


3
投票

此代码片段可能会帮助您检测和修复具有过早结束错误的图像。

简而言之,它检查图像是否以十六进制“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)           

来源:此存储库


0
投票

另一个对我有用的解决方案是使用

pillow
库。

例如,我已将以下

OpenCV
代码更改为
pillow
,所有与 JPEG 相关的警告都消失了:

# img = cv2.imread(img_file_path)
# img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

img = PIL.Image.open(img_file_path).convert("RGB") 
img = np.asarray(img)  # OpenCV RGB image 
© www.soinside.com 2019 - 2024. All rights reserved.