Как я могу поймать поврежденные файлы 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(). Могу ли я как-то поймать это? Почему я должен получить эту информацию в противном случае? Нужно ли мне проверять двоичный файл самостоятельно?

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

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

http://artax.karlin.mff.cuni.cz/~isa_j1am/other/opencv/

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

--- 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);
         }
     }

Ответ 4

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

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

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

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

Ответ 5

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

Ответ 6

Я обнаружил, что проблема в 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  ..

Ответ 7

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

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

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

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

После этого вы можете делать все, что хотите, с оригинальным поврежденным jpg-изображением.

Ответ 8

Любой спотыкается об этом посте и читает этот ответ.

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

Эти сайты могут помочь вам испортить ваш файл

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

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

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: введите код или выведите ошибку

Ответ 9

Если вы загружаете ваше изображение с помощью imdecode, вы можете проверить errno:

  std::vector<char> datas();
  //Load yout image in datas here
  errno = 0;
  cv::Mat mat = cv::imdecode(datas, -1);
  if (errno != 0)
  {
    //Error
  }

(протестировано на OpenCV 3.4.1)