http://blog.csdn.net/zhounanzhaode/article/details/50302385
待会再看
http://blog.csdn.net/cosmispower/article/details/60601151
图像配准源码:
#include<iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void main()
{
double start, duration_ms;
cv::Mat mask1, mask2, imgshowcanny;
cv::Mat imgShow1, imgShow2, imgShow3;
// 声明并从data文件夹里读取两个rgb与深度图
cv::Mat rgb1 = cv::imread("D:\\python_opencv\\source_image\\1123\\1\\1.jpg", 0);
cv::Mat rgb2 = cv::imread("D:\\python_opencv\\source_image\\1123\\1\\2.jpg", 0);
vector< cv::KeyPoint > kp1, kp2; //关键点
mask1 = rgb1.clone();
//边缘检测
//cout << "Canny edge detection" << endl;
//mask1 = Mat::zeros(rgb1.size(), CV_8UC1);
//mask2 = Mat::zeros(rgb2.size(), CV_8UC1);
cv::Canny(mask1, mask1, 50, 200, 3);//检测Canny边缘,并将结果存入CV::Mat mask1中
//cv::Canny(rgb2, mask2, 50, 150, 3);
cv::Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
dilate(mask1, mask1, element);
cv::imwrite("F:/study work/Visual Odometry dev/VO_practice_2016.4/算法测试/KAZE算法/data/mask1.jpg", mask1);
imgshowcanny = mask1.clone();
cv::resize(imgshowcanny, imgshowcanny, cv::Size(imgshowcanny.cols, imgshowcanny.rows));
//特征检测算法:AKAZE
cv::Ptr<cv::AKAZE> akaze = AKAZE::create(AKAZE::DESCRIPTOR_MLDB, 0, 3, 0.001f, 4, 4, KAZE::DIFF_PM_G2);
cv::Mat descriptors_1, descriptors_2, descriptors_3, descriptors_4, descriptors_5, descriptors_6, descriptors_7, descriptors_8, descriptors_9, descriptors_10;
start = double(getTickCount());
akaze->detectAndCompute(rgb1, mask1, kp1, descriptors_1, false);
duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency();//计时
std::cout << "It took " << duration_ms << " ms to detect features in pic1 using AKAZE." << std::endl;
start = double(getTickCount());
akaze->detectAndCompute(rgb2, cv::Mat(), kp2, descriptors_2, false);
duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency();//计时
std::cout << "It took " << duration_ms << " ms to detect features in pic2 using AKAZE." << std::endl;
// 可视化, 显示特征点
cout << "Key points of two AKAZE images: " << kp1.size() << ", " << kp2.size() << endl;
cv::drawKeypoints(rgb1, kp1, imgShow1, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
cv::drawKeypoints(rgb2, kp2, imgShow2, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
cv::resize(imgShow2, imgShow2, cv::Size(imgShow2.cols, imgShow2.rows));
cv::resize(imgShow1, imgShow1, cv::Size(imgShow1.cols, imgShow1.rows));
cv::imshow("AKAZE_keypoints2", imgShow2);
cv::imshow("AKAZE_keypoints1", imgShow1);
//cv::waitKey(0); //暂停等待一个按键
//用Matcher匹配特征 :
BFMatcher bf_matcher;
FlannBasedMatcher flann_matcher;
cv::Ptr<cv::DescriptorMatcher> knn_matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
std::vector< DMatch > flann_matches;
std::vector< DMatch > bf_matches1;
std::vector< DMatch > knn_match;
std::vector< std::vector<cv::DMatch> > knn_matches1;
start = double(getTickCount());
bf_matcher.match(descriptors_1, descriptors_2, bf_matches1);
//flann_matcher.match(descriptors_1, descriptors_2, flann_matches);
duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency();//计时
std::cout << "It took " << duration_ms << " ms to do brutal-force-match on AKAZE features." << std::endl;
start = double(getTickCount());
knn_matcher->knnMatch(descriptors_1, descriptors_2, knn_matches1, 2);
duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency();//计时
std::cout << "It took " << duration_ms << " ms to do knn-match on AKAZE features." << std::endl;
//用RANSAC求取单应矩阵的方式去掉不可靠的BF匹配
vector< DMatch > inliers1, inliers2;
cout << "Computing homography (RANSAC)" << endl;
vector<Point2f> points1(bf_matches1.size());
vector<Point2f> points2(bf_matches1.size());
for (size_t i = 0; i < bf_matches1.size(); i++)
{
points1[i] = kp1[bf_matches1[i].queryIdx].pt;//queryIdx 指代的是匹配上的点在待匹配图像的Id
points2[i] = kp2[bf_matches1[i].trainIdx].pt;//trainIdx 指代的是匹配上的点在匹配图像的Id
}
//计算单应矩阵并找出inliers
vector<uchar> flag1(points1.size(), 0);
Mat H1 = findHomography(points1, points2, CV_RANSAC, 3.0, flag1);
Mat H2 = findHomography(points2, points1, CV_RANSAC, 3.0, flag1);
/*for (int i = 0; i < H1.rows; i++) {
for (int j = 0; j < H1.cols; j++) {
cout << "H1_value" << H1[i][i] << endl;
}
}*/
std::cout << H2 << std::endl;
//cout << H << endl << endl;
for (int i = 0; i < bf_matches1.size(); i++)
{
if (flag1[i])
{
inliers1.push_back(bf_matches1[i]);
}
}
cout << "AKAZE BF matches inliers size = " << inliers1.size() << endl;
//去掉不可靠的HAMMING-KNN匹配
vector< cv::DMatch > goodMatches1;
for (size_t i = 0; i < knn_matches1.size(); i++)
{
if (knn_matches1[i][0].distance < 0.3 *
knn_matches1[i][1].distance)
goodMatches1.push_back(knn_matches1[i][0]);
}
cout << "AKAZE good knn matches size = " << goodMatches1.size() << endl;
vector<Point2f> points3(goodMatches1.size());
vector<Point2f> points4(goodMatches1.size());
for (size_t i = 0; i < goodMatches1.size(); i++)
{
points3[i] = kp1[goodMatches1[i].queryIdx].pt;
points4[i] = kp2[goodMatches1[i].trainIdx].pt;
}
Mat H3 = findHomography(points4, points3, CV_RANSAC, 3.0, flag1);
cout << "H3" << H3 << endl;
cv::Mat imdst_2, imsrc_1, imsrc_2, warp_dst, imresult;
imsrc_1 = cv::imread("D:\\python_opencv\\source_image\\1123\\1\\1.jpg");
imsrc_2 = cv::imread("D:\\python_opencv\\source_image\\1123\\1\\2.jpg");
//warpAffine(im_src, warp_dst, H2, im_src.size());
warpPerspective(imsrc_2, imdst_2, H3, imsrc_2.size());
cv::Mat imsrc_1_, imdst_2_, imresult_;
imsrc_1.convertTo(imsrc_1_, CV_32F, 1.0 / 255.0);
imdst_2.convertTo(imdst_2_, CV_32F, 1.0 / 255.0);
imresult = (imsrc_1_ + imdst_2_) / 2;
//cv::resize(imresult, imresult, cv::Size(imgshowcanny.cols / 16, imgshowcanny.rows / 16));
cv::imshow("result", imresult);
imresult.convertTo(imresult_, CV_16U, 255.0);
cv::imwrite("D:\\opencv_cpp\\opencv_cpp\\source_images\\after_transactions\\after_transaction.jpg", imresult_);
// 可视化:显示匹配的特征
cv::Mat AKAZE_BF_imgMatches;
cv::Mat AKAZE_KNN_imgMatches;
筛选匹配,把距离太大的去掉
这里使用的准则是去掉大于四倍最小距离的匹配
//vector< cv::DMatch > goodMatches;
//double minDis = 9999;
//for (size_t i = 0; i<matches.size(); i++)
//{
// if (matches[i].distance < minDis)
// minDis = matches[i].distance;
//}
//for (size_t i = 0; i<matches.size(); i++)
//{
// if (matches[i].distance < 8 * minDis)
// goodMatches.push_back(matches[i]);
//}
// 显示 good matches
cv::drawMatches(rgb1, kp1, rgb2, kp2, inliers1, AKAZE_BF_imgMatches);
cv::imwrite("F:/study work/Visual Odometry dev/VO_practice_2016.4/算法测试/KAZE算法/data/AKAZE-BF-Matches-inliers.jpg", AKAZE_BF_imgMatches);
cv::drawMatches(rgb1, kp1, rgb2, kp2, goodMatches1, AKAZE_KNN_imgMatches);
cv::imwrite("F:/study work/Visual Odometry dev/VO_practice_2016.4/算法测试/KAZE算法/data/AKAZE-Good-KNN-Matches.jpg", AKAZE_KNN_imgMatches);
cv::resize(AKAZE_BF_imgMatches, AKAZE_BF_imgMatches, Size(AKAZE_BF_imgMatches.cols / 2, AKAZE_BF_imgMatches.rows / 2));
cv::imshow("AKAZE-BF-Matches-inliers", AKAZE_BF_imgMatches);
cv::resize(AKAZE_KNN_imgMatches, AKAZE_KNN_imgMatches, Size(AKAZE_KNN_imgMatches.cols / 2, AKAZE_KNN_imgMatches.rows / 2));
cv::imshow("AKAZE-Good-KNN-Matches", AKAZE_KNN_imgMatches);
cv::waitKey(0);
}