上一篇分析了特征点和匹配器的问题,使用模板图像得到了优化的匹配器,匹配器里有建立索引表的训练特征描述子,用于匹配。
这一篇将详细分析测试图像的问题:
还是看main函数,接上一节的
ARDrawingContext drawingCtx("Markerless AR", frameSize, calibration);//这个应该是OpenGL初始化的阶段。
这个是OpenGL的初始化阶段,先不关注。
1:在processFrame函数中找到这一行
drawingCtx.isPatternPresent = pipeline.processFrame(cameraFrame);//计算位姿矩阵
这是接下来重点关注的。通过追踪,我们将追到下面:
bool PatternDetector::findPattern(const cv::Mat& image, PatternTrackingInfo& info)
{
// Convert input image to gray
getGray(image, m_grayImg);//这里是优化性能,因为检测角点和提取特征描述子都需要灰度化图像,这样就减小一次灰度化。
#if _DEBUG
cv::showAndSave("Gray image",m_grayImg);
#endif
// Extract feature points from input gray image,这里是计算测试图像的角点和特征描述子。和模板图像的计算一致。
extractFeatures(m_grayImg, m_queryKeypoints, m_queryDescriptors);
// Get matches with current pattern
getMatches(m_queryDescriptors, m_matches);//对测试图像的特征描述子,在训练描述子中找到一个最佳匹配,二者组成一个匹配,放在匹配集中。在下面有具体函数实现。
#if _DEBUG
//给出两幅图,以及在这两幅图中的角点(待查询的角点特征描述子,模板角点特征描述子),及匹配集合,绘制匹配图。内部调用OpenCV的函数,最后一个参数是只绘制100个匹配。这里绘制的是很粗糙的匹配图,有很多匹配错误。
cv::showAndSave("Raw matches", getMatchesImage(image, m_pattern.frame, m_queryKeypoints, m_pattern.keypoints, m_matches, 100));
#endif
//这个就是根据给定的查询描述子集,之前计算出的训练描述子集,对每一个查询描述子集,找到一个最佳的训练描述子,并把找到的匹配放在容器里,就是二者的下标,匹配距离等一些参数。
/*OpenCV提供了两种Matching方式:
• Brute-force matcher (cv::BFMatcher)
• Flann-based matcher (cv::FlannBasedMatcher)
Brute-force matcher就是用暴力方法找到点集一中每个descriptor在点集二中距离最近的descriptor;
Flann-based matcher 使用快速近似最近邻搜索算法寻找(用快速的第三方库近似最近邻搜索算法)
一般把点集一称为 train set (训练集)对应模板图像,点集二称为 query set(查询集)对应查找模板图的目标图像。
为了提高检测速度,你可以调用matching函数前,先训练一个matcher。训练过程可以首先使用cv::FlannBasedMatcher来优化,为descriptor建立索引树,这种操作将在匹配大量数据时发挥巨大作用(比如在上百幅图像的数据集中查找匹配图像)。而Brute-force matcher在这个过程并不进行操作,它只是将train descriptors保存在内存中。*/
void PatternDetector::getMatches(const cv::Mat& queryDescriptors, std::vector<cv::DMatch>& matches)//DMatch用于匹配特征关键点的特征描述子的类:查询特征描述子索引, 特征描述子索引, 训练图像索引, 以及不同特征描述子之间的距离.
{
matches.clear();
if (enableRatioTest)
{
// To avoid NaN's when best match has zero distance we will use inversed ratio.
为了避免NaNs,当最好的匹配是零距离时&#x