Ubuntu 18.04 ROS-melodic 源码安装指定版本opencv 和 opencv_contrib 使用nonfree模块surf算法

Opencv版本 4.5.0
Linux 版本 18.04
ROS 版本 melodic (已安装)

安装Opencv

  1. Github下载源码
    https://github.com/opencv/opencv/releases (找到4.5.0版本)
    https://github.com/opencv/opencv_contrib/tree/4.5.0

  2. 建立目录
    目录没有特殊要求, home 目录下即可

mkdir OpenCV
cd OpenCV
  1. 解压缩
tar -xf opencv-4.5.0.tar.gz
  1. 建立build目录
mkdir build
  1. 更改OpenCV Cmakelists.txt 以应用Nonfree模块
gedit /home/usrname/<Opencv目录>/CmakeLists.txt

OCV_OPTION(OPENCV_ENABLE_NONFREE "Enable non-free algorithms" ON)
第212行 OFF改成ON,否则后续编译成功但是运行SURF算法时会报错:

error: (-213:The function/feature is not implemented) This algorithm is patented and is excluded in this configuration; Set OPENCV_ENABLE_NONFREE CMake option and rebuild the library in function 'create'

  1. cmake配置
cmake  ../opencv-4.5.0
cmake --build . 

(如果要安装Contrib 可配置好后稍后统一执行步骤6)
(漫长的约俩小时的等待)

安装Open Contrib

  1. Github下载源码
    https://github.com/opencv/opencv_contrib/tree/4.5.0
    解压缩到之前建立的OpenCV
  2. 进入之前的build目录进行cmake配置
cmake -DOPENCV_ENABLE_NONFREE:BOOL=ON -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.5.0/modules ../opencv-4.5.0

格式是

cmake -DOPENCV_ENABLE_NONFREE:BOOL=ON -DOPENCV_EXTRA_MODULES_PATH=<Opencv-Contrib源码目录>/modules <Opencv源码目录>
加入 -DOPENCV_ENABLE_NONFREE:BOOL=ON 是为了编译Nonfree 模块。可能因为之前cmake没有清除干净,我在opencv-4.5.0/CmakeLists.txt 里改了没效果。如果是第一次执行改了是有效果的。如果改了没效果,可以这里直接在命令行里。
如果cmake后输出的某一行是那么说明设置成功

Non-free algorithms:       YES

这一步可能会遇到卡在
-- IPPICV: Download: ippicv_2020_lnx_intel64_20191018_general.tgz

-- data: Download: face_landmark_model.dat
一直无法下载,需要手动下载这两个文件并改配置

  1. 手动下载 ippicv_2020_lnx_intel64_20191018_general.tgz
    地址:https://github.com/opencv/opencv_3rdparty/blob/ippicv/master_20191018/ippicv/ippicv_2020_lnx_intel64_20191018_general.tgz

然后放到home目录下新建的一个Install文件夹下去 (文件夹位置随意)

  1. 修改ippicv的配置文件
gedit /home/usrname/opencv_path/opencv/3rdparty/ippicv/ippicv.cmake 

将ippicv.cmake文件下的第42行替换为放文件的本地路径

    "file:///home/usrname/install/"
    #"https://raw.githubusercontent.com/opencv/opencv_3rdparty/${IPPICV_COMMIT}/ippicv/"
    #file后面的路径换成对应ippicv下载后保存的路径
  1. 手动下载 face_landmark_model.dat

https://raw.githubusercontent.com/opencv/opencv_3rdparty/8afa57abc8229d611c4937165d20e2a2d9fc5a12/face_landmark_model.dat

  1. 配置raw.githubusercontent.com ip
    步骤5可能会遇到 无法建立到 raw.githubusercontent.com 服务器的连接的问题。
    访问 https://site.ip138.com/raw.Githubusercontent.com/
    输入raw.githubusercontent.com
    查询得出IP地址为151.101.76.133 (可以ping不同IP的延时 选择最佳IP地址)
  2. 修改hosts
    sudo gedit /etc/hosts
    添加以下内容保存即可 (IP地址查询后相应修改)
    151.101.76.133 raw.githubusercontent.com
    在这里插入图片描述下载完毕后将 放到 刚才建立的install文件夹下去
  3. 配置 face模块的CmakeLists.txt
   gedit /home/usrname/OpenCV/opencv_contrib-4.5.0/modules/face/CMakeLists.txt
    #usrname 换成自己的用户名, <tool/opencv-3.4.0>换成自己opencv源码对应的文件夹

将CMakeLists.txt文件的第19行修改为本地路径,即将原来的网址修改为下载的文件保存的路径

   "file:///home/usrname/install/"
    #"https://raw.githubusercontent.com/opencv/opencv_3rdparty/${__commit_hash}/"
    # usrname记得替换为自己的用户名,路径记得替换为自己文件对应的路径
  1. Ubuntu 20.04 安装可能会出现以下问题
    fatal error: boostdesc_bgm.i: No such file or directory
    参考解决:
    安装OpenCV时提示缺少boostdesc_bgm.i文件的问题解决方案(附带百度云资源)

  2. 重新按步骤2进行编译可以成功
    在这里插入图片描述10. 编译
    在build目录下

cmake --build .

(再次漫长的等待3小时左右)

  1. 编译完成
    有几个模块似乎编译出错,但我没用到就没管……😀
  2. 安装
    在build目录下
sudo make install

卸载老版本OpenCV

如果不卸载,编译时还是会去找老版本opencv的东西,虽然能编译,但运行时会出错。

但是卸载时务必小心,搞不好就是重装系统的节奏(笑)

由于opencv是ros安装时自带的,ros是我用apt安装的,因此卸载opencv也只能用apt-get
参考 ubuntu利用apt-get卸载软件

  1. 使用 dpkg --get-selections | grep opencv 指令找到所有opencv相关包
libopencv-calib3d-dev:amd64			install
libopencv-calib3d3.2:amd64			install
libopencv-contrib-dev:amd64			install
libopencv-contrib3.2:amd64			install
libopencv-core-dev:amd64			install
libopencv-core3.2:amd64				install
libopencv-dev					install
libopencv-features2d-dev:amd64			install
libopencv-features2d3.2:amd64			install
libopencv-flann-dev:amd64			install
libopencv-flann3.2:amd64			install
libopencv-highgui-dev:amd64			install
libopencv-highgui3.2:amd64			install
libopencv-imgcodecs-dev:amd64			install
libopencv-imgcodecs3.2:amd64			install
libopencv-imgproc-dev:amd64			install
libopencv-imgproc3.2:amd64			install
libopencv-ml-dev:amd64				install
libopencv-ml3.2:amd64				install
libopencv-objdetect-dev:amd64			install
libopencv-objdetect3.2:amd64			install
libopencv-photo-dev:amd64			install
libopencv-photo3.2:amd64			install
libopencv-shape-dev:amd64			install
libopencv-shape3.2:amd64			install
libopencv-stitching-dev:amd64			install
libopencv-stitching3.2:amd64			install
libopencv-superres-dev:amd64			install
libopencv-superres3.2:amd64			install
libopencv-ts-dev:amd64				install
libopencv-video-dev:amd64			install
libopencv-video3.2:amd64			install
libopencv-videoio-dev:amd64			install
libopencv-videoio3.2:amd64			install
libopencv-videostab-dev:amd64			install
libopencv-videostab3.2:amd64			install
libopencv-viz-dev:amd64				install
libopencv-viz3.2:amd64				install
libopencv3.2-java				install
libopencv3.2-jni				install
python-opencv					install
ros-melodic-vision-opencv			install
  1. 发现其中带core的包为‘libopencv-core3.2’注意不要使用purge,否则会把ROS整个删掉了
sudo apt-get remove libopencv-core3.2
  1. 输完指令后会出现如下输出
 下列软件包将被【卸载】:
  libopencv-dev ros-melodic-camera-calibration ros-melodic-compressed-depth-image-transport
  ros-melodic-compressed-image-transport ros-melodic-costmap-converter ros-melodic-cv-bridge
  ros-melodic-cv-camera ros-melodic-depth-image-proc ros-melodic-desktop ros-melodic-desktop-full
  ros-melodic-gazebo-plugins ros-melodic-gazebo-ros-pkgs ros-melodic-image-geometry
  ros-melodic-image-pipeline ros-melodic-image-proc ros-melodic-image-publisher
  ros-melodic-image-rotate ros-melodic-image-transport-plugins ros-melodic-image-view
  ros-melodic-perception ros-melodic-rqt-common-plugins ros-melodic-rqt-image-view
  ros-melodic-simulators ros-melodic-stereo-image-proc ros-melodic-teb-local-planner
  ros-melodic-theora-image-transport ros-melodic-vision-opencv ros-melodic-viz
  ros-melodic-web-video-server
 升级了 0 个软件包,新安装了 0 个软件包,要卸载 29 个软件包,有 204 个软件包未被升级。
解压缩后将会空出 23.7 MB 的空间。
您希望继续执行吗? [Y/n]

也就是说ROS里依赖opencv的包全都会被删掉,咬咬牙选了Y,万幸,roscore还能运行,ros系统还在。
如果以后要用以上这些包,可以从源代码下载到工作空间中,并将opencv依赖改为现在用的版本,并重新编译:
解决cv_bridge与自己安装的opencv版本不兼容的问题
如果两个版本的opencv可以共存是最好了,自己写的程序调用Opencv4.5,ros自带程序继续调用opencv3.2。但是我没找到这种方法。

配置ROS CmakeLists.txt

  1. 建立源代码和工作空间

建立ROS 工作空间"opencv"和包"surf"

mkdir -p opencv/src
echo >>~/.bashrc source ~/opencv/devel/setup.bash
cd opencv/src
catkin_create_pkg surf std_msgs roscpp rospy cv_bridge
cd surf
touch book_detection.cpp

OpenCV SURF算法的Demo源程序参考了这篇文章,针对ROS进行了少量改动

#include "ros/ros.h"
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <sys/time.h>
#include <iostream>
//#include <opencv2/xfeatures2d/nonfree.hpp> //OpenCV 4.2.0 及之后版本
using namespace std;
int main(int argc, char **argv)
{
    ros::init(argc, argv, "book_detection");
    ros::NodeHandle n;
    cv::Mat imageL=cv::imread("img1.png");
    cv::Mat imageR=cv::imread("img2.png");
   
    //提取特征点方法
	//SIFT
	//cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();
	//cv::Ptr<cv::SIFT> sift = cv::SIFT::create(); //OpenCV 4.4.0 及之后版本
	//ORB
	//cv::Ptr<cv::ORB> orb = cv::ORB::create();
	//SURF
	cv::Ptr<cv::xfeatures2d::SURF> surf = cv::xfeatures2d::SURF::create();
	
	//特征点
	std::vector<cv::KeyPoint> keyPointL, keyPointR;
	//单独提取特征点
	surf->detect(imageL, keyPointL);
	surf->detect(imageR, keyPointR);

	//画特征点
	cv::Mat keyPointImageL;
	cv::Mat keyPointImageR;
	drawKeypoints(imageL, keyPointL, keyPointImageL, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
	drawKeypoints(imageR, keyPointR, keyPointImageR, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

	//显示窗口
	cv::namedWindow("KeyPoints of imageL");
	cv::namedWindow("KeyPoints of imageR");

	//显示特征点
	cv::imshow("KeyPoints of imageL", keyPointImageL);
	cv::imshow("KeyPoints of imageR", keyPointImageR);

	//特征点匹配
	cv::Mat despL, despR;
	//提取特征点并计算特征描述子
	surf->detectAndCompute(imageL, cv::Mat(), keyPointL, despL);
	surf->detectAndCompute(imageR, cv::Mat(), keyPointR, despR);

	//Struct for DMatch: query descriptor index, train descriptor index, train image index and distance between descriptors.
	//int queryIdx –>是测试图像的特征点描述符(descriptor)的下标,同时也是描述符对应特征点(keypoint)的下标。
	//int trainIdx –> 是样本图像的特征点描述符的下标,同样也是相应的特征点的下标。
	//int imgIdx –>当样本是多张图像的话有用。
	//float distance –>代表这一对匹配的特征点描述符(本质是向量)的欧氏距离,数值越小也就说明两个特征点越相像。
	std::vector<cv::DMatch> matches;

	//如果采用flannBased方法 那么 desp通过orb的到的类型不同需要先转换类型
	if (despL.type() != CV_32F || despR.type() != CV_32F)
	{
		despL.convertTo(despL, CV_32F);
		despR.convertTo(despR, CV_32F);
	}

	cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("FlannBased");
	matcher->match(despL, despR, matches);

	//计算特征点距离的最大值 
	double maxDist = 0; 
	for (int i = 0; i < despL.rows; i++)
	{
		double dist = matches[i].distance;
		if (dist > maxDist) 
			maxDist = dist;
	}

	//挑选好的匹配点
	std::vector< cv::DMatch > good_matches;
	for (int i = 0; i < despL.rows; i++)
	{
		if (matches[i].distance < 0.5*maxDist)
		{
			good_matches.push_back(matches[i]);
		}
	}

	cv::Mat imageOutput;
	cv::drawMatches(imageL, keyPointL, imageR, keyPointR, good_matches, imageOutput);

	cv::namedWindow("picture of matching");
	cv::imshow("picture of matching", imageOutput);
	cv::waitKey(0);
	return 0;
}
  1. 更改CmakeLists.txt
gedit ~/opencv/src/surf/CMakeLists.txt

在find_package(catkin REQUIRED COMPONENTS …)下一行添加

set(OpenCV_DIR /home/username/OpenCV/build)
find_package(OpenCV 4 REQUIRED)

目录名以opencv实际build目录为准

include_directories添加一行${OpenCV_INCLUDE_DIRS}

include_directories(
# include
  ${catkin_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
)

申明可执行文件
注意在target_link_libraries添加依赖${OpenCV_LIBS}

add_executable(book_detection src/book_detection.cpp)
add_dependencies(book_detection ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(book_detection
   ${catkin_LIBRARIES}
   ${OpenCV_LIBS}
 )

最终CmakeLists.txt类似于这样

cmake_minimum_required(VERSION 3.0.2)
project(surf)
find_package(catkin REQUIRED COMPONENTS
  cv_bridge
  roscpp
  rospy
  std_msgs
)
set(OpenCV_DIR /home/username/OpenCV/build) #你的build目录
find_package(OpenCV 4 REQUIRED)

catkin_package()
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
)
## Declare a C++ executable
add_executable(book_detection src/book_detection.cpp)

## Rename C++ executable without prefix
add_dependencies(book_detection ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
 target_link_libraries(book_detection
   ${catkin_LIBRARIES}
   ${OpenCV_LIBS}
 )

  1. 编译运行
    注意把图片放到运行rosrun的同一目录下
cd ~/opencv
catkin_make
source ~/opencv/devel/setup.bash
rosrun surf book_detection

原图

在这里插入图片描述在这里插入图片描述检测后图像
在这里插入图片描述
在这里插入图片描述特征点对应图像超大小了未传


兼容性问题

经过试验和查找资料,不同大版本的ROS和opencv之间兼容很困难。如果是不同程序里调用opencv3和opencv4,只通过topic交流可能还可以,但是如果是同一个程序里调用ros原版库(如cv_bridge),同时又使用opencv4里的东西(如QrcodeDetector)或原生ros-opencv里不带的模块(如nonfree),就很大概率无法使用,毕竟编译时同一个程序只可链接一个版本的libopencvcore。这种解决办法一般是将对应模块重新按照opencv4源码编译一下,或者直接将相关源代码copy到程序里(如cv_bridge的图像转换代码其实很简单)。但总之会遇到各种问题。

后来博主发现ROS-noetic支持opencv4,就干脆将系统重装升级了。然后发现ros自带的opencv还是各种问题,毕竟新版本不太稳定(掀桌)。但如果按照本文所说的方法编译安装最新版本的opencv,则是可以完美兼容ros源生代码使用的,不会出现第一段所说的问题。

因此最好还是安装大版本一致的opencv,小版本可以自由安装。


opencv 安装问题汇总

opencv 找不到 feature2d/test/test_detectors_regression.impl.hpp 文件

安装OpenCV时提示缺少boostdesc_bgm.i文件的问题解决方案(附带百度云资源)

源码编译opencv卡在IPPICV: Download: ippicv_2017u3_lnx_intel64_general_20170822.tgz解决办法

ubuntu16.04 安装opencv IPPICV 和 face_landmark_model.dat下载不下来的问题解决


其他参考资料

【OpenCV】OpenCV 4 下 SIFT、SURF的使用

OpencCV官方安装文档

解决GitHub的raw.githubusercontent.com无法连接问题

How can I “Set OPENCV_ENABLE_NONFREE CMake option and rebuild the library in function ‘create’”?

ubuntu利用apt-get卸载软件

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值