opencv3.3.1的剔除和显示(适用其他3以上版本)
ORB特征点检测+Latch描述子+汉明码暴力匹配+自己画线显示+左上右下方式
#include <iostream>
#include "opencv2/opencv_modules.hpp"
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
// If you find this code useful, please add a reference to the following paper in your work:
// Gil Levi and Tal Hassner, "LATCH: Learned Arrangements of Three Patch Codes", arXiv preprint arXiv:1501.03719, 15 Jan. 2015
using namespace std;
using namespace cv;
const float inlier_threshold = 2.5f; // Distance threshold to identify inliers
const float nn_match_ratio = 0.8f; // Nearest neighbor matching ratio
int main(int argc, char* argv[])
{
Mat img1 = imread("img1.ppm", IMREAD_GRAYSCALE);
Mat img2 = imread("img2.ppm", IMREAD_GRAYSCALE);
vector<KeyPoint> kpts1, kpts2;
Mat desc1, desc2;
Ptr<cv::ORB> orb_detector = cv::ORB::create(10000);
Ptr<xfeatures2d::LATCH> latch = xfeatures2d::LATCH::create();
orb_detector->detect(img1, kpts1);
latch->compute(img1, kpts1, desc1);
orb_detector->detect(img2, kpts2);
latch->compute(img2, kpts2, desc2);
//直接找1近邻,SIFT找匹配点
//FlannBasedMatcher matcher;
BFMatcher matcher(NORM_HAMMING);
vector< DMatch > matches1;
matcher.match(desc1, desc2, matches1);
vector<cv::Point2f> queryCoord;
vector<cv::Point2f> objectCoord;
for (int i = 0; i < matches1.size(); i++){
queryCoord.push_back((kpts1[matches1[i].queryIdx]).pt);
objectCoord.push_back((kpts2[matches1[i].trainIdx]).pt);
}
// 计算homography矩阵
Mat mask;
vector<Point2f> queryInliers;
//queryInliers[0].
vector<Point2f> sceneInliers;
Mat H = findFundamentalMat(queryCoord, objectCoord, mask, CV_FM_RANSAC);
//Mat H = findHomography( queryCoord, objectCoord, CV_RANSAC, 10, mask);
int inliers_cnt = 0, outliers_cnt = 0;
for (int j = 0; j < mask.rows; j++){
if (mask.at<uchar>(j) == 1){
queryInliers.push_back(queryCoord[j]);
sceneInliers.push_back(objectCoord[j]);
inliers_cnt++;
}
else {
outliers_cnt++;
}
}
Mat srcColorImage = imread("img1.ppm");
Mat dstColorImage = imread("img2.ppm");
vector<Point2f> srcPoints = queryInliers;
vector<Point2f> dstPoints = sceneInliers;
// Create a image for displaying mathing keypoints
Size sz = Size(srcColorImage.size().width + dstColorImage.size().width,
srcColorImage.size().height + dstColorImage.size().height);
Mat matchingImage = Mat::zeros(sz, CV_8UC3);
// Draw camera frame
Mat roi1 = Mat(matchingImage, Rect(0, 0, srcColorImage.size().width, srcColorImage.size().height));
srcColorImage.copyTo(roi1);
// Draw original image
Mat roi2 = Mat(matchingImage, Rect(srcColorImage.size().width, srcColorImage.size().height,
dstColorImage.size().width, dstColorImage.size().height));
dstColorImage.copyTo(roi2);
// Draw line between nearest neighbor pairs
for (int i = 0; i < (int)srcPoints.size(); ++i) {
Point2f pt1 = srcPoints[i];
Point2f pt2 = dstPoints[i];
Point2f from = pt1;
Point2f to = Point(srcColorImage.size().width + pt2.x, srcColorImage.size().height + pt2.y);
line(matchingImage, from, to, Scalar(0, 255, 255));
}
// Display mathing image
resize(matchingImage, matchingImage, Size(matchingImage.cols / 2, matchingImage.rows / 2));
namedWindow("111", CV_WINDOW_AUTOSIZE);
imshow("111", matchingImage);
waitKey();
return 0;
}
SIFT特征点检测+Latch描述子+汉明码暴力匹配+Lowe的ratio=0.8剔除+预先载入单应性矩阵H剔除+系统画线+左右展示(好像自带的只能左右展示)
直接放入灰度图和彩色图放入在算法里自己转换灰度图,结果好像不太一样,看来opencv自带的灰度化方式可能有不同,灰度化的质量影响特征点检测的质量
#include <iostream>
#include "opencv2/opencv_modules.hpp"
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/imgcodecs.hpp>
#include <vector>
// If you find this code useful, please add a reference to the following paper in your work:
// Gil Levi and Tal Hassner, "LATCH: Learned Arrangements of Three Patch Codes", arXiv preprint arXiv:1501.03719, 15 Jan. 2015
using namespace std;
using namespace cv;
const float inlier_threshold = 2.5f; // Distance threshold to identify inliers
const float nn_match_ratio = 0.8f; // Nearest neighbor matching ratio
int main(int argc, char* argv[])
{
/*
CommandLineParser parser(argc, argv,
"{@img1 | ../data/graf1.png | input image 1}"
"{@img2 | ../data/graf3.png | input image 2}"
"{@homography | ../data/H1to3p.xml | homography matrix}");
*/
Mat img1 = imread("img1.ppm");
Mat img2 = imread("img2.ppm");
//Mat img2 = imread("img5.ppm", IMREAD_GRAYSCALE);
//Mat img2 = imread("img6.ppm", IMREAD_GRAYSCALE);
/*
8.7976964e-01 3.1245438e-01 -3.9430589e+01
-1.8389418e-01 9.3847198e-01 1.5315784e+02
1.9641425e-04 -1.6015275e-05 1.0000000e+00
*/
/*
6.2544644e-01 5.7759174e-02 2.2201217e+02
2.2240536e-01 1.1652147e+00 - 2.5605611e+01
4.9212545e-04 - 3.6542424e-05 1.0000000e+00
* /
/*
4.2714590e-01 -6.7181765e-01 4.5361534e+02
4.4106579e-01 1.0133230e+00 -4.6534569e+01
5.1887712e-04 -7.8853731e-05 1.0000000e+00
*/
//Mat homography;
//FileStorage fs(parser.get<String>("@homography"), FileStorage::READ);
//fs.getFirstTopLevelNode() >> homography;
Mat homography1to2 = (Mat_<double>(3, 3) << 8.7976964e-01, 3.1245438e-01, -3.9430589e+01,
-1.8389418e-01, 9.3847198e-01, 1.5315784e+02,
1.9641425e-04, -1.6015275e-05, 1.0000000e+00);
Mat homography1to5 = (Mat_<double>(3, 3) << 6.2544644e-01, 5.7759174e-02, 2.2201217e+02,
2.2240536e-01, 1.1652147e+00, -2.5605611e+01,
4.9212545e-04, -3.6542424e-05, 1.0000000e+00);
Mat homography1to6 = (Mat_<double>(3, 3) << 4.2714590e-01, -6.7181765e-01, 4.5361534e+02,
4.4106579e-01, 1.0133230e+00, -4.6534569e+01,
5.1887712e-04, -7.8853731e-05, 1.0000000e+00);
Mat homography = homography1to2;
//Mat homography = homography1to5;
//Mat homography = homography1to6;
vector<KeyPoint> kpts1, kpts2;
Mat desc1, desc2;
//Ptr<cv::ORB> orb_detector = cv::ORB::create(10000);
Ptr<cv::xfeatures2d::SIFT> orb_detector = cv::xfeatures2d::SIFT::create(10000);
Ptr<xfeatures2d::LATCH> latch = xfeatures2d::LATCH::create();
orb_detector->detect(img1, kpts1);
latch->compute(img1, kpts1, desc1);
orb_detector->detect(img2, kpts2);
latch->compute(img2, kpts2, desc2);
BFMatcher matcher(NORM_HAMMING);
vector< vector<DMatch> > nn_matches;
matcher.knnMatch(desc1, desc2, nn_matches, 2);
vector<KeyPoint> matched1, matched2, inliers1, inliers2;
vector<DMatch> good_matches;
for (size_t i = 0; i < nn_matches.size(); i++) {
DMatch first = nn_matches[i][0];
float dist1 = nn_matches[i][0].distance;
float dist2 = nn_matches[i][1].distance;
if (dist1 < nn_match_ratio * dist2) {
matched1.push_back(kpts1[first.queryIdx]);
matched2.push_back(kpts2[first.trainIdx]);
}
}
for (unsigned i = 0; i < matched1.size(); i++) {
Mat col = Mat::ones(3, 1, CV_64F);
col.at<double>(0) = matched1[i].pt.x;
col.at<double>(1) = matched1[i].pt.y;
col = homography * col;
col /= col.at<double>(2);
double dist = sqrt(pow(col.at<double>(0) - matched2[i].pt.x, 2) +
pow(col.at<double>(1) - matched2[i].pt.y, 2));
if (dist < inlier_threshold) {
int new_i = static_cast<int>(inliers1.size());
inliers1.push_back(matched1[i]);
inliers2.push_back(matched2[i]);
good_matches.push_back(DMatch(new_i, new_i, 0));
}
}
Mat res;
/*drawMatches其中参数如下:
* img1 – 源图像1
* keypoints1 –源图像1的特征点.
* img2 – 源图像2.
* keypoints2 – 源图像2的特征点
* matches1to2 – 源图像1的特征点匹配源图像2的特征点[matches[i]] .
* outImg – 输出图像具体由flags决定.
* matchColor – 匹配的颜色(特征点和连线),若matchColor==Scalar::all(-1),颜色随机.
* singlePointColor – 单个点的颜色,即未配对的特征点,若matchColor==Scalar::all(-1),颜色随机.
matchesMask – Mask决定哪些点将被画出,若为空,则画出所有匹配点.
* flags – Fdefined by DrawMatchesFlags.
*/
/*flags其中参数如下:
struct CV_EXPORTS DrawMatchesFlags
{
enum{ DEFAULT = 0, //!< Output image matrix will be created (Mat::create),
//!< i.e. existing memory of output image may be reused.
//!< Two source image, matches and single keypoints will be drawn.
//!< For each keypoint only the center point will be drawn (without
//!< the circle around keypoint with keypoint size and orientation).
DRAW_OVER_OUTIMG = 1, //!< Output image matrix will not be created (Mat::create).
//!< Matches will be drawn on existing content of output image.
NOT_DRAW_SINGLE_POINTS = 2, //!< Single keypoints will not be drawn.
DRAW_RICH_KEYPOINTS = 4 //!< For each keypoint the circle around keypoint with keypoint size and
//!< orientation will be drawn.
};
};
*/
drawMatches(img1, inliers1, img2, inliers2, good_matches, res,
Scalar(0, 255, 255), Scalar(255, 0, 0), vector<char>(), 0);
imwrite("latch_result.png", res);
double inlier_ratio = inliers1.size() * 1.0 / matched1.size();
cout << "LATCH Matching Results" << endl;
cout << "*******************************" << endl;
cout << "# Keypoints 1: \t" << kpts1.size() << endl;
cout << "# Keypoints 2: \t" << kpts2.size() << endl;
cout << "# Matches: \t" << matched1.size() << endl;
cout << "# Inliers: \t" << inliers1.size() << endl;
cout << "# Inliers Ratio: \t" << inlier_ratio << endl;
cout << endl;
namedWindow("result", 2);
imshow("result", res);
waitKey();
return 0;
}
SIFT特征点检测+SIFT描述子+最近邻匹配+不剔除+计算代码运行时间(精确到小数点)
#include<ctime>
#include "ASiftDetector.h"
#include "utils.h"
#include "gms_Header.h"
#include "gms_matcher.h"
cv::Mat UpDownDrawInlier(const cv::Mat &queryImage, const cv::Mat &objectImage,
const vector<cv::KeyPoint> &qKeypoints, const vector<cv::KeyPoint> &objKeypoints,
const vector<cv::DMatch> &matches1,
const vector<cv::Point2f> &queryCoord, const vector<cv::Point2f> &objectCoord)
{
Size sz = Size(queryImage.size().width,
queryImage.size().height + objectImage.size().height);
Mat matchingImage = Mat::zeros(sz, CV_8UC3);
// 设置matchingImage的感兴趣区域大小并赋予原图
Mat roi1 = Mat(matchingImage, Rect(0, 0, queryImage.size().width, objectImage.size().height));
queryImage.copyTo(roi1);
Mat roi2 = Mat(matchingImage, Rect(0, queryImage.size().height, objectImage.size().width, objectImage.size().height));
objectImage.copyTo(roi2);
//画出点
for (int i = 0; i < (int)queryCoord.size(); ++i) {
Point2f pt1 = queryCoord[i];
Point2f pt2 = objectCoord[i];
Point2f from = pt1;
Point2f to = Point(pt2.x, queryImage.size().height + pt2.y);
line(matchingImage, from, to, Scalar(0, 255, 255));
}
return matchingImage;
}
int main(int argc, const char * argv[]) {
string imgFileName = "img1.JPG";
Mat queryImage;
queryImage = imread(imgFileName);
string objFileName = "img6.JPG";
Mat objectImage;
objectImage = imread(objFileName);
resize(queryImage, queryImage, Size(640, 480));
resize(objectImage, objectImage, Size(640, 480));
//imresize(queryImage, 480);
//imresize(objectImage, 480);
clock_t start, finish;
start = clock();
//检测SIFT特征点,方便后续做对比
Ptr<xfeatures2d::SIFT>feature = xfeatures2d::SIFT::create(2000);
vector<KeyPoint> qKeypoints;
feature->detect(queryImage, qKeypoints);
Mat qDescriptor;
feature->compute(queryImage, qKeypoints, qDescriptor);
vector<KeyPoint> objKeypoints;
feature->detect(objectImage, objKeypoints);
Mat objDesriptor;
feature->compute(objectImage, objKeypoints, objDesriptor);
FlannBasedMatcher matcher;
vector< DMatch > matches1;
matcher.match(qDescriptor, objDesriptor, matches1);
//点转换
vector<cv::Point2f> queryCoord;
vector<cv::Point2f> objectCoord;
for (int i = 0; i < matches1.size(); i++){
queryCoord.push_back((qKeypoints[matches1[i].queryIdx]).pt);
objectCoord.push_back((objKeypoints[matches1[i].trainIdx]).pt);
}
Mat result = UpDownDrawInlier(queryImage, objectImage, qKeypoints, objKeypoints,
matches1, queryCoord, objectCoord);
finish = clock();
double sift_time = (double)(finish - start) / CLOCKS_PER_SEC;
cout << setprecision(10) << fixed << "sift_time " << sift_time << endl;
namedWindow("matchingImage", CV_WINDOW_AUTOSIZE);
imshow("matchingImage", result);
waitKey();
return 0;
}
SIFT特征点检测+SIFT描述子+最近邻匹配+
劳氏算法剔除(最近邻与次紧邻的比值<ratio=0.6)
+计算代码运行时间(精确到小数点)
+内点比率(正确点比率)
#include<ctime>
#include "ASiftDetector.h"
#include "utils.h"
#include "gms_Header.h"
#include "gms_matcher.h"
cv::Mat UpDownDrawInlier(const cv::Mat &queryImage, const cv::Mat &objectImage,
const vector<cv::KeyPoint> &qKeypoints, const vector<cv::KeyPoint> &objKeypoints,
const vector<cv::DMatch> &matches1,
const vector<cv::Point2f> &queryCoord, const vector<cv::Point2f> &objectCoord)
{
Size sz = Size(queryImage.size().width,
queryImage.size().height + objectImage.size().height);
Mat matchingImage = Mat::zeros(sz, CV_8UC3);
// 设置matchingImage的感兴趣区域大小并赋予原图
Mat roi1 = Mat(matchingImage, Rect(0, 0, queryImage.size().width, objectImage.size().height));
queryImage.copyTo(roi1);
Mat roi2 = Mat(matchingImage, Rect(0, queryImage.size().height, objectImage.size().width, objectImage.size().height));
objectImage.copyTo(roi2);
//画出点
for (int i = 0; i < (int)queryCoord.size(); ++i) {
Point2f pt1 = queryCoord[i];
Point2f pt2 = objectCoord[i];
Point2f from = pt1;
Point2f to = Point(pt2.x, queryImage.size().height + pt2.y);
line(matchingImage, from, to, Scalar(0, 255, 255));
}
return matchingImage;
}
int main(int argc, const char * argv[]) {
string imgFileName = "img1.JPG";
Mat queryImage;
queryImage = imread(imgFileName);
string objFileName = "img6.JPG";
Mat objectImage;
objectImage = imread(objFileName);
resize(queryImage, queryImage, Size(640, 480));
resize(objectImage, objectImage, Size(640, 480));
//imresize(queryImage, 480);
//imresize(objectImage, 480);
clock_t start, finish;
start = clock();
//检测SIFT特征点,方便后续做对比
Ptr<xfeatures2d::SIFT>feature = xfeatures2d::SIFT::create(2000);
vector<KeyPoint> qKeypoints;
feature->detect(queryImage, qKeypoints);
Mat qDescriptor;
feature->compute(queryImage, qKeypoints, qDescriptor);
vector<KeyPoint> objKeypoints;
feature->detect(objectImage, objKeypoints);
Mat objDesriptor;
feature->compute(objectImage, objKeypoints, objDesriptor);
FlannBasedMatcher matcher;
vector< DMatch > matches1;
matcher.match(qDescriptor, objDesriptor, matches1);
//点转换
vector<cv::Point2f> queryCoord;
vector<cv::Point2f> objectCoord;
for (int i = 0; i < matches1.size(); i++){
queryCoord.push_back((qKeypoints[matches1[i].queryIdx]).pt);
objectCoord.push_back((objKeypoints[matches1[i].trainIdx]).pt);
}
// <5>根据劳氏算法(Lowe's algorithm),得到优秀的匹配点
vector< vector<DMatch> > nn_matches; // 匹配最近的两个特征点
// 通过最近邻与次紧邻的比值<nn_match_ratio 视为优秀匹配
matcher.knnMatch(qDescriptor, objDesriptor, nn_matches, 2);
const float nn_match_ratio = 0.8f; // Nearest neighbor matching ratio
vector<KeyPoint> matched1, matched2;
vector<DMatch> good_matches;
for (size_t i = 0; i < nn_matches.size(); i++) {
DMatch first = nn_matches[i][0];
float dist1 = nn_matches[i][0].distance;
float dist2 = nn_matches[i][1].distance;
if (dist1 < nn_match_ratio * dist2) {
good_matches.push_back(nn_matches[i][0]);
matched1.push_back(qKeypoints[first.queryIdx]);
matched2.push_back(objKeypoints[first.trainIdx]);
}
}
Mat result = UpDownDrawInlier(queryImage, objectImage, qKeypoints, objKeypoints,
matches1, queryCoord, objectCoord);
cout << " " << matches1.size() << endl;
//点转换
vector<cv::Point2f> queryCoord1;
vector<cv::Point2f> objectCoord1;
for (int i = 0; i < good_matches.size(); i++){
queryCoord1.push_back((qKeypoints[good_matches[i].queryIdx]).pt);
objectCoord1.push_back((objKeypoints[good_matches[i].trainIdx]).pt);
}
Mat result1 = UpDownDrawInlier(queryImage, objectImage, qKeypoints, objKeypoints,
good_matches, queryCoord1, objectCoord1);
cout << " " << good_matches.size() << endl;
finish = clock();
double sift_time = (double)(finish - start) / CLOCKS_PER_SEC;
cout << setprecision(10) << fixed << "sift_time " << sift_time << endl;
double inlier_ratio = (double)good_matches.size() / matches1.size();
cout << "匹配率 " << inlier_ratio << endl;
//namedWindow("matchingImage", CV_WINDOW_AUTOSIZE);
imshow("matchingImage", result);
imshow("matchingImage1", result1);
waitKey();
return 0;
}
SIFT特征点检测+SIFT描述子+最近邻匹配+单应映射关系剔除(H矩阵)
这里没有写的是opencv带的,没有按论文走,但是性质一样
两种实现方式:
1。使用mask剔除
#include<ctime>
#include "ASiftDetector.h"
#include "utils.h"
#include "gms_Header.h"
#include "gms_matcher.h"
cv::Mat UpDownDrawInlier(const cv::Mat &queryImage, const cv::Mat &objectImage,
const vector<cv::KeyPoint> &qKeypoints, const vector<cv::KeyPoint> &objKeypoints,
const vector<cv::DMatch> &matches1,
const vector<cv::Point2f> &queryCoord, const vector<cv::Point2f> &objectCoord)
{
Size sz = Size(queryImage.size().width,
queryImage.size().height + objectImage.size().height);
Mat matchingImage = Mat::zeros(sz, CV_8UC3);
// 设置matchingImage的感兴趣区域大小并赋予原图
Mat roi1 = Mat(matchingImage, Rect(0, 0, queryImage.size().width, objectImage.size().height));
queryImage.copyTo(roi1);
Mat roi2 = Mat(matchingImage, Rect(0, queryImage.size().height, objectImage.size().width, objectImage.size().height));
objectImage.copyTo(roi2);
//画出点
for (int i = 0; i < (int)queryCoord.size(); ++i) {
Point2f pt1 = queryCoord[i];
Point2f pt2 = objectCoord[i];
Point2f from = pt1;
Point2f to = Point(pt2.x, queryImage.size().height + pt2.y);
line(matchingImage, from, to, Scalar(0, 255, 255));
}
return matchingImage;
}
int main(int argc, const char * argv[]) {
string imgFileName = "img1.JPG";
Mat queryImage;
queryImage = imread(imgFileName);
string objFileName = "img6.JPG";
Mat objectImage;
objectImage = imread(objFileName);
resize(queryImage, queryImage, Size(640, 480));
resize(objectImage, objectImage, Size(640, 480));
//imresize(queryImage, 480);
//imresize(objectImage, 480);
clock_t start, finish;
start = clock();
//检测SIFT特征点,方便后续做对比
Ptr<xfeatures2d::SIFT>feature = xfeatures2d::SIFT::create(2000);
vector<KeyPoint> qKeypoints;
feature->detect(queryImage, qKeypoints);
Mat qDescriptor;
feature->compute(queryImage, qKeypoints, qDescriptor);
vector<KeyPoint> objKeypoints;
feature->detect(objectImage, objKeypoints);
Mat objDesriptor;
feature->compute(objectImage, objKeypoints, objDesriptor);
FlannBasedMatcher matcher;
vector< DMatch > matches1;
matcher.match(qDescriptor, objDesriptor, matches1);
//点转换
vector<cv::Point2f> queryCoord;
vector<cv::Point2f> objectCoord;
for (int i = 0; i < matches1.size(); i++){
queryCoord.push_back((qKeypoints[matches1[i].queryIdx]).pt);
objectCoord.push_back((objKeypoints[matches1[i].trainIdx]).pt);
}
// 计算homography矩阵
Mat mask;
Mat H = findHomography(queryCoord, objectCoord, CV_RANSAC, 10, mask);
// double minVal,maxVal; cv::minMaxIdx(ipts,&minVal,&maxVal);
// cv::Mat H = cv::findHomography(queryCoord,objectCoord,mask,CV_RANSAC, 0.004 * maxVal);
// threshold from Snavely07
// N. Snavely, S. Seitz, R. Szeliski, “Modeling the World from Internet Photo Collections, ”Int’l J.of Computer Vision, Vol. 80, No. 2, pp.189–210, 2008.
vector<Point2f> queryInliers;
vector<Point2f> sceneInliers;
int inliers_cnt = 0, outliers_cnt = 0;
for (int j = 0; j < mask.rows; j++){
if (mask.at<uchar>(j) == 1){
queryInliers.push_back(queryCoord[j]);
sceneInliers.push_back(objectCoord[j]);
inliers_cnt++;
}
else {
outliers_cnt++;
}
}
Mat result = UpDownDrawInlier(queryImage, objectImage, qKeypoints, objKeypoints,
matches1, queryInliers, sceneInliers);
cout << "最近邻匹配特征点数 " << matches1.size() << endl;
cout << "内点数目 " << inliers_cnt << endl;
cout << "外点数目 " << outliers_cnt << endl;
finish = clock();
double sift_time = (double)(finish - start) / CLOCKS_PER_SEC;
cout << setprecision(10) << fixed << "sift_time " << sift_time << endl;
//double inlier_ratio = (double)good_matches.size() / matches1.size();
//cout << "匹配率 " << inlier_ratio << endl;
imshow("matchingImage", result);
imwrite("B1.jpg", result);
waitKey();
return 0;
}
2。使用[x y 1] * H 的方式剔除
#include<ctime>
#include "ASiftDetector.h"
#include "utils.h"
#include "gms_Header.h"
#include "gms_matcher.h"
cv::Mat UpDownDrawInlier(const cv::Mat &queryImage, const cv::Mat &objectImage,
const vector<cv::KeyPoint> &qKeypoints, const vector<cv::KeyPoint> &objKeypoints,
const vector<cv::DMatch> &matches1,
const vector<cv::Point2f> &queryCoord, const vector<cv::Point2f> &objectCoord)
{
Size sz = Size(queryImage.size().width,
queryImage.size().height + objectImage.size().height);
Mat matchingImage = Mat::zeros(sz, CV_8UC3);
// 设置matchingImage的感兴趣区域大小并赋予原图
Mat roi1 = Mat(matchingImage, Rect(0, 0, queryImage.size().width, objectImage.size().height));
queryImage.copyTo(roi1);
Mat roi2 = Mat(matchingImage, Rect(0, queryImage.size().height, objectImage.size().width, objectImage.size().height));
objectImage.copyTo(roi2);
//画出点
for (int i = 0; i < (int)queryCoord.size(); ++i) {
Point2f pt1 = queryCoord[i];
Point2f pt2 = objectCoord[i];
Point2f from = pt1;
Point2f to = Point(pt2.x, queryImage.size().height + pt2.y);
line(matchingImage, from, to, Scalar(0, 255, 255));
}
return matchingImage;
}
int main(int argc, const char * argv[]) {
string imgFileName = "img1.JPG";
Mat queryImage;
queryImage = imread(imgFileName);
string objFileName = "img6.JPG";
Mat objectImage;
objectImage = imread(objFileName);
resize(queryImage, queryImage, Size(640, 480));
resize(objectImage, objectImage, Size(640, 480));
//imresize(queryImage, 480);
//imresize(objectImage, 480);
clock_t start, finish;
start = clock();
//检测SIFT特征点,方便后续做对比
Ptr<xfeatures2d::SIFT>feature = xfeatures2d::SIFT::create(2000);
vector<KeyPoint> qKeypoints;
feature->detect(queryImage, qKeypoints);
Mat qDescriptor;
feature->compute(queryImage, qKeypoints, qDescriptor);
vector<KeyPoint> objKeypoints;
feature->detect(objectImage, objKeypoints);
Mat objDesriptor;
feature->compute(objectImage, objKeypoints, objDesriptor);
FlannBasedMatcher matcher;
vector< DMatch > matches1;
matcher.match(qDescriptor, objDesriptor, matches1);
//点转换
vector<cv::Point2f> queryCoord;
vector<cv::Point2f> objectCoord;
for (int i = 0; i < matches1.size(); i++){
queryCoord.push_back((qKeypoints[matches1[i].queryIdx]).pt);
objectCoord.push_back((objKeypoints[matches1[i].trainIdx]).pt);
}
// 计算homography矩阵
vector<cv::Point2f> queryInliers;
vector<cv::Point2f> sceneInliers;
const float inlier_threshold = 2.8f; // Distance threshold to identify inliers
Mat mask;
Mat H = findHomography(queryCoord, objectCoord, CV_RANSAC, 10, mask);
Mat H_inv = H.inv();
int inliers_cnt = 0, outliers_cnt = 0;
for (unsigned i = 0; i < queryCoord.size(); i++) {
Mat col = Mat::ones(3, 1, CV_64F);
col.at<double>(0) = queryCoord[i].x;
col.at<double>(1) = queryCoord[i].y;
col = H * col;
col /= col.at<double>(2); // 将[x*, y*, #] 转换为 [x*/#, y*/#, 1]
double dist = sqrt(pow(col.at<double>(0) - objectCoord[i].x, 2) +
pow(col.at<double>(1) - objectCoord[i].y, 2)); // 计算误差-欧式距离
if (dist < inlier_threshold) { // 误差小于阈值
queryInliers.push_back(queryCoord[i]);
sceneInliers.push_back(objectCoord[i]);
inliers_cnt++;
}
}
outliers_cnt = matches1.size() - inliers_cnt;
Mat result = UpDownDrawInlier(queryImage, objectImage, qKeypoints, objKeypoints,
matches1, queryInliers, sceneInliers);
cout << "最近邻匹配特征点数 " << matches1.size() << endl;
cout << "内点数目 " << inliers_cnt << endl;
cout << "外点数目 " << outliers_cnt << endl;
finish = clock();
double sift_time = (double)(finish - start) / CLOCKS_PER_SEC;
cout << setprecision(10) << fixed << "sift_time " << sift_time << endl;
//double inlier_ratio = (double)good_matches.size() / matches1.size();
//cout << "匹配率 " << inlier_ratio << endl;
imshow("matchingImage", result);
imwrite("B1.jpg", result);
waitKey();
return 0;
}
SIFT特征点检测+SIFT描述子+最近邻匹配+极线约束关系剔除(F矩阵)
F也有两种
1。mask
#include<ctime>
#include "ASiftDetector.h"
#include "utils.h"
#include "gms_Header.h"
#include "gms_matcher.h"
cv::Mat UpDownDrawInlier(const cv::Mat &queryImage, const cv::Mat &objectImage,
const vector<cv::KeyPoint> &qKeypoints, const vector<cv::KeyPoint> &objKeypoints,
const vector<cv::DMatch> &matches1,
const vector<cv::Point2f> &queryCoord, const vector<cv::Point2f> &objectCoord)
{
Size sz = Size(queryImage.size().width,
queryImage.size().height + objectImage.size().height);
Mat matchingImage = Mat::zeros(sz, CV_8UC3);
// 设置matchingImage的感兴趣区域大小并赋予原图
Mat roi1 = Mat(matchingImage, Rect(0, 0, queryImage.size().width, objectImage.size().height));
queryImage.copyTo(roi1);
Mat roi2 = Mat(matchingImage, Rect(0, queryImage.size().height, objectImage.size().width, objectImage.size().height));
objectImage.copyTo(roi2);
//画出点
for (int i = 0; i < (int)queryCoord.size(); ++i) {
Point2f pt1 = queryCoord[i];
Point2f pt2 = objectCoord[i];
Point2f from = pt1;
Point2f to = Point(pt2.x, queryImage.size().height + pt2.y);
line(matchingImage, from, to, Scalar(0, 255, 255));
}
return matchingImage;
}
int main(int argc, const char * argv[]) {
string imgFileName = "img1.JPG";
Mat queryImage;
queryImage = imread(imgFileName);
string objFileName = "img6.JPG";
Mat objectImage;
objectImage = imread(objFileName);
resize(queryImage, queryImage, Size(640, 480));
resize(objectImage, objectImage, Size(640, 480));
//imresize(queryImage, 480);
//imresize(objectImage, 480);
clock_t start, finish;
start = clock();
//检测SIFT特征点,方便后续做对比
Ptr<xfeatures2d::SIFT>feature = xfeatures2d::SIFT::create(2000);
vector<KeyPoint> qKeypoints;
feature->detect(queryImage, qKeypoints);
Mat qDescriptor;
feature->compute(queryImage, qKeypoints, qDescriptor);
vector<KeyPoint> objKeypoints;
feature->detect(objectImage, objKeypoints);
Mat objDesriptor;
feature->compute(objectImage, objKeypoints, objDesriptor);
FlannBasedMatcher matcher;
vector< DMatch > matches1;
matcher.match(qDescriptor, objDesriptor, matches1);
//点转换
vector<cv::Point2f> queryCoord;
vector<cv::Point2f> objectCoord;
for (int i = 0; i < matches1.size(); i++){
queryCoord.push_back((qKeypoints[matches1[i].queryIdx]).pt);
objectCoord.push_back((objKeypoints[matches1[i].trainIdx]).pt);
}
// 计算homography矩阵
vector<cv::Point2f> queryInliers;
vector<cv::Point2f> sceneInliers;
const float inlier_threshold = 2.8f; // Distance threshold to identify inliers
Mat mask;
double minVal, maxVal;
cv::minMaxIdx(queryCoord, &minVal, &maxVal);
Mat F = findFundamentalMat(queryCoord, objectCoord, FM_RANSAC, 0.006 * maxVal, 0.99, mask); //threshold from [Snavely07 4.1]
// N. Snavely, S. Seitz, R. Szeliski, “Modeling the World from Internet Photo Collections, ”Int’l J.of Computer Vision, Vol. 80, No. 2, pp.189–210, 2008.
Mat F_inv = F.inv();
int inliers_cnt = 0, outliers_cnt = 0;
for (int j = 0; j < mask.rows; j++){
if (mask.at<uchar>(j) == 1){
queryInliers.push_back(queryCoord[j]);
sceneInliers.push_back(objectCoord[j]);
inliers_cnt++;
}
else {
outliers_cnt++;
}
}
outliers_cnt = matches1.size() - inliers_cnt;
Mat result = UpDownDrawInlier(queryImage, objectImage, qKeypoints, objKeypoints,
matches1, queryInliers, sceneInliers);
cout << "最近邻匹配特征点数 " << matches1.size() << endl;
cout << "内点数目 " << inliers_cnt << endl;
cout << "外点数目 " << outliers_cnt << endl;
finish = clock();
double sift_time = (double)(finish - start) / CLOCKS_PER_SEC;
cout << setprecision(10) << fixed << "sift_time " << sift_time << endl;
//double inlier_ratio = (double)good_matches.size() / matches1.size();
//cout << "匹配率 " << inlier_ratio << endl;
imshow("matchingImage", result);
imwrite("B1.jpg", result);
waitKey();
return 0;
}
参数的选择
论文:
Modeling the World from Internet Photo Collections
https://download.csdn.net/download/baidu_40840693/10732806
2。PFP*=0 1*3 * 3*3 3*1 = 0
这里暂时不知道怎么写,只能最后的值dist<0.01
#include<ctime>
#include "ASiftDetector.h"
#include "utils.h"
#include "gms_Header.h"
#include "gms_matcher.h"
cv::Mat UpDownDrawInlier(const cv::Mat &queryImage, const cv::Mat &objectImage,
const vector<cv::KeyPoint> &qKeypoints, const vector<cv::KeyPoint> &objKeypoints,
const vector<cv::DMatch> &matches1,
const vector<cv::Point2f> &queryCoord, const vector<cv::Point2f> &objectCoord)
{
Size sz = Size(queryImage.size().width,
queryImage.size().height + objectImage.size().height);
Mat matchingImage = Mat::zeros(sz, CV_8UC3);
// 设置matchingImage的感兴趣区域大小并赋予原图
Mat roi1 = Mat(matchingImage, Rect(0, 0, queryImage.size().width, objectImage.size().height));
queryImage.copyTo(roi1);
Mat roi2 = Mat(matchingImage, Rect(0, queryImage.size().height, objectImage.size().width, objectImage.size().height));
objectImage.copyTo(roi2);
//画出点
for (int i = 0; i < (int)queryCoord.size(); ++i) {
Point2f pt1 = queryCoord[i];
Point2f pt2 = objectCoord[i];
Point2f from = pt1;
Point2f to = Point(pt2.x, queryImage.size().height + pt2.y);
line(matchingImage, from, to, Scalar(0, 255, 255));
}
return matchingImage;
}
int main(int argc, const char * argv[]) {
string imgFileName = "img1.JPG";
Mat queryImage;
queryImage = imread(imgFileName);
string objFileName = "img6.JPG";
Mat objectImage;
objectImage = imread(objFileName);
resize(queryImage, queryImage, Size(640, 480));
resize(objectImage, objectImage, Size(640, 480));
//imresize(queryImage, 480);
//imresize(objectImage, 480);
clock_t start, finish;
start = clock();
//检测SIFT特征点,方便后续做对比
Ptr<xfeatures2d::SIFT>feature = xfeatures2d::SIFT::create(2000);
vector<KeyPoint> qKeypoints;
feature->detect(queryImage, qKeypoints);
Mat qDescriptor;
feature->compute(queryImage, qKeypoints, qDescriptor);
vector<KeyPoint> objKeypoints;
feature->detect(objectImage, objKeypoints);
Mat objDesriptor;
feature->compute(objectImage, objKeypoints, objDesriptor);
FlannBasedMatcher matcher;
vector< DMatch > matches1;
matcher.match(qDescriptor, objDesriptor, matches1);
//点转换
vector<cv::Point2f> queryCoord;
vector<cv::Point2f> objectCoord;
for (int i = 0; i < matches1.size(); i++){
queryCoord.push_back((qKeypoints[matches1[i].queryIdx]).pt);
objectCoord.push_back((objKeypoints[matches1[i].trainIdx]).pt);
}
// 计算homography矩阵
vector<cv::Point2f> queryInliers;
vector<cv::Point2f> sceneInliers;
Mat mask;
double minVal, maxVal;
cv::minMaxIdx(queryCoord, &minVal, &maxVal);
Mat F = findFundamentalMat(queryCoord, objectCoord, FM_RANSAC, 0.006 * maxVal, 0.99, mask); //threshold from [Snavely07 4.1]
// N. Snavely, S. Seitz, R. Szeliski, “Modeling the World from Internet Photo Collections, ”Int’l J.of Computer Vision, Vol. 80, No. 2, pp.189–210, 2008.
Mat F_inv = F.inv();
int inliers_cnt = 0, outliers_cnt = 0;
for (unsigned i = 0; i < queryCoord.size(); i++) {
Mat row = Mat::ones(1, 3, CV_64F);
row.at<double>(0) = queryCoord[i].x;
row.at<double>(1) = queryCoord[i].y;
row = row*F;
Mat col = Mat::ones(3, 1, CV_64F);
col.at<double>(0) = objectCoord[i].x;
col.at<double>(1) = objectCoord[i].y;
Mat dist = row*col;
double distF = dist.at<double>(0);
distF = sqrt(pow(distF, 2));
if (distF < 0.01) { // 误差小于阈值
queryInliers.push_back(queryCoord[i]);
sceneInliers.push_back(objectCoord[i]);
inliers_cnt++;
}
}
outliers_cnt = matches1.size() - inliers_cnt;
Mat result = UpDownDrawInlier(queryImage, objectImage, qKeypoints, objKeypoints,
matches1, queryInliers, sceneInliers);
cout << "最近邻匹配特征点数 " << matches1.size() << endl;
cout << "内点数目 " << inliers_cnt << endl;
cout << "外点数目 " << outliers_cnt << endl;
finish = clock();
double sift_time = (double)(finish - start) / CLOCKS_PER_SEC;
cout << setprecision(10) << fixed << "sift_time " << sift_time << endl;
//double inlier_ratio = (double)good_matches.size() / matches1.size();
//cout << "匹配率 " << inlier_ratio << endl;
imshow("matchingImage", result);
imwrite("B1.jpg", result);
waitKey();
return 0;
}
根据F矩阵画出极线
#include<ctime>
#include "ASiftDetector.h"
#include "utils.h"
#include "gms_Header.h"
#include "gms_matcher.h"
cv::Mat UpDownDrawInlier(const cv::Mat &queryImage, const cv::Mat &objectImage,
const vector<cv::KeyPoint> &qKeypoints, const vector<cv::KeyPoint> &objKeypoints,
const vector<cv::DMatch> &matches1,
const vector<cv::Point2f> &queryCoord, const vector<cv::Point2f> &objectCoord)
{
Size sz = Size(queryImage.size().width,
queryImage.size().height + objectImage.size().height);
Mat matchingImage = Mat::zeros(sz, CV_8UC3);
// 设置matchingImage的感兴趣区域大小并赋予原图
Mat roi1 = Mat(matchingImage, Rect(0, 0, queryImage.size().width, objectImage.size().height));
queryImage.copyTo(roi1);
Mat roi2 = Mat(matchingImage, Rect(0, queryImage.size().height, objectImage.size().width, objectImage.size().height));
objectImage.copyTo(roi2);
//画出点
for (int i = 0; i < (int)queryCoord.size(); ++i) {
Point2f pt1 = queryCoord[i];
Point2f pt2 = objectCoord[i];
Point2f from = pt1;
Point2f to = Point(pt2.x, queryImage.size().height + pt2.y);
line(matchingImage, from, to, Scalar(0, 255, 255));
}
return matchingImage;
}
int main(int argc, const char * argv[]) {
string imgFileName = "img1.JPG";
Mat queryImage;
queryImage = imread(imgFileName);
string objFileName = "img3.JPG";
Mat objectImage;
objectImage = imread(objFileName);
resize(queryImage, queryImage, Size(640, 480));
resize(objectImage, objectImage, Size(640, 480));
//imresize(queryImage, 480);
//imresize(objectImage, 480);
clock_t start, finish;
start = clock();
//检测SIFT特征点,方便后续做对比
Ptr<xfeatures2d::SIFT>feature = xfeatures2d::SIFT::create(2000);
vector<KeyPoint> qKeypoints;
feature->detect(queryImage, qKeypoints);
Mat qDescriptor;
feature->compute(queryImage, qKeypoints, qDescriptor);
vector<KeyPoint> objKeypoints;
feature->detect(objectImage, objKeypoints);
Mat objDesriptor;
feature->compute(objectImage, objKeypoints, objDesriptor);
FlannBasedMatcher matcher;
vector< DMatch > matches1;
matcher.match(qDescriptor, objDesriptor, matches1);
//点转换
vector<cv::Point2f> queryCoord;
vector<cv::Point2f> objectCoord;
for (int i = 0; i < matches1.size(); i++){
queryCoord.push_back((qKeypoints[matches1[i].queryIdx]).pt);
objectCoord.push_back((objKeypoints[matches1[i].trainIdx]).pt);
}
// 计算homography矩阵
vector<cv::Point2f> queryInliers;
vector<cv::Point2f> sceneInliers;
Mat mask;
double minVal, maxVal;
cv::minMaxIdx(queryCoord, &minVal, &maxVal);
Mat F = findFundamentalMat(queryCoord, objectCoord, FM_RANSAC, 0.006 * maxVal, 0.99, mask); //threshold from [Snavely07 4.1]
// N. Snavely, S. Seitz, R. Szeliski, “Modeling the World from Internet Photo Collections, ”Int’l J.of Computer Vision, Vol. 80, No. 2, pp.189–210, 2008.
//Mat F_inv = F.inv(); //求逆
Mat F_transpose = F.t(); //转置
int inliers_cnt = 0, outliers_cnt = 0;
for (unsigned i = 0; i < queryCoord.size(); i++) {
Mat row = Mat::ones(1, 3, CV_64F);
row.at<double>(0) = queryCoord[i].x;
row.at<double>(1) = queryCoord[i].y;
row = row*F;
Mat col = Mat::ones(3, 1, CV_64F);
col.at<double>(0) = objectCoord[i].x;
col.at<double>(1) = objectCoord[i].y;
Mat dist = row*col;
double distF = dist.at<double>(0);
distF = sqrt(pow(distF, 2));
if (distF < 0.01) { // 误差小于阈值
queryInliers.push_back(queryCoord[i]);
sceneInliers.push_back(objectCoord[i]);
inliers_cnt++;
}
}
outliers_cnt = matches1.size() - inliers_cnt;
Mat result = UpDownDrawInlier(queryImage, objectImage, qKeypoints, objKeypoints,
matches1, queryInliers, sceneInliers);
cout << "最近邻匹配特征点数 " << matches1.size() << endl;
cout << "内点数目 " << inliers_cnt << endl;
cout << "外点数目 " << outliers_cnt << endl;
cv::Mat imagekeyPt1; // 左图
cv::Mat imagekeyPt2; // 右图
vector<KeyPoint> NewKeyP1;
vector<KeyPoint> NewKeyP2;
for (int i = 0; i < queryInliers.size(); i++){
KeyPoint key;
key.pt.x = queryInliers[i].x;
key.pt.y = queryInliers[i].y;
NewKeyP1.push_back(key);
key.pt.x = sceneInliers[i].x;
key.pt.y = sceneInliers[i].y;
NewKeyP2.push_back(key);
}
cv::drawKeypoints(queryImage, NewKeyP1, imagekeyPt1, cv::Scalar(255, 0, 0), cv::DrawMatchesFlags::DEFAULT);
cv::drawKeypoints(objectImage, NewKeyP2, imagekeyPt2, cv::Scalar(255, 0, 0), cv::DrawMatchesFlags::DEFAULT);
//使用基础矩阵 在对应图像上绘制外极线
std::vector<cv::Vec3f> lines1; //存储外极线
cv::computeCorrespondEpilines(cv::Mat(queryInliers), 1, F, lines1);//获取图像1中的二维特征点 在图像2中对应的外极线
for (std::vector<cv::Vec3f>::const_iterator it1 = lines1.begin();
it1 != lines1.end(); ++it1)
{
cv::line(imagekeyPt2,
cv::Point(0, -(*it1)[2] / (*it1)[1]),
cv::Point(imagekeyPt2.cols, -((*it1)[2] + (*it1)[0] * imagekeyPt2.cols) / (*it1)[1]),
cv::Scalar(0, 0, 255));
}
cv::namedWindow("Image2 Epilines");
cv::imshow("Image2 Epilines", imagekeyPt2);
//使用基础矩阵 在对应图像上绘制外极线
std::vector<cv::Vec3f> lines2; //存储外极线
cv::computeCorrespondEpilines(cv::Mat(sceneInliers), 2, F, lines2);//获取图像2中的二维特征点 在图像1中对应的外极线
// 这里存有疑问,computeCorrespondEpilines第二个参数为2,就自动是2对1,那么F是否还需要转置,这里需要看一下源代码才知道
for (std::vector<cv::Vec3f>::const_iterator it2 = lines2.begin();
it2 != lines2.end(); ++it2)
{
cv::line(imagekeyPt1,
cv::Point(0, -(*it2)[2] / (*it2)[1]),
cv::Point(imagekeyPt1.cols, -((*it2)[2] + (*it2)[0] * imagekeyPt1.cols) / (*it2)[1]),
cv::Scalar(0, 0, 255));
}
cv::namedWindow("Image1 Epilines");
cv::imshow("Image1 Epilines", imagekeyPt1);
finish = clock();
double sift_time = (double)(finish - start) / CLOCKS_PER_SEC;
cout << setprecision(10) << fixed << "sift_time " << sift_time << endl;
//double inlier_ratio = (double)good_matches.size() / matches1.size();
//cout << "匹配率 " << inlier_ratio << endl;
imshow("matchingImage", result);
imwrite("B1.jpg", result);
waitKey();
return 0;
}