OpenCV的安装与版本管理

本文最后更新于 2024年10月14日 下午

本文主要分享了在Linux下OpenCV库的安装与版本管理。

安装

1. 安装依赖

1
2
3
4
5
6
7
# 安装依赖
sudo apt-get -y install libopencv-dev build-essential cmake git libgtk2.0-dev libtiff5-dev
sudo apt-get -y install pkg-config python-dev python-numpy libdc1394-22 libdc1394-22-dev
sudo apt-get -y install libtheora-dev libvorbis-dev libxvidcore-dev x264 v4l-utils unzip
sudo apt-get -y install libqt4-dev libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev
sudo apt-get -y install libswscale-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-dev libtbb-dev
sudo apt-get -y install libjpeg-dev libpng12-dev libjasper-dev libavcodec-dev libavformat-dev

2. 新建文件夹

下载地址:https://opencv.org/releases/

点击Sources进行下载自己需要的版本。

1
2
3
4
5
6
7
8
mkdir opencv  # 创建新的文件夹作为OpenCV的目录
cd opencv # 将路径转到OpenCV的目录
# 下载OpenCV的安装包
wget https://github.com/Itseez/opencv/archive/3.2.0.zip -O opencv-3.2.0.zip # 此处3.2.0可换成任意自己需要的版本即可直接下载相应版本
unzip opencv-3.2.0.zip # 解压OpenCV的安装包
cd opencv-3.2.0 # 将路径转到opencv-3.2.0的目录
mkdir build # 创建build文件夹
cd build # 将路径转到build文件夹

3. 编译安装

编译安装流程

假设我们已经安装好一版OpenCV,一般都默认安装在/usr/local下。如果需要安装另一个版本的OpenCV,就不能再安装到/usr/local,而是选择其他路径,否则会覆盖掉之前的版本。

1
2
3
4
5
6
7
8
9
10
11
12
# 运行cmake,注意CMAKE_INSTALL_PREFIX的路径选择
sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D WITH_V4L=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..
# 在已有opencv3.1.0安装在/usr/local/路径下的前提下,我选择将opencv3.4.5安装在/usr/local/opencv/opencv345/路径下
sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local/opencv/opencv345 -D WITH_TBB=ON -D WITH_V4L=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..

sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local/opencv/opencv452 -D WITH_TBB=ON -D WITH_V4L=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..
# 建议在make之前先查看CPU的核心数
nproc # 你可以根据你的核心数来调整make指令的参数,比如笔者的CPU核心数为12,则可以执行:
# make -j12

sudo make -j8 # 运行make
sudo make install # 运行install

报错处理

1
2
3
4
sudo make distclean  # 清除上一次make以及configure命令生成的文件
sudo make clean # 清除上一次make命令生成的文件
cd .. # 退出build文件夹
sudo rm -r build/ # 删除build文件夹,解决报错后重来一遍。

3.1.0

  1. icv_add_video_stream_FFMPEG

    1
    2
    3
    4
    // 在opencv-3.2.0/modules/videoio/src/cap_ffmpeg_impl.hpp 里最顶端添加:
    #define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
    #define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
    #define AVFMT_RAWPICTURE 0x0020

3.2.0

  1. /usr/include/c++/5/bits/c0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C 2011 standard.

    在根目录的CmakeLists.txt开头加上一句:

    1
    add_definitions(-std=c++11)

4. 环境变量配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
sudo gedit /etc/ld.so.conf.d/opencv.conf 
# 执行命令后打开的可能是一个空白的文件,直接添加上下面这句代码:
/usr/local/lib # /usr/local/opencv/opencv345/lib
# 其中/usr/local是opencv安装路径也就是makefile中指定的安装路径。
sudo ldconfig # 运行配置

sudo gedit /etc/ld.so.conf
# 在文件中加上一行
include /usr/local/lib # include /usr/local/opencv/opencv345/lib
# 其中/usr/local是opencv安装路径也就是makefile中指定的安装路径。
sudo ldconfig # 运行配置

sudo gedit /etc/bash.bashrc
# 在文件末尾加入:
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
# 或
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opencv/opencv345/lib/pkgconfig
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/opencv/opencv345/lib
# 如果命令行解释器Shell不是bash
exec bash # 将命令行从zsh切换为bash
source /etc/bash.bashrc
exec zsh # 重新运行zsh命令行工具
sudo updatedb # 更新数据库
# Reboot your machine and run following command to check installed version

也可以直接修改~/.bashrc或者~/.zshrc(用哪个终端就改哪个)?值得一试:

1
2
3
4
5
6
7
8
9
10
11
sudo gedit ~/.bashrc
# 或
sudo gedit ~/.zshrc

#OpenCV 3.4.5
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opencv/opencv345/lib/pkgconfig
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/opencv/opencv345/lib

source ~/.bashrc
# 或
source ~/.zshrc

我是都用了,反正只要路径设置正确,就算重复覆盖额外多余了,不会报错就行。

5. 多版本共存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sudo gedit /etc/bash.bashrc
# 或 取决于下面的语句你是放在哪里的
sudo gedit ~/.bashrc

# 注释掉其他版本,仅保留你现在想要用的版本即可。
#OpenCV_4.2.0
#export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opencv_4.2.0/lib/pkgconfig
#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/opencv_4.2.0/lib

#OpenCV_3.4.6
#export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opencv_3.4.6/lib/pkgconfig
#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/opencv_3.4.6/lib

#OpenCV_2.4.9
#export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opencv_2.4.9/lib/pkgconfig
#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/opencv_2.4.9/lib

source ~/.bashrc

6. 安装检查

1
2
3
4
pkg-config --modversion opencv  # 查询版本
pkg-config --cflags opencv # 得到opencv的安装路径
# -> -I/usr/local/include/opencv -I/usr/local/include
pkg-config --cflags opencv4 # 附加:得到opencv4的安装路径

7. 验证配置结果

任意目录创建一个test.cpp文件,写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "opencv.hpp"
// 如果报错 fatal error: opencv.hpp: 没有那个文件或目录
// 则改为 #include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
cout << "OpenCV version : " << CV_VERSION << endl;
cout << "Major version : " << CV_MAJOR_VERSION << endl;
cout << "Minor version : " << CV_MINOR_VERSION << endl;
cout << "Subminor version : " << CV_SUBMINOR_VERSION << endl;
}

使用命令行在其文件夹下执行:

1
2
3
4
5
# 编译test.cpp程序,并生成可执行文件
g++ -std=c++11 test.cpp 'pkg-config --libs --cflags opencv4' -o result

# 执行可执行文件
./result

我这么做会报错,所以,自己在这里是在根目录下新建文件CMakeLists.txt,写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cmake_minimum_required(VERSION 2.8) 
# 指定OpenCVConfig.cmake文件的目录
set(OpenCV_DIR /usr/local/opencv/opencv345/share/OpenCV)
project(test)
# 用find package指令找到OpenCV包
find_package(OpenCV REQUIRED)
# 指定OpenCV的头文件目录
include_directories(${OpenCV_INCLUDE_DIRS})

add_executable(test test.cpp)
# 将编译生成的文件与OpenCV的动态库/静态库进行链接3
target_link_libraries(test ${OpenCV_LIBS})

# 打印OpenCV的信息
message(STATUS "opencv version: ${OpenCV_VERSION}")
message(STATUS "opencv lib: ${OpenCV_LIBS}")
message(STATUS "opencv include dir: ${OpenCV_INCLUDE_DIRS}")
message(STATUS "opencv config path: $[openCV_CONFIG_PATH}")

开始编译:

1
2
3
4
5
mkdir build
cd build
cmake ..
make -j8
./test

输出以下内容,即表明配置成功:

1
2
3
4
OpenCV version : 3.4.5
Major version : 3
Minor version : 4
Subminor version : 5

版本管理

方法1. 去掉cv_bridge,自行在CMakeLists.txt文件里指定OpenCV的路径

首先进行第一章安装的第4、5步。

后,编辑CMakeLists.txt文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 指定OpenCVConfig.cmake文件的目录
# 注意opencv安装目录下的/share/OpenCV
set(OpenCV_DIR /usr/local/share/OpenCV) # 默认安装在/usr/local/
set(OpenCV_DIR /usr/local/opencv/opencv345/share/OpenCV) # 自定义安装在/usr/local/opencv/opencv345的openv3.4.5
set(OpenCV_DIR /usr/local/opencv/opencv452/lib/cmake/opencv4)
# set(OpenCV_DIR /opt/ros/kinetic/share/OpenCV-3.3.1-dev)
# set(OpenCV_DIR /path/to/opencv/build)

# 用find package指令找到指定路径的OpenCV包
find_package(OpenCV REQUIRED)
# 指定OpenCV的头文件目录
include_directories(
......
${OpenCV_INCLUDE_DIRS}
......
)
# include_directories(${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})

# 将编译生成的文件与OpenCV的动态库/静态库进行链接
target_link_libraries(
......
${OpenCV_LIBS}
......
)

# 打印OpenCV的信息
message(STATUS "opencv version: ${OpenCV_VERSION}")
message(STATUS "opencv lib: ${OpenCV_LIBS}")
message(STATUS "opencv include dir: ${OpenCV_INCLUDE_DIRS}")
message(STATUS "opencv config path: $[openCV_CONFIG_PATH}")

如果编译时出现类似“Build error : undefined reference to cv_bridge::CvImage::toImageMsg() const”问题,可以尝试加入cv_bridge:

1
2
3
find_package(catkin REQUIRED COMPONENTS
cv_bridge
)

方法2. 对于ROS编译,可以修改cv_bridge的配置文件,使得cv_bridge去调用我们自己安装的OpenCV版本

首先进行第一章安装的第4、5步。

后,编辑CMakeLists.txt文件:

  1. 首先打开终端并进入cv_bridge配置文件所在目录,并用gedit指令打开该配置文件。

    1
    2
    3
    # cd /opt/ros/kinetic/share/cv_bridge/cmake/
    cd /opt/ros/melodic/share/cv_bridge/cmake/
    sudo gedit cv_bridgeConfig.cmake
  2. 然后按ctrl+f,输入关键词include找到以下内容并按图中的方式进行修改。Line 96左右。

    1
    2
    set(_include_dirs "include;/usr/local/opencv/opencv345/include/opencv2;/usr/local/opencv/opencv345/include/opencv;/usr/local/opencv/opencv345/include;/usr/include")
    set(_include_dirs "include;/usr/local/opencv/opencv320/include/opencv2;/usr/local/opencv/opencv320/include/opencv;/usr/local/opencv/opencv320/include;/usr/include")
  3. 将默认的OpenCV头文件目录替换后,再按ctrl+f并输入关键词libraries可以找到下图的区域,我们将其库文件也进行替换。Line 120左右。

    1
    2
    3
    4
    set(libraries "cv_bridge;/usr/local/opencv/opencv345/lib/libopencv_core.so.3.4.5;/usr/local/opencv/opencv345/lib/libopencv_imgproc.so.3.4.5;/usr/local/opencv/opencv345/lib/libopencv_imgcodecs.so.3.4.5;/usr/local/opencv/opencv345/lib/libopencv_calib3d.so.3.4.5;/usr/local/opencv/opencv345/lib/libopencv_highgui.so.3.4.5")
    set(libraries "cv_bridge;/usr/local/opencv/opencv320/lib/libopencv_core.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_imgproc.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_imgcodecs.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_calib3d.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_highgui.so.3.2.0")
    # OpenCV3.2.0库文件全
    set(libraries "cv_bridge;/usr/local/opencv/opencv320/lib/libopencv_calib3d.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_core.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_features2d.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_flann.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_highgui.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_imgcodecs.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_imgproc.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_ml.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_objdetect.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_photo.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_shape.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_stitching.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_superres.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_video.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_videoio.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_videostab.so.3.2.0;/usr/local/opencv/opencv320/lib/libopencv_viz.so.3.2.0")

    与头文件直接写入目录的方式不同,库文件是将文件本身也写入到配置文件中。而OpenCV的库文件有很多种,如下图所示。

    所以我们通常都将core、highgui、imgproc等常用的库文件写入到配置文件中,万一遇到要用的函数的库文件没有包含在配置文件中只要手动添加就可以。

  4. 修改cv_bridge的配置文件结束后,我们只需要在工程的CMakeLists.txt文件中的find_package加入cv_bridge就能够使用自己安装的OpenCV版本。不需要再像(1)方法中那样手动指定路径,而且这样做的好处就是能够使用cv_bridge。因为该包在OpenCV图像与ROS图像之间的转换中会经常用到。

    1
    find_package(cv_bridge)

    这时候再编译工程就可以通过了,但奇怪的是我们发现编译输出OpenCV的版本还是3.3.1并且配置文件还是默认的OpenCV3。

  5. 在终端下面用gedit打开cv_bridge-extras.cmake文件,对该文件进行修改,把自己安装的OpenCV对应的目录输入到文件中。

    1
    2
    cd /opt/ros/kinetic/share/cv_bridge/cmake/
    sudo gedit cv_bridge-extras.cmake
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    set(OpenCV_VERSION 3.4.5)
    set(OpenCV_VERSION_MAJOR 3)
    set(OpenCV_VERSION_MINOR 4)
    set(OpenCV_VERSION_PATCH 5)
    set(OpenCV_SHARED ON)
    set(OpenCV_CONFIG_PATH /usr/local/opencv/opencv345/share/OpenCV)
    set(OpenCV_INSTALL_PATH /usr/local/opencv/opencv345)
    set(OpenCV_LIB_COMPONENTS opencv_calib3d;opencv_core;opencv_features2d;opencv_flann;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_shape;opencv_stitching;opencv_superres;opencv_video;opencv_videoio;opencv_videostab;opencv_viz;opencv_aruco;opencv_bgsegm;opencv_bioinspired;opencv_ccalib;opencv_datasets;opencv_dpm;opencv_face;opencv_freetype;opencv_fuzzy;opencv_hdf;opencv_line_descriptor;opencv_optflow;opencv_phase_unwrapping;opencv_plot;opencv_reg;opencv_rgbd;opencv_saliency;opencv_stereo;opencv_structured_light;opencv_surface_matching;opencv_text;opencv_ximgproc;opencv_xobjdetect;opencv_xphoto)
    set(OpenCV_USE_MANGLED_PATHS FALSE)
    set(OpenCV_MODULES_SUFFIX )

    #set(OpenCV_VERSION 3.2.0)
    #set(OpenCV_VERSION_MAJOR 3)
    #set(OpenCV_VERSION_MINOR 2)
    #set(OpenCV_VERSION_PATCH 0)
    #set(OpenCV_SHARED ON)
    #set(OpenCV_CONFIG_PATH /usr/local/opencv/opencv320/share/OpenCV)
    #set(OpenCV_INSTALL_PATH /usr/local/opencv/opencv320)
    #set(OpenCV_LIB_COMPONENTS opencv_calib3d;opencv_core;opencv_features2d;opencv_flann;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_shape;opencv_stitching;opencv_superres;opencv_video;opencv_videoio;opencv_videostab;opencv_viz;opencv_aruco;opencv_bgsegm;opencv_bioinspired;opencv_ccalib;opencv_datasets;opencv_dpm;opencv_face;opencv_freetype;opencv_fuzzy;opencv_hdf;opencv_line_descriptor;opencv_optflow;opencv_phase_unwrapping;opencv_plot;opencv_reg;opencv_rgbd;opencv_saliency;opencv_stereo;opencv_structured_light;opencv_surface_matching;opencv_text;opencv_ximgproc;opencv_xobjdetect;opencv_xphoto)
    #set(OpenCV_USE_MANGLED_PATHS FALSE)
    #set(OpenCV_MODULES_SUFFIX )

    再运行catkin_make编译工程就可以发现版本号回到了我们指定的版本号。当然,这只是对于显示设置而已,对于使用OpenCV没有太大的影响。

方法3. cv_bridge与手动指定结合的方式

首先进行第一章安装的第4、5步。

后,编辑CMakeLists.txt文件:

  1. 我们打开自己安装的OpenCV的配置文件可以发现该配置文件主要是用来设置一些OpenCV的相关信息。

  2. 然后我们只要在cv_bridge中导入OpenCV的配置文件,那么只要使用cv_bridge的包就可以在ROS中使用相关的OpenCV版本。

  3. 同样从配置文件中得到库函数目录的路径。

    上面要注意的是在给系统赋予OpenCV头文件和库文件目录路径时,千万不要忘记把cv_bridge的头文件和库文件目录路径忘记赋给系统。

  4. 最后把cv_bridge配置文件设置OpenCV参数的选项注释掉。

  5. 完成。

主要参考链接

Ubuntu环境下ROS安装自己OPENCV版本

buntu配置OpenCV及多版本OpenCV共存


OpenCV的安装与版本管理
http://zeyulong.com/posts/75ff45ce/
作者
龙泽雨
发布于
2024年1月10日
许可协议