在同一台计算机上运行多个版本的OpenCV

25
我的电脑正在运行Ubuntu-16.04-LTS操作系统,已经安装了OpenCV-2.4.13。但是,我想使用更新版本的OpenCV功能,如OpenCV-3.2.0,而不删除旧版本。
到目前为止,我已经下载了OpenCV-3.2.0并进行了编译和安装。我正在使用CMake编译OpenCV,因此我更改了我的CMakeLists.txt文件:
cmake_minimum_required (VERSION 3.2)

project(io)

find_package(OpenCV REQUIRED)

include_directories("/home/ubuntu/opencv-3.2.0/include") # directory of OpenCV-3.2.0
link_directories("/home/ubuntu/opencv-3.2.0/lib") # directory of OpenCV-3.2.0

add_executable(cv_io io.cpp)

target_link_libraries(cv_io ${OpenCV_LIBS})

现在,当我运行这段小代码时,
#include <iostream>
#include "opencv2/core/version.hpp"

int main(int argc, char ** argv)
{
  std::cout << "OpenCV version: "
            << CV_MAJOR_VERSION << "." 
            << CV_MINOR_VERSION << "."
            << CV_SUBMINOR_VERSION
            << std::endl;
  return 0;
}

我得到的是

OpenCV版本:3.2.0

而不是

OpenCV版本:2.4.13

所以一切似乎都很正常,除了当我开始运行一些实际的OpenCV函数,例如:

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>

int main()
{
    cv::Mat img = cv::imread("ferrari.jpg");

    cv::Mat dst;
    cv::Sobel(img, dst, CV_32F, 1, 1);

    cv::imwrite("ferrari_sobel.png", dst);

    cv::VideoCapture input(0);
}

我遇到了所有这些未定义引用错误:

CMakeFiles/cv_io.dir/io.cpp.o: 在函数 main' 中: io.cpp:(.text+0x40): 对 cv::imread(cv::String const&, int) 未定义的引用 io.cpp:(.text+0xd4): 对 cv::imwrite(cv::String const&, cv::_InputArray const&, std::vector<int, std::allocator<int> > const&) 未定义的引用 CMakeFiles/cv_io.dir/io.cpp.o: 在函数 cv::String::String(char const*): io.cpp:(.text._ZN2cv6StringC2EPKc[_ZN2cv6StringC5EPKc]+0x40): 对 cv::String::allocate(unsigned long) 未定义的引用 CMakeFiles/cv_io.dir/io.cpp.o: 在函数 cv::String::~String(): io.cpp:(.text._ZN2cv6StringD2Ev[_ZN2cv6StringD5Ev]+0x10): 对 cv::String::deallocate() 未定义的引用 CMakeFiles/cv_io.dir/io.cpp.o: 在函数 cv::String::operator=(cv::String const&): io.cpp:(.text.ZN2cv6StringaSERKS0[ZN2cv6StringaSERKS0]+0x2c): 对 cv::String::deallocate() 未定义的引用 collect2: error: ld 返回 1 退出状态 CMakeFiles/cv_io.dir/build.make:121: 目标 'cv_io' 失败 make2: *** [cv_io] 错误 1 CMakeFiles/Makefile2:67: 目标 'CMakeFiles/cv_io.dir/all' 失败 make1: *** [CMakeFiles/cv_io.dir/all] 错误 2 Makefile:83: 目标 'all' 失败 make: *** [all] 错误 2

有人知道如何解决这个问题吗?我认为问题在于我仍然没有正确地在CMakeLists.txt中链接所有库。此外,我发现本文下面的评论提到了类似于我正在经历的问题,但我不理解包含解决方案的页面它所指的内容。我对OpenCV和CMake非常陌生,希望您能提供尽可能明确的说明。我已经卡在这里很久了,所以任何帮助都将不胜感激!非常感谢!


1
配置两个不同版本的OpenCV真是太痛苦了,我深有同感。 - yotabyte
如果您有兴趣,可以在Docker容器上运行两个版本。这样配置多个版本就会更加容易,而不会影响系统范围内的软件包。 - Srinivas
1
@Srinivas 虽然那个方法应该可行,但似乎有点过度和繁重。 - Gabriel Devillers
3个回答

18

我有一个工作中的CMakelists.txt,与您描述的几乎相同,只是我正在运行一个非常旧的Ubuntu 12.04(这不是我的计算机)。

我认为你的问题来自于这一行:

find_package(OpenCV REQUIRED)

这使你可以访问您所用分发版本的OpenCV 2.4。然后,您正在链接手动安装的3.2.x版本。因此,当您使用的函数接口在两个版本之间发生更改时,问题就会出现。我想您的第一段代码是偶然运行成功的。

这是我的CMakeList.txt文件:

cmake_minimum_required(VERSION 2.8)
project(demo)

find_package(OpenCV 3.2 REQUIRED PATHS "/path/to/OCV3.2/install/dir/")

include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(main main.cpp)
target_link_libraries(main ${OpenCV_LIBS})

如果您不想将OpenCV 3.2安装的硬编码路径提交到您的存储库中,您可以通过更改CMakeList.txt中的find_package行来进行优化:

if(DEFINED ENV{OPENCV_INSTALL_DIR})
    find_package(OpenCV 3.2 REQUIRED PATHS $ENV{OPENCV_INSTALL_DIR})
else()
    message("OPENCV_INSTALL_DIR not set, searching in default location(s)")
    find_package(OpenCV 3.2 REQUIRED)
endif(DEFINED ENV{OPENCV_INSTALL_DIR})

然后您只需要在运行cmake之前定义变量OPENCV_INSTALL_DIR。我通过从我的.bashrc导出它来实现这一点。


1
在设置包含文件以使用新安装的OpenCV头文件时,您正在链接到系统路径上的opencv。版本只存储在头文件中,这就是为什么它输出预期版本但无法链接的原因。在运行查找模块之前,请尝试将变量“OpenCV_DIR”设置为要使用的OpenCVConfig.cmake文件的位置。
请参阅您所使用的cmake版本的文档here。请注意find_package可以在两种模式(模块或配置模式)下运行。
除非您链接到静态库,否则仍然会出现运行库/应用程序的问题。要解决此问题,您需要将库添加到LD_LIBRARY_PATH中。

1

确实,您正在链接到系统默认版本的OpenCV。

通过使用正确的OpenCVConfig.cmake文件路径调用CMake来重新配置您的项目。

cmake /path/to/your/sources -DOpenCV_DIR=/home/ubuntu/opencv-3.2.0

在构建目录中查找文件CMakeCache.txt。它包含内部CMake变量,其中也包括OpenCV路径。

此外,硬编码路径是不正确的。使用include_directories(${OPENCV_INCLUDE_DIRS})

引用自OpenCVConfig.cmake

  - OpenCV_LIB_DIR                  : The directory(es) where lib files are. Calling LINK_DIRECTORIES
                                     with this path is NOT needed.

他没有运行时错误,这是在链接期间发生的。他使用的CMake命令告诉它链接到错误版本的库。 - jhauris
@wl2776 我刚刚运行了 cmake .. -DOpenCV_DIR=/home/ubuntu/opencv-3.2.0 然后是 make,但是未定义的引用错误仍然存在。另外,最初我使用了 include_directories(${OPENCV_INCLUDE_DIRS}),但是当我运行打印版本代码时,它会打印出 OpenCV version: 2.4.13,所以这就是我为什么切换到现在正在使用的东西的原因。 - Tony Tarng

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