在OpenCV中使用imread()加载图像时如何捕获损坏的JPEG?

时间:2012-02-03 16:30:21

标签: opencv jpeg corrupt

OpenCV说的是

Corrupt JPEG data: premature end of data segment

Corrupt JPEG data: bad Huffman code

Corrupt JPEG data: 22 extraneous bytes before marker 0xd9

使用imread()加载损坏的jpeg图像时。 我可以以某种方式抓住它吗?为什么我会收到这些信息? 我是否必须自己检查二进制文件?

10 个答案:

答案 0 :(得分:6)

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。从现在开始,您应该能够像任何其他OpenCV错误一样捕获libjpeg错误。例如:

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

(我submitted a pull request对于上述内容,但它被拒绝了,因为它会导致人们在没有异常捕获的情况下阅读图片时出现问题。)

希望这有助于任何仍在努力解决这个问题的人。祝你好运。

答案 1 :(得分:2)

如果使用imread(),则无法捕捉到它。但是imdecode()调用了imread()函数。 也许它会为您提供更多反馈。为此,您必须自己将图像加载到内存中,然后调用解码器。

归结为:您必须深入了解OpenCV来源以解决您的问题。

答案 2 :(得分:2)

我最近不得不处理这个问题并在这里找到了解决方案

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

答案 3 :(得分:2)

在文件中修复错误可能更容易,而不是尝试修复OpenCV的加载功能。如果您使用的是Linux,则可以使用ImageMagick对一组图像进行修复(通常默认安装它):

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

此命令更改文件的属性,使图像数据保持不变。但是,图像被加载并重新保存,从而消除了导致损坏错误的额外信息。

如果您需要有关ImageMagick的更多信息,可以访问他们的网站:http://www.imagemagick.org/script/index.php

答案 4 :(得分:1)

我正在使用opencv python包来读取一些图像,并且还遇到了此错误消息。 Python无法捕获此错误。但是如果你想在不重新编译opencv的情况下找到哪个图像被破坏,可以尝试以下方法。

首先,您可以精确定位损坏图像所在的目录,这非常简单。然后转到目录,并使用ImageMagick 提供的mogrify命令行工具更改图像元信息,如@goe所示。

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

上述命令会将原始jpg图像转换为png格式,并清除原始图像以删除元信息中的错误。当您运行mogrify命令时,它还会输出一些有关目录中哪个图像已损坏的消息,以便您可以准确地找到损坏的图像。

之后,您可以使用原始损坏的jpg图像执行任何操作。

答案 5 :(得分:0)

您可以将stderr重定向到文件,然后在imread之后,在该文件中搜索字符串“Huffman”。搜索文件后,清空它。它适用于我,现在我可以丢弃损坏的图像,只处理好的图像。

答案 6 :(得分:0)

我发现问题出在libjpeg中。如果OpenCV使用它,则会出错

  

损坏的JPEG数据:标记0xd9之前的22个无关字节

您可以尝试my solution来解决它。它在编译期间禁用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 :(得分:0)

任何人都会在这篇文章中发现并读到这个答案。

我不得不抓住一个损坏的图像文件。

这些网站可以帮助您破坏文件

第一个和第三个网站没那么有用。

第二个网站很有意思,因为我可以设置我需要破坏的文件数量。

我在这里使用的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: 做你的代码或者弹出错误

答案 8 :(得分:0)

如果使用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上测试)

答案 9 :(得分:0)

我找到了一个简单的解决方案,无需重新编译 openCV。 您可以使用 imagemagick 来检测相同的错误,但它会按预期返回错误。请参阅此处的说明:https://stackoverflow.com/a/66283167/2887398