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编辑:我的错,我没有使用那种方法......所以我不知道出了什么问题......
我在使用“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++ 访问冲突读取位置 0xDDDDDDCD 已更新
C++:XY.exe 中 0x0b9ec715 (XX.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000004