发布模式和调试模式下使用Haar级联的结果不同。

13

我正在使用从MIT汽车数据集训练的Haar级联分类器来在OpenCV中检测车辆(使用OpenCV提供的实用程序进行训练)。当以Debug模式编译时,这个方法运行得相当好,但是当以Release模式编译时,级联就完全没有检测到。在下面的测试图像上运行以下代码可以在Debug模式下检测到一个目标,但无法在Release模式下检测到(这种情况在我的所有数据序列中都持续发生)。

您有什么建议,为什么会出现这种情况,更重要的是,在Release模式下运行时我应该怎么做才能获得检测结果?

级联文件

代码

cv::Mat testImage = cv::imread("testImage.png",0);
cv::equalizeHist(testImage, testImage);

cv::CascadeClassifier vehicleCascade;
vehicleCascade.load("cars3.xml");

// Detect vehicles
std::vector<cv::Rect> cars;
vehicleCascade.detectMultiScale(
    testImage,                  // Input image
    cars,                   // Output bounding boxes
    1.1,                    // scale factor - how much image size is reduced at each scale
    5,                      // min neighbours - how many neighbours required to maintain rect
    0|CV_HAAR_SCALE_IMAGE,  // Not used
    cv::Size(30,30),        // Min poss object size
    cv::Size()              // Max poss object size
    );

std::cout << "Found " << cars.size() << " objects.\n";

for (int i=0; i<cars.size(); ++i)
    cv::rectangle(testImage, cars.at(i), CV_RGB(255,0,0), 3);

cv::namedWindow("Haar cascade");
cv::imshow("Haar cascade", testImage);
cv::waitKey(0);
cv::imwrite("output.png", testImage);

测试图片

testImage


图像和级联文件加载正常,在我的实际代码中,我使用完整的目录路径。据我所知,两种模式都没有错误,唯一的区别是detectMultiScale返回的对象数量。 - Chris
好的 :/ 我删除了我的第一条评论,因为关于 PNG 的部分不相关。 - Étienne
这通常是存在未定义行为并依赖于特定行为(无论是在您的代码中还是在库中)或依赖于不同的特定生成代码(例如,由于在发布模式下保留在寄存器中的内容而导致浮点精度不同)的迹象。在这里,您可以做的最好的事情是逐步比较两种模式下涉及的所有计算,并找出它们开始偏离的地方。 - PlasmaHH
同意PlasmaHH的观点:很可能是UB的问题。你可能有一个栅栏错误,它经常在调试版本中产生某些行为,然后在发布版本中产生不同的行为,因为分配的顺序不同。作为一个快速而廉价的测试,你尝试在valgrind中运行程序了吗? - smocking
2个回答

3
  1. 很奇怪,但对我来说,你的代码在两种模式下都能正常工作。我使用的是Windows 7 32位上的Visual Studio 2010。这是我的项目 - https://www.dropbox.com/s/5kubn5tlu7k6ziy/opencvhw.rar,所以你可以检查可执行文件(Release和Debug目录)。如果你正在使用Visual Studio并希望自己构建它,你需要更改两种模式的库和包含目录的路径(包含目录路径相同,库目录路径不同)。(项目->...属性->配置属性->vc++目录)

  2. 一般来说,我建议认真检查项目配置。很容易犯小错误,这可能会导致非常奇怪的行为。有时重新从头开始配置一切可能是最好的选择。

  3. OpenCV有非常奇怪的bug - 这不是什么新鲜事:)例如,我无法在调试时使用某些编解码器 - 如果我在调试模式下运行程序,但不进行调试,则一切正常,但如果我尝试调试 - 从文件读取的每个帧都为空(但其大小正确)。 可能你只是遇到了类似的问题。尝试将图像转换为不同的格式(我认为bmp是测试的最佳选择 - 它应该始终在没有任何其他库的情况下工作)。

  4. 还要注意,你上传了jpg文件,所以我不得不自己重命名和转换它 - 可能在转换过程中,这个文件中的一些内容发生了变化,所以我们没有在完全相同的文件上测试你的代码 - 在dropbox上上传你的png文件,这样我就可以测试它。


感谢您为我解决这个问题。不幸的是,我目前无法访问Dropbox,因此无法测试您的项目或上传更多文件,但我可以确认我仍然有同样的问题。我使用CMake生成项目,所以可能有一些选项我没有注意到。目前我已经从我的项目中省略了Haar级联,并将在以后返回进行更多调查。 - Chris

2

请看这篇帖子: 这种错误可能是由于在发布模式下链接到OpenCV的调试库所致。


我已经阅读了相关内容,但是我在加载XML文件或运行代码方面没有任何问题,只是输出结果不同。此外,正确的OpenCV dll被加载 - 调试版本用于调试,发布版本用于发布。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接