【问题标题】:How can I catch corrupt JPEGs when loading an image with imread() in OpenCV?在 OpenCV 中使用 imread() 加载图像时如何捕获损坏的 JPEG?
【发布时间】:2012-02-26 06:26:07
【问题描述】:

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 图像时。 我能以某种方式抓住它吗?否则我为什么会得到这些信息? 我必须自己检查二进制文件吗?

【问题讨论】:

  • 嗨,你有这个问题的解决方案吗,我也反对 OpenCV 的这个问题。谢谢!
  • 用户可能也有兴趣阅读post here

标签: opencv jpeg corrupt


【解决方案1】:

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

归结为:您必须深入挖掘 OpenCV 源代码才能解决您的问题。

【讨论】:

  • 是的..我害怕有人会告诉我这个;)
  • 你有没有找到办法做到这一点,我会很感兴趣,因为我面临同样的问题。
  • imdecode() 没有给出关于 libjpeg 警告的任何反馈
【解决方案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】:

    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,但它被拒绝了,因为它会导致人们阅读图像时出现问题,而不会异常捕捉。)

    希望这可以帮助仍在努力解决此问题的任何人。祝你好运。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        我发现问题出在 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  ..
        

        【讨论】:

        • 您应该在此处发布您的解决方案,而不是将用户指向其他地方。链接用于提供更多信息。
        【解决方案6】:

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

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

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

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

        【讨论】:

        • 虽然很难捕捉到错误,但至少我们可以通过这种方式消除错误信息。很好的解决方法~
        【解决方案7】:

        我正在使用 opencv python 包读取一些图像,也遇到了这个错误消息。 Python 无法捕获此错误。但是如果你想在不按照@Robbert的建议重新编译opencv的情况下找到损坏的图像,你可以试试下面的方法。

        首先,您可以查明损坏图像所在的目录,这相当容易。然后你进入目录,使用ImageMagick 提供的mogrify命令行工具来更改图像元信息,正如@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 上测试)

            【讨论】:

              【解决方案10】:

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

              【讨论】:

                猜你喜欢
                • 2021-12-26
                • 2012-10-15
                • 2021-04-28
                • 2021-07-28
                • 2019-10-19
                • 1970-01-01
                • 2021-09-08
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多