Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I catch corrupt JPEGs when loading an image with imread() in OpenCV?

Tags:

OpenCV says something like

Corrupt JPEG data: premature end of data segment 

or

Corrupt JPEG data: bad Huffman code 

or

Corrupt JPEG data: 22 extraneous bytes before marker 0xd9 

when loading a corrupt jpeg image with imread(). Can I somehow catch that? Why would I get this information otherwise? Do I have to check the binary file on my own?

like image 422
Ben Avatar asked Feb 03 '12 16:02

Ben


People also ask

How can you tell if an image is corrupted?

The only way to check if file is corrupted is to try reading it as it is described in file format, ie. load BMP as BMP with reading BMP header, BMP data etc. There are many web pages that describe graphics file formats.

Can you corrupt an image file?

Image files can corrupt due to system or user errors. You know your image is corrupt when you are unable to view the image or your image-editing software is producing error messages. You may even see a distorted version of the picture. You can perform a few steps to troubleshoot a corrupt image file.


2 Answers

OpenCV (version 2.4) does not overwrite the basic error handling for libjpeg, making them 'uncatchable'. Add the following method to modules/highgui/src/grfmt_jpeg.cpp, right below the definition of error_exit():

METHODDEF(void) output_message( j_common_ptr cinfo ) {     char buffer[JMSG_LENGTH_MAX];      /* Create the message */     (*cinfo->err->format_message) (cinfo, buffer);      /* Default OpenCV error handling instead of print */     CV_Error(CV_StsError, buffer); } 

Now apply the method to the decoder error handler:

state->cinfo.err = jpeg_std_error(&state->jerr.pub); state->jerr.pub.error_exit = error_exit; state->jerr.pub.output_message = output_message; /* Add this line */ 

Apply the method to the encoder error handler as well:

cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = error_exit; jerr.pub.output_message = output_message; /* Add this line */ 

Recompile and install OpenCV as usual. From now on you should be able to catch libjpeg errors like any other OpenCV error. Example:

>>> cv2.imread("/var/opencv/bad_image.jpg") OpenCV Error: Unspecified error (Corrupt JPEG data: 1137 extraneous bytes before marker 0xc4) in output_message, file /var/opencv/opencv-2.4.9/modules/highgui/src/grfmt_jpeg.cpp, line 180 Traceback (most recent call last):   File "<stdin>", line 1, in <module> cv2.error: /var/opencv/opencv-2.4.9/modules/highgui/src/grfmt_jpeg.cpp:180: error: (-2) Corrupt JPEG data: 1137 extraneous bytes before marker 0xc4 in function output_message 

(I've submitted a pull request for the above but it got rejected because it would cause issues with people reading images without exception catching.)

Hope this helps anyone still struggling with this issue. Good luck.

like image 67
Robbert Avatar answered Sep 21 '22 02:09

Robbert


It could be easier to fix the error in the file instead of trying to repair the loading function of OpenCV. If you are using Linux you can use ImageMagick to make reparation to a set of images (is usual to have it installed by default):

$ mogrify -set comment 'Image rewritten with ImageMagick' *.jpg

This command changes a property of the file leaving the image data untouched. However, the image is loaded and resaved, eliminating the extra information that causes the corruption error.

If you need more information about ImageMagick you can visit their website: http://www.imagemagick.org/script/index.php

like image 27
goe Avatar answered Sep 23 '22 02:09

goe