烟雾环境下对RGB图SIFT特征提取,匹配及深度图有效值的影响
1 环境配置
1.1 opencv_contrib
已安装opencv3.4.7,如果需要SIFT,SURF等算法的时候,需要配置OpenCV扩展模块(opencv_contrib),版本需与原opencv版本一致。
OpenCV扩展模块(opencv_contrib)下载地址:
https://github.com/opencv/opencv_contrib/releases
编译过程:
cd <opencv_build_directory>
sudo make clean
cmake -DOPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules -DOPENCV_ENABLE_NONFREE=ON <opencv_main>
make
sudo make install
1.2 MathGL-数据可视化
sduo apt-get install mathgl
或者源码安装,参考链接:
http://mathgl.sourceforge.net/
http://mathgl.sourceforge.net/doc_en/
1.3 实验数据
实验室410采集的图片:
1.3.1 Left
1.3.2 Right
1.3.3 depth
1.4 实验环境
Ubuntu 18.04 + CLion
2 准备工作
2.1 对大批量图片文件名的导出
cd 到当前目录
ls left/ > left.txt
ls right/ > right.txt
ls depth/ > depth.txt
2.2 SIFT特征
contrastThreshold默认=0.04,对比阈值,过滤半均匀(低对比度)区域的弱特征,阈值越大,检测到的特征越少。
edgeThreshold默认=10, 边缘阈值,过滤掉边缘状特征,阈值越大,过滤掉的特征越少,更多的特征被保留。
考察以上两个阈值改变对SIFT特征提取与匹配的影响。
2.3 深度图
烟雾对深度图的影响从深度值无效点的比例、整张图的平均深度来观察。
3 SIFT特征提取与匹配
首先提取图像的sift特征点,再对相邻两帧的特征点做匹配,形成特征点对,最后计算图像变换的单应矩阵,RANSAC剔除误匹配点。
3.1 C++代码
// C++
#include<iostream>
#include<fstream>
#include<vector>
// OpenCV
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>
#include <opencv2/calib3d/calib3d.hpp>
//MathGL
#include <mgl2/mgl.h>
using namespace std;
using namespace cv;
vector<int> *siftFeature(double contrastThreshold, double edgeThreshold, const std::string &txtfilename,
const std::string &foldername) {
ifstream fin;
fin.open(txtfilename, ios::in);
if (!fin.is_open()) {
cerr << "文件打开失败!" << endl;
return 0;
}
std::string filename_1;
getline(fin, filename_1);
std::string filename_2;
//检测结果
vector<int> *num_feature = new vector<int>[2];
//检测到的特征点数量
vector<int> num_keyPoints;
//匹配的特征点对
vector<int> num_matches;
//读取待提取和匹配的两张图
Mat srcImg1 = imread(foldername + filename_1);
Mat srcImg2;
//定义SIFT特征检测类对象
cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create(1000, 3,
contrastThreshold, edgeThreshold,
1.6);
//定义KeyPoint变量
vector<KeyPoint> keyPoints1;
vector<KeyPoint> keyPoints2;
//特征点检测
sift->detect(srcImg1, keyPoints1);
//绘制特征点(关键点)
Mat feature_pic1, feature_pic2;
drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
/ drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
//计算特征点描述符 / 特征向量提取
Mat description1;
sift->compute(srcImg1, keyPoints1, description1);
Mat description2;
//计数
int count = 0;
num_keyPoints.push_back(keyPoints1.size());
while (getline(fin, filename_2)) {
srcImg2 = imread(foldername + filename_2);
//特征点检测
sift->detect(srcImg2, keyPoints2);
cout << "--------------------" << "特征提取" << "--------------------" << endl;
count++;
cout << "********************" << count << "********************" << endl;
cout << "SITF特征检测提取到的特征点数:" << keyPoints1.size() << endl;
count++;
cout << "********************" << count << "********************" << endl;
num_keyPoints.push_back(keyPoints2.size());
cout << "SITF特征检测提取到的特征点数:" << keyPoints2.size() << endl;
//绘制特征点(关键点)
drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
// drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
//显示结果
// imshow("feature1", feature_pic1);
//imshow("feature2", feature_pic2);
//计算特征点描述符 / 特征向量提取
sift->compute(srcImg2, keyPoints2, description2);
//进行BFMatch暴力匹配
//BruteForceMatcher<L2<float>>matcher; //实例化暴力匹配器
FlannBasedMatcher matcher; //实例化FLANN匹配器 //快速最近邻逼近搜索
vector<DMatch> matches; //定义匹配结果变量
matcher.match(description1, description2, matches); //实现描述符之间的匹配
double max_dist = 0;
double min_dist = 10000;
for (int i = 0; i < matches.size(); i++) {
double dist = matches[i].distance;
if (dist < min_dist)
min_dist = dist;
if (dist > max_dist)
max_dist = dist;
}
cout << "最大距离:" << max_dist << endl;
cout << "最小距离:" << min_dist << endl;
//筛选出较好的匹配点
vector<DMatch> good_matches;
double dThreshold = 0.5; //匹配的阈值,越大匹配的点数越多
for (int i = 0; i < matches.size(); i++) {
if (matches[i].distance < dThreshold * max_dist) {
good_matches.push_back(matches[i]);
}
}
/