Как я могу поймать поврежденные JPEG при загрузке изображения с imread () в OpenCV?

OpenCV говорит что-то вроде

Corrupt JPEG data: premature end of data segment

или

Corrupt JPEG data: bad Huffman code

или

Corrupt JPEG data: 22 extraneous bytes before marker 0xd9

при загрузке поврежденного изображения jpeg с помощью imread (). Могу я как-нибудь это уловить? Иначе зачем бы мне получать эту информацию? Должен ли я проверить двоичный файл самостоятельно?

8 ответов


вы не можете поймать его, если вы используете imread(). Однако есть imdecode() функция, которая вызывается imread(). может быть это дает вам больше обратной связи. Для этого вам нужно будет загрузить изображение в память самостоятельно, а затем вызвать декодер.

это сводится к: вы должны копаться в источниках OpenCV, чтобы решить вашу проблему.


OpenCV (версия 2.4) не перезаписывает основную обработку ошибок для libjpeg, делая их "неуловимыми". Добавьте следующий метод в modules/highgui/src/grfmt_jpeg.cpp, под определение 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);
}

теперь примените метод к обработчику ошибок декодера:

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 */

применить метод к обработчику ошибок кодировщика, а также:

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

перекомпилировать и установить OpenCV, как обычно. Отныне вы должны быть в состоянии поймать ошибки libjpeg, как и любой другой OpenCV ошибка. Пример:

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

подан запрос на вытягивание для вышеизложенного, но он был отклонен, потому что это вызовет проблемы с людьми, читающими изображения без исключения.)

надеюсь, это поможет любому, кто все еще борется с этой проблемой. Удача.


мне пришлось иметь дело с этим недавно и нашел решение здесь

http://artax.karlin.mff.cuni.cz / ~isa_j1am / другое / opencv/

Мне просто нужно сделать 2 правки @ $cv\modules\highgui\src\grfmt_jpeg.СРР.

--- opencv-1.0.0.orig/otherlibs/highgui/grfmt_jpeg.cpp  2006-10-16 13:02:49.000000000 +0200
+++ opencv-1.0.0/otherlibs/highgui/grfmt_jpeg.cpp   2007-08-11 09:10:28.000000000 +0200
@@ -181,7 +181,7 @@
             m_height = cinfo->image_height;
             m_iscolor = cinfo->num_components > 1;

-            result = true;
+            result = (cinfo->err->num_warnings == 0);
         }
     }

@@ -405,8 +405,9 @@
                         icvCvt_CMYK2Gray_8u_C4C1R( buffer[0], 0, data, 0, cvSize(m_width,1) );
                 }
             }
-            result = true;
+
             jpeg_finish_decompress( cinfo );
+            result = (cinfo->err->num_warnings == 0);
         }
     }

может быть проще исправить ошибку в файле вместо того, чтобы пытаться восстановить функцию загрузки OpenCV. Если вы используете Linux, вы можете использовать ImageMagick для восстановления набора изображений (обычно он устанавливается по умолчанию):

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

эта команда изменяет свойство файла, оставляя данные изображения нетронутыми. Однако изображение загружается и повторно сохраняется, устраняя дополнительную информацию, которая вызывает ошибку повреждения.

Если вам нужна дополнительная информация о ImageMagick вы можете посетить их веб-сайт:http://www.imagemagick.org/script/index.php


вы можете перенаправить stderr в файл, затем после imread найдите строку "Huffman" внутри этого файла. После поиска файла очистите его. Это работает для меня и теперь я могу отбросить испорченные снимки и просто хороших.


Я использую пакет OpenCV python для чтения некоторого изображения, а также встретил это сообщение об ошибке. Эта ошибка не может быть поймана Python. Но если вы хотите найти, какое изображение повреждено без перекомпиляции opencv, как предложил @Robbert, вы можете попробовать следующий метод.

во-первых, вы можете определить каталог, где находятся поврежденные изображения, что довольно легко. Затем перейдите в каталог и используйте mogrify инструмент командной строки, предусмотренные ImageMagick изменить метаинформация изображения, как предлагает @goe.

mogrify -set comment "errors fixed in meta info" -format png *.jpg

вышеуказанная команда преобразует исходное изображение jpg в формат png, а также очистит исходное изображение, чтобы удалить ошибки в meta info. При запуске mogrify команда, она также выведет сообщение о том, какое изображение повреждено в каталоге, чтобы вы могли точно найти поврежденное изображение.

после этого вы можете делать все что угодно с исходным поврежденным изображения.


Я обнаружил, что проблема находится в libjpeg. Если OpenCV использует его, он получает ошибку

поврежденные данные JPEG: 22 посторонних байта перед маркером 0xd9

вы можете попробовать мое решение чтобы решить это. Он отключает JPEG во время компиляции. После этого OpenCV не может читать / писать, но он работает.

cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_SHARED_LIBS=OFF -D BUILD_EXAMPLES=OFF -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D WITH_JPEG=OFF -D WITH_IPP=OFF  ..

любой натыкается на этот пост и прочитает этот ответ.

я должен был получить поврежденный файл изображения.

эти веб-сайты могут помочь вам повредить файл

первый и третий сайт был не так уж и полезен.

второй веб-сайт интересен, поскольку я мог бы установить объем файла, который мне нужно повредить.

OpenCV версия, которую я использовал здесь 3.4.0

я использовал обычный тег cv2.imread(fileLocation)

fileLocation расположение поврежденного файла изображения

OpenCV не показал никакого сообщения об ошибке для любого из поврежденных файлов, используемых здесь

первый и третий веб-сайт дали только один файл, и оба имели None хранящиеся в их, когда я пытался напечатать их

второй веб-сайт позволил мне решить объем файла, который должен был быть поврежден

Corruption% Opencv сообщение о печати изображения

4% нет

10% нет

25% нет

50% нет Corrupt JPEG data: 3 extraneous bytes before marker 0x4f

75% нет Corrupt JPEG data: 153 extraneous bytes before marker 0xb2

100% Corrupt JPEG data: 330 extraneous bytes before marker 0xc6 нет

Я думаю только проверить мы должны сделать здесь будет

if image is not None: Сделайте свой код или еще поп ошибка