Как я могу поймать поврежденные файлы 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)