C++ + OpenCV = 访问冲突读取位置 0x02176000

Posted

技术标签:

【中文标题】C++ + OpenCV = 访问冲突读取位置 0x02176000【英文标题】:C++ + OpenCV = Access violation reading location 0x02176000 【发布时间】:2010-12-17 19:30:48 【问题描述】:

这段代码实际上一直工作到现在。我不知道是什么导致它现在抛出错误(我实际上不记得对代码进行任何更改)。在这里(它从文件中读取图像到 OpenCV IplImage 对象,然后将其转换为 jpeg 缓冲区):

  IplImage* fIplImageHeader = cvLoadImage( filePath.c_str() );

  vector<int> p;
  p.push_back( CV_IMWRITE_JPEG_QUALITY );
  p.push_back( 75 ); // JPG quality
  vector<unsigned char> buf;
  cv::imencode( ".jpg", fIplImageHeader, buf, p ); // this line gives error

完整的错误是:

Unhandled exception at 0x638fee22 in Client.exe: 0xC0000005: Access violation reading location 0x02176000.

fIplImageHeader 包含一个有效的图像,我可以使用它来确认:

cvShowImage( "Window", fIplImageHeader );

编辑:

更长的sn-p:

while ( l < 30 )

            // path to image
    std::stringstream sstm;
    string filePath;
    sstm << workingDirectory << "/temp/" << k << ".jpg";
    filePath = sstm.str();

    cout << filePath.c_str() << endl;

    // load image to IplImage
    IplImage* fIplImageHeader = cvLoadImage( filePath.c_str() );

    // convert to JPG
    vector<int> p;
    p.push_back( CV_IMWRITE_JPEG_QUALITY );
    p.push_back( 75 ); // JPG quality
    vector<unsigned char> buf;
    cv::imencode( ".jpg", fIplImageHeader, buf, p );

            // do stuff

    k++;
    l++;
    if (10 == k)
    
        k = 0;
    

    char key = cvWaitKey( 1000/30 );

    cvReleaseImage( &fIplImageHeader );

【问题讨论】:

imencode 的文档对其参数有何说明? @Martin York opencv.willowgarage.com/documentation/cpp/… 为什么要混合 C++ 和 C 接口? (使用 cv::Mat 的 IplImage 与 cv::imencode) @etarion 我认为这是将 IplImage 转换为 jpeg 而不将其保存到磁盘的唯一方法?我只能将它放在内存(缓冲区)中。如果您知道另一种方法,请发布答案。不过,关键是上面的代码曾经可以工作。 重点是,当您可以访问更友好的 cv::Mat 时,为什么还要使用 IplImage*?此外,您应该使用调试器逐步完成,以查看实际导致错误的原因... 【参考方案1】:

输出缓冲区应该调整为输出图像的大小,但您没有使用buf 对象指定明确的大小。至少在您引用的文档页面 http://opencv.willowgarage.com/documentation/cpp/reading_and_writing_images_and_video.html

中提到了这一点

您可以尝试在buf 上设置明确的大小吗?现在在您的代码示例中,它只是一个空向量。

编辑:是的,我认为你是对的,如果我在 doc 页面上多看几眼,似乎表明 cv::imencode 会进行分配,所以你不应该这样做。如果这是真的,那么您的输入图像是否真的很大,您是否内存不足?也可以进入cv::imencode的调试版吗?

编辑:此页面上还有另一个代码示例http://opencv.willowgarage.com/documentation/cpp/core_basic_structures.html#Mat

IplImage* img = cvLoadImage("greatwave.jpg", 1);
Mat mtx(img); // convert IplImage* -> cv::Mat

您是否也可以尝试“转换为 cv::Mat”步骤,并将其传递给 cv::imencode

【讨论】:

我认为 vector 应该自动调整大小?但我会尝试手动设置它的大小。谢谢。 图片为 31KB jpeg 图片。当加载到 IplImage 时,它​​当然会变大。但它应该仍然很小(可能几百 KB)。 我也尝试了 Mat 转换。抛出相同的异常。我在我的问题中添加了更长的代码 sn-p。我实际上是在尝试在 while 循环中执行此操作,但是在第一个循环中出现异常,因此这应该不是问题。 转换是隐式完成的,这就是它可以在所有工作中工作的原因。 @etarion 我也尝试从一开始就使用 Mat 并且我得到了同样的异常,所以其他地方肯定有问题。【参考方案2】:

编辑:我的错,我没有使用那种方法......所以我不知道出了什么问题......

我在使用“imencode”时遇到了同样的异常,我不知道是否需要调整 jpegBuf 向量的大小

void CWebcamWidget::putJpegImage(IplImage *iplImage) 
    // Sans compression jpeg
    //image = QImage((const uchar*)iplImage->imageData, iplImage->width, iplImage->height, QImage::Format_RGB888).rgbSwapped();

    // Still doesn't work using cv::vector...
    cv::vector<int> p;
    p.push_back(CV_IMWRITE_JPEG_QUALITY);
    p.push_back(75); // JPG quality
    cv::vector<uchar> jpegBuf;
    imencode(".jpg", iplImage, jpegBuf, p);

    // Conversion vector<uchar> => uchar*
    uchar *buf;
    memcpy(buf, &jpegBuf[0], sizeof(uchar)*jpegBuf.size());

    image = QImage((const uchar*)buf, iplImage->width, iplImage->height, QImage::Format_RGB888).rgbSwapped();
    imageLabel->setPixmap(QPixmap::fromImage(image));

我不知道我是否真的需要从vector转换为uchar*,也许没有它我可以节省一些CPU时间......

【讨论】:

【参考方案3】:

我最近在使用 OpenCV 3.0 和 Visual Studio 2015 的项目的调试版本中也遇到了这个问题。该项目之前是用 Visual Studio 2013 构建的,我不记得有这个问题。发布版本也没有触发异常。在调用imencode 时发生异常,我这样使用:

bool writeImageToDisk(const std::string& filename, cv::Mat image) 
    std::vector<uchar> imageData;
    bool result = cv::imencode(".jpg", image, imageData);
    if (!result) 
        return false;
    
    ...

我使用了从 OpenCV 官方网站下载的 openvc_world300.dll 和 .lib。由于它们被放置在子文件夹 vc12 中,我假设它们是使用 Visual Studio 2013 构建的。我无法测试 Debug 版本,因为我的系统上没有安装适当的 Visual C++ 2013 DLL。

升级到 OpenCV 3.2 后,这个问题已为我解决,而没有触及其他任何东西,所以分布式二进制文件可能存在错误或问题。

【讨论】:

以上是关于C++ + OpenCV = 访问冲突读取位置 0x02176000的主要内容,如果未能解决你的问题,请参考以下文章

C ++中的openCV Mat访问冲突

当我尝试删除数组时,C++ 访问冲突读取位置 0xDDDDDDCD 已更新

访问冲突读取位置 0xcccccccc

C++:XY.exe 中 0x0b9ec715 (XX.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000004

异常错误:访问冲突读取位置 0xDDDDDDDD

C ++访问冲突读取位置0xcdcdcdcd调用函数时出错