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...
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.
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