三维重建小有基础入门之特征点检测基础
前言:本文将从此篇开始,记录自己从普通CVer入门三维重建的学习过程,可能过程比较坎坷,都在摸索阶段,但争取每次学习都能进一步,提高自己的能力,同时,每篇文章都会按情况相应地推出B站讲解视频,可以关注up 出门吃三碗饭 观看讲解视频,文章同步更新到公众号 AI知识物语 ,大家可以关注下助助力。另外本平台的评论私信不会看,有问题可以移步B站视频评论区or私信。
最后感谢相关博主,开源社区,github等对内容的贡献,也希望各位读者在读完后能有自己的收获,并且写文章分享自己的心得,希望这个社区越做越好。
个人对于该研究的展望以及背景:对我选择这个领域最大的感受是《头号玩家》电影,里面的画面我始终抱有着在不久地未来将会商业落地的期许。同时,XR(AR,VR)元宇宙、数字藏品等概念爆火,体现了虚拟场景相关的市场有极大的潜力。虽然目前三维重建相关方面的上市企业大部分是车企相关(基于自己调查的数据),做slam、点云方面的工作(应该是无人驾驶),一些近几年比较新的公司我看到有做虚拟偶像(也属于虚拟内容)等三维重建方面的工作(并不局限三维重建,还会融和动作捕捉等等其他cv技术)。
另外我最惊讶的是 Alex Yu在2022年,当时应该在UCB读大四时候基于最初Nerf提出的Plenoxels模型,并展示在CVPR上,后面有关注到他结合自己的论文算法,和导师创建了 LumaAI公司,使用Nerf技术去实现移动端的三维重建(拍照可以实现),目前只支持IOS系统。虽然其使用,交互设计,或者盈利模式还不是特别成熟,但我相信在不久的未来,该项技术能够很好地提高社会的生产力,为人们提供更好的生活服务。
LumaAI公司Nerf 三维建模产品链接
好,就唠嗑到这里了!让我们开始讲内容吧。任务伟大的成就、梦想,离不开一项项基础技术的支持。所以我们得脚踏实地去学习。
(一)Harris角点检测
什么是角点:
(1)轮廓间交点
(2)视角变化,也能检测到的点(比如我在角度X可以看到角点A,那么移动后,在角度Y需要也能看到角点A)
(3)角点附近像素点梯度变化大,通俗来看,就是附近不平滑,或者颜色差异大
基本思想:以每个点为中心取固定窗口并在图像上任意方向滑动,比较滑动前后像素灰度变化,若变化大,则存在角点。
数学逻辑:先来看图,和角点检测的公式

在一张图片上,我们取一个点,并以他为中心取一个正方形框,作为检测区域。

公式和图里的符号的含义:
(1)[u,v] 是窗口偏移量,也就是移动方向 ,E代表灰度变化。E[u,v]就表示窗口偏移前后的灰度变化值
(2)公式 Σ 对每一个点都进行计算
(3)w(x,y)表示权重,可以设为全是1,那么所有像素点的贡献都是一样的。如果设为高斯权重,那么距离该点越近,其贡献越大
(4)I(x,y)表示取起点的像素,I(x+u,y+v)下一个点的像素。这里对两个像素取了平方差,这样的好处可以避免差值为负数,取绝对值也可以有相同的效果,平方差用得比较多,梯度下降里面平方差用得也挺多。
总得公式用语言来表达:
窗口移动前后变化差值 = 每个点逐次计算[每个点的权重 * 点移动前后像素平方差 ]
(5)第一步到第二步的方式是通过泰勒展开(只需一阶展开即可),属于大学里高数的一般知识,不用慌,一开始慢慢看
泰勒展开参考文章
(6)对第二步进行化简,可以得到第三步的公式,这部分比较困难,我们一一来看。首先引入2个公式

把图像的梯度公式代入 第二行式子可以求得最终第三行的式子。

基于已经计算好的第3个式子,如上图一样进一步化简得出 E(u,v)关于λ1 和λ2的式子。 因为上图其化简格式像一个椭圆,为了更好地观察函数图像,不防把 E(u,v)设置为1,。如下图图像


根据上面的式子可以知道,椭圆的两边长 如蓝色的图里表示。
当λ1,λ2越大的时候,图像上可以看到椭圆上下和左右都会变得很窄,也就体现了实际检测的图片该区域梯度变化快,前后差异值大。如果λ1,λ2都接近0,其根号的倒数趋近于无穷大,那么这个椭圆会很宽,也就体现了实际检测的图片该区域梯度变化慢,不是位于角点区域,可以认为其区域相对平滑。
到这里可以看到λ1,λ2的巨大作用和直观表达性,那如何对其求解?
这里引入角点准则公式

角点检测算法实际上是对函数C进行阈值处理,C >threshold,取C的局部最大值。
这种算法容易造成响应的角点有可能会密集地集中在一小块区域,会造成计算的浪费,效率的降低。因此引入了 非极大值抑制,通过选取 上述一小块区域的 “局部响应最大值”,来避免重复的检测。
现在我们来回顾下整个的算法流程

(一)首先我们根据移动向量[u,v]来计算图像移动时的梯度变化
(二)移动过程中每个像素代入公式,计算其Harris矩阵的值为H
(三,四)把H代入角点准则公式,当返回C的值大于一定的值的时候,把其设置为角点
代码:
简单介绍下使用的函数
(1)dst = cv.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]])
该功能在图像上运行Harris角检测器。
参数:
src: 输入单通道8位或浮点图像。
blockSize:它是考虑进行角点检测的邻域的大小
ksize:滑动核的大小。
k:角点响应值R计算公式中的α。
返回:
dst: 用于存储哈里斯探测器响应的图像。它的类型为CV_32FC1,大小与src相同。
(2)dst = cv.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
通过使用特定的结构元素来放大图像。该函数使用指定的结构化元素来扩展源图像,该结构化元素确定在其上获取最大值的像素邻域的形状。
参数:
src: 输入图像;通道数可以是任意的,但深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。
kernel:用于扩张的结构元素;如果elemenat = Mat(),则使用3 x 3的矩形结构元素。
anchor: 锚在元素内的位置;默认值(-1,-1)表示锚点位于元素中心。
iterations:进行扩张的次数。
返回:
dst: 输出与src大小和类型相同的图像。
代码参考文章
import numpy as np
import cv2 as cv
filename = 'test_image/test_chessboard.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv.cornerHarris(gray,2,3,0.04)
#result is dilated for marking the corners, not important
dst = cv.dilate(dst,None)
# Threshold for an optimal value, it may vary depending on the image.
img[dst>0.01*dst.max()]=[0,0,255]
cv.imshow('dst',img)
if cv.waitKey(0) & 0xff == 27:cv.destroyAllWindows()

第一小篇章到这里就先结束了,后序其实还有很多知识点,但因笔者数学功底不好,还未消化,所以迟迟未落笔。后续会继续更新相关方面的文章,从基础特征点检测,到sfm,稠密重建,点云网格重建等等。另外有时间会超出视频版的讲解,可以关注B站 出门吃三碗饭 以及公众号 AI知识物语 。另外如果文章有问题,不足之处,欢迎指出,谢谢观看。
相关文章:
三维重建小有基础入门之特征点检测基础
前言:本文将从此篇开始,记录自己从普通CVer入门三维重建的学习过程,可能过程比较坎坷,都在摸索阶段,但争取每次学习都能进一步,提高自己的能力,同时,每篇文章都会按情况相应地推出B站…...
基于node.js+vue+mysql考研辅导学习打卡交流网站系统vscode
语言 node.js 框架:Express 前端:Vue.js 数据库:mysql 数据库工具:Navicat 开发软件:VScode 主要功能包括管理员:首页、个人中心、用户管理、每日打卡管理、考研学校管理、考研专业管理、直通车管理、学习教材管理、…...
【C++、数据结构】封装unordered_map和unordered_set(用哈希桶实现)
文章目录📖 前言1. 复用同一个哈希桶⚡1.1 🌀修改后结点的定义1.2 🌀两个容器各自模板参数类型:2. 改造之后的哈希桶⛳3. 哈希桶的迭代器🔥3.1 💥哈希桶的begin()和 end(…...
StratoVirt 的 vCPU 拓扑(SMP)
CPU 拓扑用来表示 CPU 在硬件层面的组合方式,本文主要讲解 CPU 拓扑中的 SMP(Symmetric Multi-Processor,对称多处理器系统)架构,CPU 拓扑还包括其他信息,比如:cache 等,这些部分会在…...
现在直播大部分都是RTMP RTMP VS RTC
一 RTMP 抓了下抖音直播的包,windows端,走的TCP,加密了,估计还是RTMP。 我以为直播带货,都是RTC了。 快手直播也是TCP,地址用了IPV6。 淘宝直播也是。现在大部分直播都是RTMP。 只有视频会议走的RTC。…...
【Unity实战100例】Unity循环UI界面切换卡片功能
目录 编辑 一:制作UI界面 二:代码逻辑 1.定义基础变量...
Monorepo or 物料市场?结合工作实际情况对公司现有前端体系的思考
前言 去年年中基于若依vue前端框架进行了改造,加上后端的配合,我写了一套脚手架和项目中后台模板。中后台模板中包含了许多基础代码,比如登录/注册、路由、权限等等相关功能。这个中后台模板是基于我们实际开发定制的,所以跟通用…...
GEE学习笔记八十八:在自己的APP中使用绘制矢量(上)
在GEE中尤其是自己的APP中调用绘制的矢量图形方法之前没有合适的方法,但是现在可以通过ui.Map.DrawingTools(...)以及ui.Map.GeometryLayer(...)结合来做。具体的API如下图: 在这一篇中我先通过一个简单的例子来展示一下使用这些API后可以实现什么效果&a…...
“笨办法”学Python 3 ——练习 39. 字典,可爱的字典
练习39 源代码 # create a mapping of state to abbreviation #创建一个州与缩写的映射 states {Oregon:OR,Florida:FL,California: CA, New York: NY,Michigan:MI} #创建一个字典,key为州名,value为州缩写#Create a basic set of states and some cit…...
模糊的照片如何修复清晰?
相信有很多人用手机拍照时,觉得拍出来的照片一定是很漂亮的,结果拍了之后,拿出来一看模糊一片,根本看不清是什么。或者是只显示一半另一半模糊一片。而这些精彩瞬间很多时候是无法重拍的。虽然谁也不想拍出的照片出现模糊…...
如何理解session、cookie、token的区别与联系?
session、cookie、token。 相信学过接口的朋友都特别熟悉了。 但是对我一个刚接触接口测试的小白来说,属实有点分不清楚。 下文就是我通过查阅各种资料总结出来的一点理解,不准确的地方还请各位指正。 (文末送洗浴中心流程指南)…...
【MyBatis】| MyBatis分页插件PageHelper
目录 一:MyBatis使⽤PageHelper 1. limit分⻚ 2. PageHelper插件 一:MyBatis使⽤PageHelper 1. limit分⻚ (1)概念: ①页码:pageNum(用户会发送请求,携带页码pageNum给服务器&am…...
Java枚举类详解
一、定义格式 public enum s { 枚举项1,枚举项2,枚举项3; } // 定义一个枚举类,用来表示春,夏,秋,冬这四个固定值 public enum Season {SPRING,SUMMER,AUTUMN,WINTER; } 二、枚举的特点 1、所有枚举类都是Enum的子类 2、我们可以通…...
C语言数组
一.数组定义 数组由数据类型相同的一系列元素组成 如 int main(){ float candy[365]; char code[12]; int states[50]; … } cnady是包含了365个float元素的数组。code是包含了12个char类型的数组。states包含了50个int类型的数组。 二.数组初始化和取值 我们使用花括号包含值&…...
Scala 入门(第一章Scala 环境搭建、插件的安装)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 第 1 章 Scala 入门1.1 概述1.1.1 为什么学习 Scala1.1.2 Scala 发展历史1.1.3 Scala 和 Java 关系1.1.4 Scala 语言特点1.2 Scala 环境搭建1.3 Scala 插件安装1.4 HelloWorl…...
math@多项式@求和式乘法@代数学基本定理
文章目录多项式求和式乘法应用代数学基本定理相关证明高次方程其他关于多项式的参考多项式求和式乘法 S∏j1(∑k1ajk) j∏j1m(∑k1njajk) jS\prod_{j1}\left(\sum\limits_{k1}a_{jk}\right)_{\!\!\!j} \\\prod_{j1}^{m}\left(\sum\limits_{k1}^{n_j}a_{jk}\r…...
Kafka系列之:基于SCRAM和Ranger机制完成动态新增kafka读写账号、赋予账号对指定Topic的读写权限
Kafka系列之:基于SCRAM和Ranger机制完成动态新增kafka读写账号、赋予账号对指定Topic的读写权限 一、需求背景二、添加写用户三、查看用户是否添加到zookeeper中四、查看用户五、赋予用户topic写权限六、生产者配置文件七、ranger给用户权限八、往Topic写数据九、删除添加的用…...
第五十三章 DFS进阶(一)——剪枝优化
第五十四章 DFS进阶(一)——剪枝优化一、什么是剪枝?二、剪枝优化的策略1、优化搜索顺序2、排除等效冗余3、可行性剪枝4、最优性剪枝5、记忆化搜索三、例题1、AcWing 165. 小猫爬山(DFS 剪枝优化)2、AcWing 167. 木棒…...
Java字节码深度知多少?
文章目录1、字节码结构1.1、基本结构1.2、实际观测2、内存表示3、方法调用指令4、invokedynamicEND结语Java真的是长盛不衰,拥有顽强的生命力。其中,字节码机制功不可没。字节码,就像是 Linux 的 ELF。有了它,JVM直接摇身一变&…...
【C++】智能指针(万字详解)
🌈欢迎来到C专栏~~智能指针 (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort目前状态:大三非科班啃C中🌍博客主页:张小姐的猫~江湖背景快上车🚘,握好方向盘跟我有一起打天下嘞!送给自己的一句鸡汤&…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑 在电子商务领域,转化率与网站性能是决定商业成败的核心指标。今天,我们将深入解析不同类型电商平台的转化率基准,探讨页面加载速度对用户行为的…...
