Detect / Avoid "Premature End of Jpeg" in Cv2 - Python

Detect / Avoid "Premature End of Jpeg" in Cv2 - Python

I have a stream of images saved to a file (like every 2 seconds) from outside program (can't control it). When I try to read that image, sometimes, it is read while it is being written, so I get the message from OpenCV about the end of the JPEG. Is there a way to test if the file is bad, and if so to wait a while and then try to re-read it?

Thanks...

2

4 Answers

I researched a little about this "error", and it appears to be a warning in C which python cannot detect properly. It's a very tough issue, and happens because the image is not complete. Detecting if the image ends properly (with b'\xff\xd9' characters) seems to work:

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)

I found the below solution to be much more elegant and less verbose. Albeit, it requires the skimage package.

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

Turns out skimage catches the exception while opencv doesn't. So, reading in the image with skimage.io before opencv should solve the problem.

Source: This medium post.

0

The solution that worked for me was to read the file as binary data and then turn it to a 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

This snippet might help you in detecting and fixing Images with the Premature Ending Error.

In short it checks if the image ends with the hex 'D9'. If it doesn't, using opencv to read and then save the image will restore the appropriate format.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Maya Lin-Takahashi
Author

Maya Lin-Takahashi

Maya is a hardware enthusiast who tests and reviews smart home devices, smartphones, wearables, and audio gear. She focuses on practical consumer value and build quality.