Ubuntu 18.04 ROS-melodic 源码安装指定版本opencv 和 opencv_contrib 使用nonfree模块surf算法
Opencv版本 4.5.0Linux 版本 18.04ROS 版本 melodic (已安装)安装OpencvGithub下载源码https://github.com/opencv/opencv/releases (找到4.5.0版本)https://github.com/opencv/opencv_contrib/tree/4.5.0建立目录目录没有特殊要求, home 目录下即可mkdir
Opencv版本 4.5.0
Linux 版本 18.04
ROS 版本 melodic (已安装)
安装Opencv
-
Github下载源码
https://github.com/opencv/opencv/releases (找到4.5.0版本)
https://github.com/opencv/opencv_contrib/tree/4.5.0 -
建立目录
目录没有特殊要求, home 目录下即可
mkdir OpenCV
cd OpenCV
- 解压缩
tar -xf opencv-4.5.0.tar.gz
- 建立build目录
mkdir build
- 更改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'
- cmake配置
cmake ../opencv-4.5.0
cmake --build .
(如果要安装Contrib 可配置好后稍后统一执行步骤6)
(漫长的约俩小时的等待)
安装Open Contrib
- Github下载源码
https://github.com/opencv/opencv_contrib/tree/4.5.0
解压缩到之前建立的OpenCV - 进入之前的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
一直无法下载,需要手动下载这两个文件并改配置
- 手动下载 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文件夹下去 (文件夹位置随意)
- 修改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下载后保存的路径
- 手动下载 face_landmark_model.dat
- 配置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地址) - 修改hosts
sudo gedit /etc/hosts
添加以下内容保存即可 (IP地址查询后相应修改)
151.101.76.133 raw.githubusercontent.com
下载完毕后将 放到 刚才建立的install文件夹下去 - 配置 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记得替换为自己的用户名,路径记得替换为自己文件对应的路径
-
Ubuntu 20.04 安装可能会出现以下问题
fatal error: boostdesc_bgm.i: No such file or directory
参考解决:
安装OpenCV时提示缺少boostdesc_bgm.i文件的问题解决方案(附带百度云资源) -
重新按步骤2进行编译可以成功
10. 编译
在build目录下
cmake --build .
(再次漫长的等待3小时左右)
- 编译完成
有几个模块似乎编译出错,但我没用到就没管……😀 - 安装
在build目录下
sudo make install
卸载老版本OpenCV
如果不卸载,编译时还是会去找老版本opencv的东西,虽然能编译,但运行时会出错。
但是卸载时务必小心,搞不好就是重装系统的节奏(笑)
由于opencv是ros安装时自带的,ros是我用apt安装的,因此卸载opencv也只能用apt-get
参考 ubuntu利用apt-get卸载软件
- 使用
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
- 发现其中带core的包为‘libopencv-core3.2’注意不要使用purge,否则会把ROS整个删掉了
sudo apt-get remove libopencv-core3.2
- 输完指令后会出现如下输出
下列软件包将被【卸载】:
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
- 建立源代码和工作空间
建立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;
}
- 更改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}
)
- 编译运行
注意把图片放到运行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的使用
解决GitHub的raw.githubusercontent.com无法连接问题
How can I “Set OPENCV_ENABLE_NONFREE CMake option and rebuild the library in function ‘create’”?
更多推荐
所有评论(0)