Colmap学习二:前端部分(特征点提取、匹配与剔除)

2023-10-19 06:59

本文主要是介绍Colmap学习二:前端部分(特征点提取、匹配与剔除),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 Colmap特征提取和描述

colmap一般使用sift-gpu,涉及的知识:

1.1 图像金字塔:DOG图像金字塔,再找极值
1.2 SIFT特征检测与描述:确定主方向和128维的描述子,再归一化(消除光照的影响)。

其中由于Euclidean distance 容易受较大值的影响,使用
Hellinger distance更稳定。colmap先对sift的结果进行L1 normalize,再对每一个元素求平方根,得到的结果便是L2 normalized。在论文中给出了使用RootSIFT匹配的结果优于SIFT
在这里插入图片描述

1.3 colmap代码细节参数

Octave,Sublevel,模糊尺度,极值筛选阈值,初始直方图的平滑次数,描述子的归一化,DSP-Sift特征等。
直接看源码:在这里插入图片描述

1.4 colmap特征点储存格式,便于后续自己改feature
  • feature/types.h可以看到,2,4,6参数的形式都可以:

struct FeatureKeypoint {FeatureKeypoint();FeatureKeypoint(const float x, const float y);FeatureKeypoint(const float x, const float y, const float scale,const float orientation);FeatureKeypoint(const float x, const float y, const float a11,const float a12, const float a21, const float a22);static FeatureKeypoint FromParameters(const float x, const float y,const float scale_x,const float scale_y,const float orientation,const float shear);// Rescale the feature location and shape size by the given scale factor.void Rescale(const float scale);void Rescale(const float scale_x, const float scale_y);// Compute similarity shape parameters from affine shape.float ComputeScale() const;float ComputeScaleX() const;float ComputeScaleY() const;float ComputeOrientation() const;float ComputeShear() const;// Location of the feature, with the origin at the upper left image corner,// i.e. the upper left pixel has the coordinate (0.5, 0.5).float x;float y;// Affine shape of the feature.float a11;float a12;float a21;float a22;
};
  • base/database.cc可以看到默认为6(也就是ASIFT算法)
FeatureKeypointsBlob FeatureKeypointsToBlob(const FeatureKeypoints& keypoints) {const FeatureKeypointsBlob::Index kNumCols = 6;FeatureKeypointsBlob blob(keypoints.size(), kNumCols);for (size_t i = 0; i < keypoints.size(); ++i) {blob(i, 0) = keypoints[i].x;blob(i, 1) = keypoints[i].y;blob(i, 2) = keypoints[i].a11;blob(i, 3) = keypoints[i].a12;blob(i, 4) = keypoints[i].a21;blob(i, 5) = keypoints[i].a22;}return blob;
}FeatureKeypoints FeatureKeypointsFromBlob(const FeatureKeypointsBlob& blob) {FeatureKeypoints keypoints(static_cast<size_t>(blob.rows()));if (blob.cols() == 2) {for (FeatureKeypointsBlob::Index i = 0; i < blob.rows(); ++i) {keypoints[i] = FeatureKeypoint(blob(i, 0), blob(i, 1));}} else if (blob.cols() == 4) {for (FeatureKeypointsBlob::Index i = 0; i < blob.rows(); ++i) {keypoints[i] =FeatureKeypoint(blob(i, 0), blob(i, 1), blob(i, 2), blob(i, 3));}} else if (blob.cols() == 6) {for (FeatureKeypointsBlob::Index i = 0; i < blob.rows(); ++i) {keypoints[i] = FeatureKeypoint(blob(i, 0), blob(i, 1), blob(i, 2),blob(i, 3), blob(i, 4), blob(i, 5));}} else {LOG(FATAL) << "Keypoint format not supported";}return keypoints;
}FeatureMatchesBlob FeatureMatchesToBlob(const FeatureMatches& matches) {const FeatureMatchesBlob::Index kNumCols = 2;FeatureMatchesBlob blob(matches.size(), kNumCols);for (size_t i = 0; i < matches.size(); ++i) {blob(i, 0) = matches[i].point2D_idx1;blob(i, 1) = matches[i].point2D_idx2;}return blob;
}FeatureMatches FeatureMatchesFromBlob(const FeatureMatchesBlob& blob) {CHECK_EQ(blob.cols(), 2);FeatureMatches matches(static_cast<size_t>(blob.rows()));for (FeatureMatchesBlob::Index i = 0; i < blob.rows(); ++i) {matches[i].point2D_idx1 = blob(i, 0);matches[i].point2D_idx2 = blob(i, 1);}return matches;
}

2 Colmap特征匹配算法

2.1 相似度判断准则:余弦相似度
2.2 五种匹配算法

暴力匹配(遍历费时),顺序匹配(序列图像用)、词汇树匹配(兼顾时效)、空间匹配(有额外的空间信息用)和转移匹配:
在这里插入图片描述

上图的Custom为自定义,自己去定义哪几张图像匹配哪几张不匹配,算是一种人工调参手段。

  • colmap中的Sequential Matching
  • colmap中Spatial Matching增添位姿信息
  • colmap各种匹配的使用体验
2.3 几何验证算法:剔除outliers
  • 对于标定相机,用E/F H/F H/E的内点个数比值来决定选用的剔除模型
 // Determine inlier ratios of different models.const double E_F_inlier_ratio =static_cast<double>(E_report.support.num_inliers) /F_report.support.num_inliers;const double H_F_inlier_ratio =static_cast<double>(H_report.support.num_inliers) /F_report.support.num_inliers;const double H_E_inlier_ratio =static_cast<double>(H_report.support.num_inliers) /E_report.support.num_inliers;
  • 对于未标定相机,利用仅可以得到的F矩阵(E无法得到
 // Uncalibrated configuration.num_inliers = F_report.support.num_inliers;best_inlier_mask = &F_report.inlier_mask;if (H_F_inlier_ratio > options.max_H_inlier_ratio) {config = ConfigurationType::PLANAR_OR_PANORAMIC;if (H_report.support.num_inliers > num_inliers) {num_inliers = H_report.support.num_inliers;best_inlier_mask = &H_report.inlier_mask;}} else {config = ConfigurationType::UNCALIBRATED;}} else if (H_report.success &&H_report.support.num_inliers >= options.min_num_inliers) {num_inliers = H_report.support.num_inliers;best_inlier_mask = &H_report.inlier_mask;config = ConfigurationType::PLANAR_OR_PANORAMIC;} else {config = ConfigurationType::DEGENERATE;return;}
  • Guide Matching:由网课上说的是,图1点x在图2的极线Fx上,但是由于误差可能在其附近,于是设置了一个极线的上下阈值。想更全面的了解,可以参考OpenMVG的匹配对几何验证。
  • GeometricAdjacencyMatrix:无向图,一个矩阵。
    – n*n矩阵(n为图像个数),0代表没有,其他数值代表有多少匹配。
    – i行j列也就是图i∈n与图j∈n的匹配点个数。可知,对角位置为0(自己和自己无匹配)
2.4 匹配点存储格式

索引对(替换前端只要统一为以下输出格式就好了)

FeatureMatchesBlob FeatureMatchesToBlob(const FeatureMatches& matches) {const FeatureMatchesBlob::Index kNumCols = 2;FeatureMatchesBlob blob(matches.size(), kNumCols);for (size_t i = 0; i < matches.size(); ++i) {blob(i, 0) = matches[i].point2D_idx1;blob(i, 1) = matches[i].point2D_idx2;}return blob;
}FeatureMatches FeatureMatchesFromBlob(const FeatureMatchesBlob& blob) {CHECK_EQ(blob.cols(), 2);FeatureMatches matches(static_cast<size_t>(blob.rows()));for (FeatureMatchesBlob::Index i = 0; i < blob.rows(); ++i) {matches[i].point2D_idx1 = blob(i, 0);matches[i].point2D_idx2 = blob(i, 1);}return matches;
}

3. 动态物体剔除

剔除Mask以外的特征

  • Mask是动态目标的话,mask内部应该为黑色0
  • Mask是要保留的目标的话,mask外部为黑色0
  • colmap的以下函数仅将mask内的点输入到out_index中输出keypoints:
void MaskKeypoints(const Bitmap& mask, FeatureKeypoints* keypoints,FeatureDescriptors* descriptors) {size_t out_index = 0;BitmapColor<uint8_t> color;for (size_t i = 0; i < keypoints->size(); ++i) {if (!mask.GetPixel(static_cast<int>(keypoints->at(i).x),static_cast<int>(keypoints->at(i).y), &color) ||color.r == 0) {// Delete this keypoint by not copying it to the output.} else {// Retain this keypoint by copying it to the output index (in case this// index differs from its current position).if (out_index != i) {keypoints->at(out_index) = keypoints->at(i);for (int col = 0; col < descriptors->cols(); ++col) {(*descriptors)(out_index, col) = (*descriptors)(i, col);}}out_index += 1;}}keypoints->resize(out_index);descriptors->conservativeResize(out_index, descriptors->cols());
}

看一下GUI:

  • 1为输入图像的Mask序列
  • 2可以只输入一张图像,是整体所有图像序列的Mask(可以用来去边缘水印)

在这里插入图片描述

4. 自定义feature替换sift

4.1自己写特征提取

输出为1.4的db格式,246

4.2匹配、筛outliers

输出为2.4的db格式,索引值

4.3 继续后面的流程

Reference:以上主要参考源代码和网课

这篇关于Colmap学习二:前端部分(特征点提取、匹配与剔除)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/weixin_44671418/article/details/124837271
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/238139

相关文章

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

使用vscode搭建pywebview集成vue项目实践

《使用vscode搭建pywebview集成vue项目实践》:本文主要介绍使用vscode搭建pywebview集成vue项目实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录环境准备项目源码下载项目说明调试与生成可执行文件核心代码说明总结本节我们使用pythonpywebv

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

使用Python和Tkinter实现html标签去除工具

《使用Python和Tkinter实现html标签去除工具》本文介绍用Python和Tkinter开发的HTML标签去除工具,支持去除HTML标签、转义实体并输出纯文本,提供图形界面操作及复制功能,需... 目录html 标签去除工具功能介绍创作过程1. 技术选型2. 核心实现逻辑3. 用户体验增强如何运行

CSS 样式表的四种应用方式及css注释的应用小结

《CSS样式表的四种应用方式及css注释的应用小结》:本文主要介绍了CSS样式表的四种应用方式及css注释的应用小结,本文通过实例代码给大家介绍的非常详细,详细内容请阅读本文,希望能对你有所帮助... 一、外部 css(推荐方式)定义:将 CSS 代码保存为独立的 .css 文件,通过 <link> 标签

Python对PDF书签进行添加,修改提取和删除操作

《Python对PDF书签进行添加,修改提取和删除操作》PDF书签是PDF文件中的导航工具,通常包含一个标题和一个跳转位置,本教程将详细介绍如何使用Python对PDF文件中的书签进行操作... 目录简介使用工具python 向 PDF 添加书签添加书签添加嵌套书签Python 修改 PDF 书签Pytho

使用Vue-ECharts实现数据可视化图表功能

《使用Vue-ECharts实现数据可视化图表功能》在前端开发中,经常会遇到需要展示数据可视化的需求,比如柱状图、折线图、饼图等,这类需求不仅要求我们准确地将数据呈现出来,还需要兼顾美观与交互体验,所... 目录前言为什么选择 vue-ECharts?1. 基于 ECharts,功能强大2. 更符合 Vue

Vue中插槽slot的使用示例详解

《Vue中插槽slot的使用示例详解》:本文主要介绍Vue中插槽slot的使用示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、插槽是什么二、插槽分类2.1 匿名插槽2.2 具名插槽2.3 作用域插槽三、插槽的基本使用3.1 匿名插槽

springboot+vue项目怎么解决跨域问题详解

《springboot+vue项目怎么解决跨域问题详解》:本文主要介绍springboot+vue项目怎么解决跨域问题的相关资料,包括前端代理、后端全局配置CORS、注解配置和Nginx反向代理,... 目录1. 前端代理(开发环境推荐)2. 后端全局配置 CORS(生产环境推荐)3. 后端注解配置(按接口

Vue 2 项目中配置 Tailwind CSS 和 Font Awesome 的最佳实践举例

《Vue2项目中配置TailwindCSS和FontAwesome的最佳实践举例》:本文主要介绍Vue2项目中配置TailwindCSS和FontAwesome的最... 目录vue 2 项目中配置 Tailwind css 和 Font Awesome 的最佳实践一、Tailwind CSS 配置1. 安