c++实现基于sift匹配后的控制点按照均匀分布、方向、尺度筛选

文章介绍了在大图片控制点提取中,如何通过分块处理提高效率并减少内存消耗。主要涉及均匀性筛选,即按窗口大小选取关键点,以及尺度和旋转一致性筛选,以减少冗余匹配点。通过实例展示了如何使用这些技术优化匹配结果。
摘要由CSDN通过智能技术生成

c++实现基于sift匹配后的控制点按照均匀分布、方向、尺度筛选

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

1、均匀性筛选
2、尺度和方向性筛选

前言

在基于大图片进行控制点提取时,我们经常会进行分块处理,既有效的提高处理效率,减少内存,也可以加速点的提取和匹配。切片时需要注意不同大小的图片对提点和匹配的影响,因为图片的旋转和偏移程度不同,如果我们切成1000*1000大小进行提点和匹配,在提点和点匹配会有几万,甚至几十万个点的输出和进一步转换处理,最后输出可能也有几千、几万个点,对后续校正或者别的使用可能不太友好,可以通过均匀性进行筛选保留一些点即可,实现方案如下面文章。

提示:以下是本篇文章正文内容,下面案例可供参考

一、均匀性筛选

这里涉及到按照待处理窗口大小进行筛选,例如:我们选择10001000的大小按照200200进行筛选,每个窗口内保留1个点,即筛选完一个1000*1000大小图片点数<=25个点;代码如下:

main里使用方式如下:

//点筛选
	/*img1:图片1
	RR_keypoint01:图片1上的控制点
	img2:图片2
	RR_keypoint02:图片2上的控制点
	RRR_matches:图片1和2匹配上的控制点*/
	vector<DMatch> RRR_matches;
	RRR_matches = filterMatchesByGrid(RR_keypoint01, RR_keypoint02, RR_matches, 200);

	cout << "控制点均匀性筛选后个数:" << RRR_matches.size() << endl;
	// 绘制匹配结果
	cv::Mat imgMatchesss;
	cv::drawMatches(img1, RR_keypoint01, img2, RR_keypoint02, RRR_matches, imgMatchesss, cv::Scalar::all(-1), cv::Scalar::all(-1), std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
	string dstImg1ss = "E:\\BaiduNetdiskDownload\\out\\均匀性2.png";
	// 显示图像
	printf("保存结果为png\n");
	cv::imwrite(dstImg1ss, imgMatchesss); //0000000000000000000

filterMatchesByGrid函数如下:

vector<DMatch> filterMatchesByGrid(vector<KeyPoint>& keypoints1, vector<KeyPoint>& keypoints2, vector<DMatch>& matches, int gridSize) {
	// 假设keypoints1和keypoints2是匹配点对应的关键点,matches是它们之间的匹配
	map<pair<int, int>, vector<DMatch>> grid; // 用来按网格存储匹配点
	for (const DMatch& match : matches) {
		// 获取匹配点在第一幅图像中的位置
		Point2f pt = keypoints1[match.queryIdx].pt; //以待校正影像的行列号作为均匀性分布条件
		// 计算网格索引
		int gridX = pt.x / gridSize;
		int gridY = pt.y / gridSize;
		// 将匹配添加到对应的网格中
		grid[make_pair(gridX, gridY)].push_back(match);
	}
	vector<DMatch> filteredMatches; // 用于存储筛选后的匹配
	for (auto& entry : grid) {
		// 这里简单地选择每个网格中的第一个匹配作为代表
		filteredMatches.push_back(entry.second[0]);
	}
	// 现在filteredMatches包含了筛选后的匹配,可以进一步使用
	return filteredMatches;
}

二、尺度和旋转一致性筛选

代码如下:

// 尺度和旋转一致性检查
	const double scaleThreshold = 1.5; // 尺度比阈值  1.5
	const double rotationThreshold = 10.0; // 旋转差异阈值(度) 10.0
	std::vector<cv::DMatch> goodMatches;
	for (size_t i = 0; i < RRR_matches.size(); i++) {
		cv::DMatch& match = RRR_matches[i];
		// 计算尺度比
		double scaleRatio = RR_keypoint01[match.queryIdx].size / RR_keypoint02[match.trainIdx].size;
		// 计算旋转差异
		double rotationDiff = std::abs(RR_keypoint01[match.queryIdx].angle - RR_keypoint02[match.trainIdx].angle);
		rotationDiff = rotationDiff > 180.0 ? 360.0 - rotationDiff : rotationDiff; // 调整旋转差异到[0, 180]
		/*if (scaleRatio <= scaleThreshold && rotationDiff <= rotationThreshold) {
			goodMatches.push_back(match);
		}*/
		if (rotationDiff <= rotationThreshold) {
			goodMatches.push_back(match);
		}
	}
	cout << "尺度转换一致性检查后控制点个数:" << goodMatches.size() << endl;
	// 绘制匹配结果
	cv::Mat imgMatches;
	cv::drawMatches(img1, RR_keypoint01, img2, RR_keypoint02, goodMatches, imgMatches, cv::Scalar::all(-1), cv::Scalar::all(-1), std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
	string dstImg1 = "E:\\BaiduNetdiskDownload\\out\\1.png";
	// 显示图像
	printf("保存结果为png\n");
	cv::imwrite(dstImg1, imgMatches); //0000000000000000000

总结

大家正确使用即可,效果还是很好的,这里就不给大家看结果了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值