OpenCV旋转估计(1)用于估计图像间仿射变换关系的类cv::detail::AffineBasedEstimator
- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
基于仿射变换的估计器。
这种估计器使用匹配器估算的成对变换来为每个相机估算最终的变换。
cv::detail::AffineBasedEstimator 是 OpenCV 库中用于估计图像间仿射变换关系的类。仿射变换是一种二维坐标到二维坐标之间的线性映射,它保持了直线和平行线的性质,但允许旋转、平移、缩放和倾斜。
此类通常在图像拼接、特征匹配后处理等任务中使用,用来精确计算两张或多张图像间的相对位置关系。仿射变换可以通过三对点(每个图像中各三点)来唯一确定,因此该类可能要求用户提供至少三对匹配点以进行变换矩阵的估算。
基本用法
- 创建对象:首先,需要创建 cv::detail::AffineBasedEstimator 类的一个实例。
- 准备数据:准备好你想要用来估计仿射变换的数据,这通常是一系列匹配好的关键点对。
- 调用估算方法:调用类的方法来执行估算。具体方法名可能根据版本有所不同,但通常会有一个类似 estimate() 的函数,接受输入的关键点对,并返回一个表示仿射变换的矩阵。
- 应用变换:得到的仿射变换矩阵可以应用于图像上,例如通过 cv::warpAffine 函数将一张图片转换到另一张图片的坐标系下。
主要成员函数
-
构造函数
AffineBasedEstimator()
默认构造函数,初始化 AffineBasedEstimator 对象。 -
estimate 函数
bool estimate(const std::vector& features, const std::vector& pairwise_matches, std::vectorcv::UMat& cameras)
该函数使用由匹配器提供的成对变换信息来估计每个相机(即每张图片)的最终仿射变换矩阵。参数:
- features: 包含每张图片的关键点和描述符信息的 ImageFeatures 结构体列表。
- pairwise_matches: 包含每对图片之间的匹配信息的 MatchesInfo 结构体列表。
- cameras: 输出参数,包含估计得到的每个相机的变换矩阵(通常是仿射变换矩阵)。
代码示例
#include <opencv2/opencv.hpp>
#include <opencv2/stitching/detail/matchers.hpp>
#include <vector>
using namespace cv;
using namespace cv::detail;
using namespace std;
int main()
{
Mat img1 = imread("/media/dingxin/data/study/OpenCV/sources/images/stich1.png", IMREAD_GRAYSCALE);
Mat img2 = imread("/media/dingxin/data/study/OpenCV/sources/images/stich2.png", IMREAD_GRAYSCALE);
if (img1.empty() || img2.empty()) {
cerr << "无法读取图像文件" << endl;
return -1;
}
// 初始化特征检测器和描述符提取器
Ptr< Feature2D > detector = ORB::create( 500 ); // 提取500个关键点
Ptr< DescriptorMatcher > matcher = DescriptorMatcher::create( "BruteForce-Hamming" );
// 检测特征点并计算描述符
vector< KeyPoint > keypoints1, keypoints2;
Mat descriptors1, descriptors2;
detector->detectAndCompute( img1, noArray(), keypoints1, descriptors1 );
detector->detectAndCompute( img2, noArray(), keypoints2, descriptors2 );
// 匹配描述符
vector< DMatch > matches;
matcher->match( descriptors1, descriptors2, matches );
// 过滤匹配结果(可选)
vector< Point2f > points1, points2;
for ( size_t i = 0; i < matches.size(); i++ )
{
points1.push_back( keypoints1[ matches[ i ].queryIdx ].pt );
points2.push_back( keypoints2[ matches[ i ].trainIdx ].pt );
}
// 使用RANSAC算法估计仿射变换
Mat inliers_mask;
Mat affine_matrix = estimateAffinePartial2D( points1, points2, inliers_mask );
cout << "Affine Matrix: \n" << affine_matrix << endl;
// 绘制匹配结果(仅显示内点)
vector< DMatch > good_matches;
for ( int i = 0; i < inliers_mask.rows; ++i )
{
if ( inliers_mask.at< uchar >( i ) )
{
good_matches.push_back( matches[ i ] );
}
}
Mat img_matches;
drawMatches( img1, keypoints1, img2, keypoints2, good_matches, img_matches );
imshow( "Good Matches & Affine Transform", img_matches );
waitKey( 0 );
return 0;
}