使用OpenCV 2.4.12的SurfFeatureDetector后偶发崩溃问题求助
问题原因
- 第一个是OpenCV 2.4.x版本编译链接不匹配:这是最常见的偶发析构崩溃诱因,尤其是Windows平台下,如果出现以下任意一种情况,都会导致堆内存管理不一致,nonfree模块分配的附加数据在你的代码段释放时触发崩溃:
- 编译时链接的OpenCV头文件版本和运行时加载的动态库版本不一致
- Debug模式编译的程序链接了Release版本的OpenCV库,或者反过来
- 项目运行时库设置(/MD、/MDd、/MT、/MTd)和编译OpenCV时用的运行时库不一致
- 第二个是2.4.12版本SURF实现的已知bug:该版本的SURF特征提取逻辑在处理纹理极浅、尺寸过小的输入图像时,内部会出现越界写入,破坏存储关键点的vector的控制头数据,导致析构时尝试访问非法地址,而同版本的SIFT没有这个问题,所以只会在使用SURF时复现。
修复方案
- 优先检查链接配置:确认所有依赖的OpenCV库(尤其是
opencv_nonfree模块)的版本、编译模式和项目配置完全一致,Windows平台下Debug模式必须带d后缀的库,Release模式用不带后缀的库,运行时库参数和OpenCV编译参数保持一致。 - 替换SURF调用接口:不要用
SurfFeatureDetector的抽象接口,直接调用底层SURF实现,代码修改如下:
{ cv::SiftFeatureDetector siftDetector; cv::SURF surfDetector(400); // 直接用cv::SURF类 std::vector<cv::KeyPoint> siftKeypoints,surfKeypoints; try { siftDetector.detect(fiducial,siftKeypoints); // 替换detect调用方式 surfDetector(fiducial, cv::Mat(), surfKeypoints); } catch (...) { return; } ... return; }
- 临时规避方案:可以将SURF的阈值参数调大,过滤掉低置信度的特征点,降低触发越界bug的概率,或者升级到OpenCV 3.x及以上版本,该bug在后续版本已经修复。
内容的提问来源于stack exchange,提问作者Elmi
相关产品推荐
相关产品推荐

