Запуск нескольких версий OpenCV на одном компьютере

Мой компьютер работает 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);
}

Я получаю все эти справочные ошибки undefined:

CMakeFiles/cv_io.dir/io.cpp.o: В функции main': io.cpp:(.text+0x40): undefined reference to cv:: imread (cv:: String const &, int) 'io.cpp: (. text + 0xd4): undefined ссылка на cv::imwrite(cv::String const&, cv::_InputArray const&, std::vector<int, std::allocator<int> > const&)' CMakeFiles/cv_io.dir/io.cpp.o: In function резюме:: Строка:: String (charсопз *) ':. Io.cpp:( text._ZN2cv6StringC2EPKc [_ZN2cv6StringC5EPKc] + 0x40): undefined ссылка на cv::String::allocate(unsigned long)' CMakeFiles/cv_io.dir/io.cpp.o: In function cv:: String:: ~ String() ': io.cpp:(. text._ZN2cv6StringD2Ev [_ZN2cv6StringD5Ev] + 0x10): undefinedссылка на cv::String::deallocate()' CMakeFiles/cv_io.dir/io.cpp.o: In function cv:: String:: operator = (cv:: String const &) ': io.cpp:( text.ZN2cv6StringaSERKS0 [ZN2cv6StringaSERKS0] + 0x2c).: undefined ссылка на `cv:: String:: deallocate() 'collect2: error: ld вернулся 1 статус выхода CMakeFiles/cv_io.dir/build.make: 121: рецепт для target 'cv_io' не удалось сделать 2: * [cv_io] Ошибка 1 CMakeFiles/Makefile2: 67: рецепт для цели "CMakeFiles/cv_io.dir/all" не удалось сделать 1: * [CMakeFiles/cv_io.dir/all] Ошибка 2 Makefile: 83: рецепт для цели "все" не удалось: *** [все] Ошибка 2

Кто-нибудь знает, как решить эту проблему? Я думаю, проблема в том, что я все еще не связываю все библиотеки правильно в CMakeLists.txt. Кроме того, я нашел комментарий ниже этой статьи, в котором упоминается нечто похожее на то, что я испытываю, но я не понимаю страница, содержащая решение, о котором идет речь. Я очень новичок в OpenCV и CMake, поэтому, надеюсь, вы можете предоставить мне инструкции, которые настолько ясны, насколько это возможно. Я застрял на этом навсегда, поэтому любая помощь высоко ценится! Большое спасибо!

Ответ 1

У меня есть рабочий 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})

Тогда вам просто нужно определить переменную OPENCV_INSTALL_DIR перед запуском cmake. Я делаю это, экспортируя его из моего .bashrc

Ответ 2

Действительно, вы связываетесь с версией OpenCV по умолчанию, установленной по умолчанию.

Переконфигурируйте свой проект, вызвав CMake с правильным путем в файл OpenCVConfig.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.

Ответ 3

Пока вы настраиваете включенные файлы для использования вновь установленных заголовков OpenCV, вы связываетесь с opencv на вашем системном пути. Версия просто хранится в заголовках, поэтому она выводит ожидаемую версию, но не связывает ее. Попробуйте установить переменную "OpenCV_DIR" в местоположение файла OpenCVConfig.cmake, который вы хотите использовать до запуска модуля поиска.

Смотрите документацию для вашей версии cmake здесь. Обратите внимание на два режима, в которых может быть найден find_package (режим Module или Config).

Если вы не связываетесь со статическими библиотеками, у вас все еще будут проблемы с запуском вашей библиотеки/приложения. Чтобы исправить это, вам нужно добавить библиотеки в LD_LIBRARY_PATH.