关于特征匹配可视化的cpp实现(参考多种示例)

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <opencv2/opencv.hpp>
# define M_PI           3.14159265358979323846
using namespace std;
using namespace cv;

enum MyEnum
{
	ONLY_LINES = 1,
	LINES_AND_POINTS = 2,
	COLOR_CODED_POINTS_X = 3,
	COLOR_CODED_POINTS_Y = 4,
	COLOR_CODED_POINTS_XpY = 5,
	POINTS_DeepMatch = 6,
	POINTS_DeepMatch_COLOR = 7
};

Mat draw_matches(Mat &matchingImage, vector<uchar> &inliersMask, MyEnum drawing_type, std::vector<Point2f> &obj, std::vector<Point2f> &scene, Mat &retained_matches, cv::Size &img1_size, cv::Size &img2_size)
{
	if (drawing_type == ONLY_LINES)
	{
		for (size_t i = 0; i<inliersMask.size(); i++){
			if (inliersMask[i])
			{
				line(matchingImage, obj[i], scene[i], Scalar(0, 0, 255));
			}
		}
	}
	else if (drawing_type == LINES_AND_POINTS)
	{
		for (size_t i = 0; i<inliersMask.size(); i++){
			if (inliersMask[i])
			{
				line(matchingImage, obj[i], scene[i], Scalar(255, 0, 0));
				circle(matchingImage, obj[i], 1, Scalar(0, 255, 255), 2);
				circle(matchingImage, scene[i], 1, Scalar(0, 255, 0), 2);
			}
		}
	}
	else if ((drawing_type == COLOR_CODED_POINTS_X) || (drawing_type == COLOR_CODED_POINTS_Y) || (drawing_type == COLOR_CODED_POINTS_XpY))
	{
		Mat _1_255(256, 1, CV_8UC1, Scalar(0));
		for (int i = 0; i < _1_255.rows; i++)
			_1_255.at<uchar>(i, 0) = i;
		Mat _colormap;
		applyColorMap(_1_255, _colormap, COLORMAP_HSV);
		int colormap_idx;
		Scalar color;
		for (size_t i = 0; i<inliersMask.size(); i++){
			if (inliersMask[i])
			{
				if (drawing_type == COLOR_CODED_POINTS_X)
					colormap_idx = int(obj[i].x * 256. / img1_size.width); //x - gradient
				if (drawing_type == COLOR_CODED_POINTS_Y)
					colormap_idx = int(obj[i].y * 256. / img1_size.height); //y - gradient
				if (drawing_type == COLOR_CODED_POINTS_XpY)
					colormap_idx = int((obj[i].x - img1_size.width * 0.5 + obj[i].y - img1_size.height * 0.5) * 256. / (img1_size.height * 0.5 + img1_size.width * 0.5)); //manhattan gradient

				colormap_idx = colormap_idx >= 0 ? colormap_idx : 256 + colormap_idx;
				const uchar* inData = _colormap.ptr<uchar>(colormap_idx);
				color = Scalar(inData[0], inData[1], inData[2]);
				circle(matchingImage, obj[i], 1, color, 2);
				circle(matchingImage, scene[i], 1, color, 2);
			}
		}
	}
	else if (drawing_type == POINTS_DeepMatch)
	{
		int img1_p1_x, img1_p2_x, img1_p3_y, img1_p4_y;
		int img2_p1_x, img2_p2_x, img2_p3_y, img2_p4_y;
		int pixel = 6;
		for (size_t i = 0; i<inliersMask.size(); i++){
			if (inliersMask[i])
			{
				img1_p1_x = obj[i].x - pixel < 0 ? 0 : obj[i].x - pixel;
				img1_p2_x = obj[i].x + pixel > img1_size.width - 1 ? img1_size.width - 1 : obj[i].x + pixel;
				img1_p3_y = obj[i].y - pixel < 0 ? 0 : obj[i].y - pixel;
				img1_p4_y = obj[i].y + pixel > img1_size.height - 1 ? img1_size.height - 1 : obj[i].y + pixel;

				line(matchingImage, Point(img1_p1_x, obj[i].y), Point(img1_p2_x, obj[i].y), Scalar(255, 0, 0), 2);
				line(matchingImage, Point(obj[i].x, img1_p3_y), Point(obj[i].x, img1_p4_y), Scalar(255, 0, 0), 2);

				//右图点要进行减去左图宽度操作
				img2_p1_x = scene[i].x - img1_size.width - pixel < 0 ? 0 : scene[i].x - pixel;
				img2_p2_x = scene[i].x - img1_size.width + pixel > img2_size.width - 1 ? img2_size.width - 1 : scene[i].x + pixel;
				img2_p3_y = scene[i].y - pixel < 0 ? 0 : scene[i].y - pixel;
				img2_p4_y = scene[i].y + pixel > img2_size.height - 1 ? img2_size.height - 1 : scene[i].y + pixel;

				line(matchingImage, Point(img2_p1_x, scene[i].y), Point(img2_p2_x, scene[i].y), Scalar(0, 0, 255), 2);
				line(matchingImage, Point(scene[i].x, img2_p3_y), Point(scene[i].x, img2_p4_y), Scalar(0, 0, 255), 2);
			}
		}
	}
	else if (drawing_type == POINTS_DeepMatch_COLOR)
	{
		int img1_p1_x, img1_p2_x, img1_p3_y, img1_p4_y;
		int img2_p1_x, img2_p2_x, img2_p3_y, img2_p4_y;
		int pixel = 6;

		
		//构建颜色矩阵
		cv::Scalar tempVal = cv::mean(retained_matches);
		float x1_mean = tempVal.val[0];
		float y1_mean = tempVal.val[1];

		Mat img1_xy;
		vector<Mat> split_channel;
		vector<Mat> merge_channel(2);
		split(retained_matches, split_channel);
		split_channel[0] -= x1_mean;
		split_channel[1] -= y1_mean;
		merge_channel[0] = split_channel[0];
		merge_channel[1] = split_channel[1];
		merge(merge_channel, img1_xy);
		//Mat img1_xy_Transpose = img1_xy.t();
		float aa = atan2(63.2115365, -211.2886977);
		Mat img_score(img1_xy.size().height, 1, CV_32S, Scalar(0));
		for (size_t k = 0; k < inliersMask.size(); k++){
			double cos = double(img1_xy.at<int>(k, 0));
			double sin = double(img1_xy.at<int>(k, 1));
			int temp = int(128 * atan2(sin, cos) / M_PI);
			//cpp像python一样求余 %
			img_score.at<int>(k, 0) = temp - 256 * floor(temp / 256.00);
		}

		Mat _1_255(256, 1, CV_8UC1, Scalar(0));
		for (int i = 0; i < _1_255.rows; i++)
			_1_255.at<uchar>(i, 0) = i;
		Mat _colormap;
		applyColorMap(_1_255, _colormap, COLORMAP_HSV);
		Scalar color;

		for (size_t i = 0; i<inliersMask.size(); i++){
			if (inliersMask[i])
			{
				const uchar* inData = _colormap.ptr<uchar>(img_score.at<int>(i, 0));
				color = Scalar(inData[0], inData[1], inData[2]);

				img1_p1_x = obj[i].x - pixel < 0 ? 0 : obj[i].x - pixel;
				img1_p2_x = obj[i].x + pixel > img1_size.width - 1 ? img1_size.width - 1 : obj[i].x + pixel;
				img1_p3_y = obj[i].y - pixel < 0 ? 0 : obj[i].y - pixel;
				img1_p4_y = obj[i].y + pixel > img1_size.height - 1 ? img1_size.height - 1 : obj[i].y + pixel;

				line(matchingImage, Point(img1_p1_x, obj[i].y), Point(img1_p2_x, obj[i].y), color, 2);
				line(matchingImage, Point(obj[i].x, img1_p3_y), Point(obj[i].x, img1_p4_y), color, 2);

				//右图点要进行减去左图宽度操作
				img2_p1_x = scene[i].x - img1_size.width - pixel < 0 ? 0 : scene[i].x - pixel;
				img2_p2_x = scene[i].x - img1_size.width + pixel > img2_size.width - 1 ? img2_size.width - 1 : scene[i].x + pixel;
				img2_p3_y = scene[i].y - pixel < 0 ? 0 : scene[i].y - pixel;
				img2_p4_y = scene[i].y + pixel > img2_size.height - 1 ? img2_size.height - 1 : scene[i].y + pixel;

				line(matchingImage, Point(img2_p1_x, scene[i].y), Point(img2_p2_x, scene[i].y), color, 2);
				line(matchingImage, Point(scene[i].x, img2_p3_y), Point(scene[i].x, img2_p4_y), color, 2);
			}
		}
	}
	return matchingImage;
}

//int main()
//{
//	Mat imgLeft = imread("img1.ppm");
//	Mat imgRight = imread("img3.ppm");
//
//	int maxHeight = max(imgLeft.size().height, imgRight.size().height);
//	Size sz = Size(imgLeft.size().width + imgRight.size().width, maxHeight);
//	Mat matchingImage = Mat::zeros(sz, CV_8UC3);
//	// 设置matchingImage的感兴趣区域大小并赋予原图
//	Mat roi1 = Mat(matchingImage, Rect(0, 0, imgLeft.size().width, imgLeft.size().height));
//	imgLeft.copyTo(roi1);
//	Mat roi2 = Mat(matchingImage, Rect(imgLeft.size().width, 0, imgRight.size().width, imgRight.size().height));
//	imgRight.copyTo(roi2);
//
//	std::ifstream fout;
//	fout.open("./opencv_coord_matchPoint.txt", std::fstream::out | std::fstream::in);
//	if (!fout)
//	{
//		std::cerr << "error:========" << "File Not Opened" << std::endl;
//		return -1;
//	}
//	//设置精度  小数点后两位
//	//fout.setf(ios::fixed, ios::floatfield);
//	//fout.precision(2);
//	string sline;//每一行
//	string out;
//	string x1, y1, x2, y2;
//	int i_x1, i_y1, i_x2, i_y2;
//	std::vector<Point2f>obj;
//	std::vector<Point2f>scene;
//	while (getline(fout, sline))
//	{
//		istringstream sin(sline);
//		sin >> x1 >> y1 >> x2 >> y2;
//		//cout << x1 << " " << y1 << " " << x2 << " " << y2 << " " << "\n";
//		i_x1 = std::stoi(x1);
//		i_y1 = std::stoi(y1);
//		i_x2 = std::stoi(x2);
//		i_y2 = std::stoi(y2);
//
//		obj.push_back(Point(i_x1 - 1, i_y1 - 1));
//		scene.push_back(Point(imgLeft.size().width + i_x2 - 1, i_y2 - 1));
//	}
//
//	Mat retained_matches(obj.size(), 1, CV_32SC4, Scalar(0, 0, 0, 0));
//	for (size_t p = 0; p < obj.size(); ++p)
//	{
//		retained_matches.at<Vec4i>(p, 0)[0] = obj[p].x;
//		retained_matches.at<Vec4i>(p, 0)[1] = obj[p].y;
//		retained_matches.at<Vec4i>(p, 0)[2] = scene[p].x - imgLeft.size().width;
//		retained_matches.at<Vec4i>(p, 0)[3] = scene[p].y;
//	}
//
//
//	vector<uchar>inliersMask(obj.size());
//	Mat H = findHomography(scene, obj, CV_FM_RANSAC, 1, inliersMask);
//	MyEnum drawing_type = POINTS_DeepMatch_COLOR;
//	Mat result = draw_matches(matchingImage, inliersMask, drawing_type, obj, scene, retained_matches, imgLeft.size(), imgRight.size());
//	Mat showImg;
//	resize(result, showImg, Size(matchingImage.cols / 2, matchingImage.rows / 2), 0, 0, INTER_LINEAR);
//	imshow("draw_matchPoint", showImg);
//	waitKey();
//	return 0;
//}

int main()
{
	Mat imgLeft = imread("img1.ppm");
	Mat imgRight = imread("img2.ppm");

	vector<KeyPoint> keyPoint1;
	ORB orb(500000);
	orb.detect(imgLeft, keyPoint1);
	Mat descriImage1;
	orb.compute(imgLeft, keyPoint1, descriImage1);
	vector<KeyPoint> keyPoints2;
	orb.detect(imgRight, keyPoints2);
	Mat descriImage2;
	orb.compute(imgRight, keyPoints2, descriImage2);
	vector<DMatch> matches;
	Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
	matcher->match(descriImage1, descriImage2, matches);

	int maxHeight = max(imgLeft.size().height, imgRight.size().height);
	Size sz = Size(imgLeft.size().width + imgRight.size().width, maxHeight);
	Mat matchingImage = Mat::zeros(sz, CV_8UC3);
	// 设置matchingImage的感兴趣区域大小并赋予原图
	Mat roi1 = Mat(matchingImage, Rect(0, 0, imgLeft.size().width, imgLeft.size().height));
	imgLeft.copyTo(roi1);
	Mat roi2 = Mat(matchingImage, Rect(imgLeft.size().width, 0, imgRight.size().width, imgRight.size().height));
	imgRight.copyTo(roi2);

	double max_dist = 0; double min_dist = 100;
	for (int i = 0; i < descriImage1.rows; i++)
	{
		double dist = matches[i].distance;
		if (dist < min_dist) min_dist = dist;
		if (dist > max_dist) max_dist = dist;
	}
	std::vector< DMatch > good_matches;
	for (int i = 0; i < descriImage1.rows; i++)
	{
		if (matches[i].distance < 0.9*max_dist)
		{
			good_matches.push_back(matches[i]);
		}
	}
	std::vector<Point2f>obj;
	std::vector<Point2f>scene;
	Mat retained_matches(good_matches.size(), 1, CV_32SC4, Scalar(0, 0, 0, 0));
	int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
	for (size_t i = 0; i < good_matches.size(); ++i)
	{
		x2 = keyPoints2[good_matches[i].trainIdx].pt.x + imgLeft.size().width;
		y2 = keyPoints2[good_matches[i].trainIdx].pt.y;
		obj.push_back(keyPoint1[good_matches[i].queryIdx].pt);
		scene.push_back(cv::Point(x2, y2));
		retained_matches.at<Vec4i>(i, 0)[0] = keyPoint1[good_matches[i].queryIdx].pt.x;
		retained_matches.at<Vec4i>(i, 0)[1] = keyPoint1[good_matches[i].queryIdx].pt.y;
		retained_matches.at<Vec4i>(i, 0)[2] = x2;
		retained_matches.at<Vec4i>(i, 0)[3] = y2;
	}

	vector<uchar>inliersMask(obj.size());
	Mat H = findHomography(scene, obj, CV_FM_RANSAC, 3, inliersMask);
	MyEnum drawing_type = POINTS_DeepMatch_COLOR;
	Mat result = draw_matches(matchingImage, inliersMask, drawing_type, obj, scene, retained_matches, imgLeft.size(), imgRight.size());
	Mat showImg;
	resize(result, showImg, Size(matchingImage.cols / 2, matchingImage.rows / 2), 0, 0, INTER_LINEAR);
	imshow("draw_matchPoint", showImg);
	waitKey();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值