使用发布库时,OpenCV的imread(文件名)在调试模式下失败

25

我有一些C++代码,除了函数imread(file)之外,所有东西在OpenCV上都运行良好。 它可以正确找到文件并加载名称,但不会加载任何数据。

Mat pattImage = imread(fileName, 0);

经过在网上的一些研究,我意识到我处于调试模式,但使用的是发布版 OpenCV 库,而不是调试版。

debug library:    opencv_core231d.lib
release library:  opencv_core231.lib

虽然这是一个典型的愚蠢错误,我认为这与调试库应该允许OpenCV代码调试,而发布库则允许更快地执行代码毫无关系,但我不明白为什么imread会失败。

有人可以解释一下在OpenCVdebugrelease库之间的区别以及为什么会出现这个错误吗?

这是一个OpenCV的bug吗?


1
是的,它是2.3.1版本。在Windows 7,32位上。 - Jav_Rock
3
我永远都不会厌倦告诉人们,OpenCV在Windows下使用C++接口时会出现最奇怪的错误。你可以试着用C接口编写一个小测试来检查它是否正常工作(例如cvLoadImage()等)。请自行尝试。 - karlphillip
1
是的,使用C接口它确实可以工作,但我仍然想知道为什么它会失败,因为我认为它不应该失败。也许在将来的版本中他们会修复它。无论如何,我仍然喜欢解决OpenCV的问题... - Jav_Rock
复现在2.4.8版本中。真的很奇怪……O_o使用调试库可以正常工作。 - Jon Ander Ortiz Durántez
7个回答

29

我永远不会厌倦地告诉人们,在Windows下,C++ OpenCV接口存在着最奇怪的bug

编写一个小测试,使用C接口检查它是否正常工作(cvLoadImage()等)。

更新:现在您知道了C接口可以正常工作,您可以选择去邮件列表中报告这个错误或自己深入代码中找出为什么它失败了。


在另一个问题(http://stackoverflow.com/q/19206627/575530)中,我被导向使用C++接口而不是C接口,但是您的回答让我想知道。您是否建议Windows用户使用C接口而非C++接口? - dumbledad
3
不行,C++接口没问题,问题是一些OpenCV安装程序提供了使用特定标志编译的二进制文件,你需要在项目中设置这些标志才能构建带有OpenCV的应用程序。例如,在Visual Studio上,你可能想要进入项目属性,选择C/C++ > 代码生成,并确保运行库字段设置为“多线程调试(/MTd)” - karlphillip
你如何知道你的库不匹配?我已使用CMAKE_BUILD_TYPE=DEBUG重建了opencv。我正在linux上的eclipse中编译我的测试程序。但是imread无法加载有效图像。 - Seth
这里报告的问题不适用于Linux。您是否传递了文件的完整路径(而不是相对路径)? - karlphillip

9
在发布模式下,您必须使用发布库,在调试模式下 - 调试库。这不是一个错误。

你具体怎么做到的? - KansaiRobot

3

2
一般情况下,将“Debug”可执行配置与“Release”配置库链接是完全合法的(只要库导出的符号在Debug和Release中相同,为什么不行呢?)。除非你不想让这种“混合”发生。 但是,OpenCV开发人员决定不允许这种混合,并且他们使用特定代码段执行此类禁止(您可以在发布3.4.4行54的文件cvdef.h中找到此内容)。 这不是C++接口错误,而是“有意”的行为。 您可以在https://github.com/opencv/opencv/pull/9161找到更多信息,其中记录了此更改。

1
例如OpenCV 4.2,
按以下方式更改项目属性:
配置:调试
配置属性->链接器->输入->其他依赖项
添加 opencv_world420d.lib
配置:发布
配置属性->链接器->输入->其他依赖项
添加 opencv_world420.lib
然后你就可以了。

1

请使用正斜杠 (/) 而不是反斜杠 (\),即使在 Windows 系统中也是如此。

错误示例:

cv::imread("C:\example\1.jpg");

正确:

cv::imread("C:/example/1.jpg");

0

你可以通过将Debug应用程序的运行库从/MDd(多线程DLL调试版本)更改为/MD(多线程DLL常规发布版本),来解决这个问题。

你的代码仍然未经优化,比正常发布模式更易于调试,但是你会失去一些调试信息(例如在C运行时内部崩溃的信息)。 你也会失去一些调试特性,例如调试堆,但是如果你不知道它是什么,则不会影响你。

要执行此工作,只需转到“属性>C / C ++ / 代码生成”,并将“运行时库”从/MDd更改为/MD。


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