论文笔记:Modeling Kinect Sensor Noise for Improved 3D Reconstruction and Tracking

news2024/11/18 23:31:09

文章目录

  • 概述
    • 效果如何?
    • take home message
      • lateral noise 模型
      • axial noise 模型
  • 实验
    • 实验设定
    • lateral noise与axial noise的定义
    • axial noise与lateral noise的提取
    • 噪声分布的结果和建模
      • 最终拟合得到的lateral noise模型
      • 最终拟合得到的axial noise模型
  • 应用噪声模型至KinectFusion
    • 数据滤波
    • 位姿估计: 加权ICP
    • Volumetric depth map fusion
  • 重建与tracking结果
  • 代码分析
    • 初始化
  • 结论

概述

对相机进行噪声模型分析,主要目的是为了更好地处理kincet深度图。
此外,噪声模型也可以更好地应用给kinectfusion系统pipeline中的滤波、体积融合以及位姿估计等动作。
实验结果表示,这样做的好处是可以重建更为精细的细节以及thinner surface。
定量结果进一步地表明,噪声模型的引入,亦可以提高姿态估计的精度。

开源代码实现:https://github.com/intelligent-control-lab/Kinect_Smoothing/tree/master/kinect_smoothing (仅仅是给深度图去噪的部分有)
论文链接: http://users.cecs.anu.edu.au/~nguyen/papers/conferences/Nguyen2012-ModelingKinectSensorNoise.pdf

效果如何?

左边是原始结果,右边是引入噪声模型之后的结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

初看只觉得提升了物体的完整性,倒是没太看出来对于细节的提升。

take home message

lateral noise 模型

在这里插入图片描述

axial noise 模型

0-60°时:
在这里插入图片描述
再考虑到 θ \theta θ接近于90°的情况,使用双曲线模型进行拟合,最终有:
在这里插入图片描述

实验

kinect 传感器的噪声,在此我们直接定义为测量深度与实际深度之间的差别。

早些时候,轴向噪声(axial noise)是直接通过比较某一平面物体(比如说门)以及目标测量值(垂直于sensor的z轴)的平均深度而实现。
当sensor距离target越来越远的时候,深度测量值的方差数值呈现出上升的趋势。
但是没有去研究 surface angle或lateral noise。
lateral noise的测量没有那么直观,理想情况下是一种点扩散模型。
完全恢复这种点扩散模型是非常困难的。
一种可选的思路是用sensor的step response function进行近似。


简而言之:
approximate the PSF as the distribution of absolute distances from the observed edge pixels to a fitted straight edge of a planar target

实验设定

深度成像在0.4m到3.0m之间。

lateral noise与axial noise的定义

lateral noise从深度图的纵向边上进行提取:

在这里插入图片描述

axial noise从raw depth与拟合的plane之间进行提取:

在这里插入图片描述

在这里插入图片描述

axial noise与lateral noise的提取

提取lateral noise与axial noise过程的示意图为:

在这里插入图片描述
步骤(a)- 步骤(c)的目的是计算得到lateral noise STD σ L \sigma_L σL:
(a) 裁剪出两条水平边;
(b)提取两条竖直边上的像素点,然后拟合成两条竖直线;
(c)提取边缘像素点到拟合直线的距离,并用于计算lateral noise STD σ L \sigma_L σL


(d)向内裁剪两个垂直边三倍 σ L \sigma_L σL
(e)拟合平面,使得其仍然保持为一个矩形的深度图;
(f)提取旋转角度 θ \theta θ以及 σ Z \sigma_Z σZ

平面拟合可以通过使用orthogonal distance regression来实现。
下图为一些不同 z z z位置和平面角度的示例:
在这里插入图片描述

噪声分布的结果和建模

target的大小是 A 2 A2 A2 - A 5 A5 A5
距离从0.5m到2.75m,步距为0.25m。
在每个距离下,抓取了不同角度 θ \theta θ的1000张深度图。这会导致在每个角度、每个距离都能够抓取大概10张左右的的深度图。
我们使用:
A 5 A5 A5大小的平面在0.5m、0.75m,
A 4 A4 A4大小的平面在1.0m、1.25m,
A 3 A3 A3大小的平面在1.5m、1.75m,
A 2 A2 A2大小的平面在2.25m、2.5m、2.75m。


使用kinect出厂时候的默认内参来进行镜头检校,fov是70°,等效焦距是585个像素,主点直接定义为图像中心。

三个样例距离的噪声分布有如:
在这里插入图片描述
显然,lateral noise几乎不随着深度变化而显著变化。相比之下,axial noise随着深度的增加而显著增加。

图6则给出lateral noise和axial noise关于z轴距离更加直观的表现,注意,图表中避免了极限surface angle时的情况,因为无效深度像素会使得鲁棒的平面拟合不切实际:
在这里插入图片描述

最终拟合得到的lateral noise模型

图7a展示了 lateral noise(单位是像素)关于距离和角度的变化情况:
在这里插入图片描述
可以发现,

  1. 除了在 z = 0.5 m z = 0.5m z=0.5m的情况下, σ L \sigma_L σL在其他距离下的变化并不大;
  2. 在 70°以前, σ L \sigma_L σL呈现微微上升的状态;如果将像素值转换成真实世界中的距离的话,就是图6中所呈现的线性增长情况。

去除小于0.5m以及大于2.8m距离的无效数据,利用常规最小二乘方法回归出线性模型(用于模拟常规接近于70°时的情况)与二次项模型(用于模拟接近于90°时的变化情况)的组合形态,正如上图(a)中黑色曲线所示。
lateral noise在像素和真实世界中的公式分别为:
在这里插入图片描述

最终拟合得到的axial noise模型

在这里插入图片描述
可以看到,

  1. σ z \sigma_z σz在不同的深度值的体现是非常不一样的,但是对于距离恒定,角度变化的情况下,60度以内基本恒定,90度以上就变得相对陡峭;
  2. 当距离超过 2.5m的时候, σ z \sigma_z σz在接近于0°的时候会体现较为显著的下降趋势。这主要是因为 Kinect的深度分辨率在远距离会有所下降。

假定在10°-60°之间 z轴向的噪声是恒定的,并使用线性回归来你和得到z轴向噪声与距离之间的关系。
当然,在线性回归的时候避免引入 10° - 60°以外的无效数据。

此时有:
在这里插入图片描述
再考虑到 θ \theta θ接近于90°的情况,我们使用双曲线模型进行拟合,最终有:
在这里插入图片描述
在这里插入图片描述

应用噪声模型至KinectFusion

在KinectFusion中,移动的深度相机的pose是通过传统ICP的point-plane变种而实现的。
Drift的减轻主要时通过frame-to-model来实现的。
隐式模型的提取主要有两种方式:ray-casting或marching cubes。


数学标识:

u = ( x , y ) \bold{u} = (x, y) u=(x,y): 深度图上的2D像素坐标;
D i ( u ) \bold{D}_i(\bold{u}) Di(u):在time frame i i i u u u位置上的深度数值;
K \bold{K} K:内参矩阵
v i ( u ) = D i ( u ) K − 1 [ u , 1 ] \bold{v}_i(\bold{u}) = \bold{D}_i(\bold{u}) \bold{K}^{-1}[\bold{u}, 1] vi(u)=Di(u)K1[u,1]:对应于深度 u \bold{u} u的三维顶点;
v i g = T i v i \bold{v}_i^g = \bold{T}_i \bold{v}_i vig=Tivi: 全局坐标系下的顶点。

数据滤波

一种在3D空间下对Kinect 数据滤波的方式是将噪声PDF建模成 3 ∗ 3 3 * 3 33的协方差矩阵。
但lateral nosie与深度无关,这会导致协方差矩阵有所冗余。
进而,我们可以直接在二维的深度图上继续进行滤波。

注意,PDF仅仅在Z方向上expand。 在这里插入图片描述

换言之, σ L \sigma_L σL σ Z \sigma_Z σZ可以被直接用于做深度图的保边滤波【怎么理解保边?】。
σ L \sigma_L σL在多数情况下会小于1。
首先使用 3 ∗ 3 3 * 3 33大小的核对深度图 D i \bold{D}_i Di进行平滑滤波,进而得到平滑后的深度图 D i ~ ( u ) \tilde{\bold{D}_i} (\bold{u}) Di~(u)
在这里插入图片描述

实现代码为:

	def modeling_filter(self,img, theta=30, threshold=10, depth_min=100, depth_max=4000,noise_type='normal'):
		"""
		modeling the noise distribution and filtering based on noise model
		:param img: numpy-array,
		:param theta: float, average angle between kinect z-axis and object plane.
		:param threshold: int, thrshold for 'modeling' and 'modeling_pf' method.
		:param depth_min: float,  minimum valid depth, we only filter the area of depth > depth_min
		:param depth_max: float,  maximum valid depth, we only filter the area of depth < depth_max
		:param noise_type: 'normal' of 'pf',
				'normal': noise modeling based on 'Modeling Kinect Sensor Noise for Improved 3D Reconstruction and Tracking'
				'pf': noise modeling based on 'Kinect v2 for Mobile Robot Navigation: Evaluation and Modeling'
		:return: denoised img: numpy-array
		"""

		denoised_img = img.copy()
		h, w = img.shape
		lateral_noise = self._lateral_noise_pf if noise_type=='pf' else self._lateral_noise
		axial_noise = self._axial_noise_pf if noise_type == 'pf' else self._axial_noise
		l_noise = np.power(lateral_noise(img, theta), 2)
		z_noise = np.power(axial_noise(img, theta), 2)
		distance_metrics = np.array([[1.414, 1, 1.414],
		                             [1, 0, 1],
		                             [1.414, 1, 1.414]])
		for x in range(h):
			for y in range(w):
				D_u = img[x, y]
				if D_u >= depth_min and D_u <= depth_max:
					# 计算 sigma_l, sigma_l
					sigmal_l = l_noise[x, y]
					sigmal_z = z_noise[x, y]
					D_k = img[max(x - 1, 0):x + 2, max(y - 1, 0):y + 2]
					delta_z = abs(D_k - D_u)
					delta_u = distance_metrics[int(x == 0):2 + int(x < h - 1), int(y == 0):2 + int(y < w - 1)]
					mark = delta_z < threshold
					D_k_list = D_k[mark].flatten()
					u_list = delta_u[mark].flatten()
					z_list = delta_z[mark].flatten()
					if len(D_k_list) > 0:
						w_k_list = np.exp(- u_list ** 2 / (2 * sigmal_l) - z_list ** 2 / (2 * sigmal_z))
						denoised_img[x, y] = np.sum(D_k_list * w_k_list) / w_k_list.sum()
		return denoised_img

从平滑后的深度图中,我们可以引出得到法向量图:
在这里插入图片描述

所谓的surface angle也就是 法向量方向与相机z轴方向之间的夹角,即:在这里插入图片描述

位姿估计: 加权ICP

数据关联的方式为:projective data association。
在数据关联的过程中,不仅仅使用了距离以及法向的阈值,还限制了在这里插入图片描述
需要小于 70°。

point-plane 能量函数线性化的前提假设是上一个pose到下一个pose之间的移动是非常小的。
这种方式会使得每一个数据都有着一样的重要程度,可能会导致次优解。
因此,这里引入加权的概念,即有:
在这里插入图片描述

Volumetric depth map fusion

为了更好地适应高斯形态的axial-noise,进一步提出在voxel grid中的tsdf编码,主要是基于axial noise pdf的cdf。
在这里插入图片描述

在最原始的sdf中, truncation length μ \mu μ主要用于去评估不确定性。在此,我们直接将其设置为 3 σ z 3 \sigma_z 3σz

在实验中,当截断长度为 6 σ z 6 \sigma_z 6σz的时候,可以进一步地包容住相机tracking的误差。

随着ICP误差的逐步减小,truncation length可以被自适应地从 6 σ z 6 \sigma_z 6σz降低至 3 σ z 3 \sigma_z 3σz

这个过程的伪代码是:

在这里插入图片描述

上述伪代码的第17行是一个近似的高斯CDF的修改版本,可以使得产生的数值在 [-1,1]之间。
s d f k sdf_k sdfk则指代原本KinectFusion算法中的sdf数值。
在原始的KinectFusion系统中,如果下一帧融合进来的点云距离表面比较远(比如说噪声),却会以同样的权重intergrate进来,就会导致几何特征有所丢失。

为了避免这个问题,标准化的项会被加进voxel weight中,如上述伪代码的第18行所示。其中,指数项就是noise distribution weight。
在这里插入图片描述主要用来自适应 3D noise 分布的宽度,在深度增加的情况下尽量覆盖更多的voxels。
在这里插入图片描述 accounts for increased length of the distribution for larger z-depths:

重建与tracking结果

在这里插入图片描述

在这里插入图片描述

代码分析

初始化

从去噪滤波初始化的“flag”可以看出来,设计了四种方式:“modeling”、“modeling_pf”、“anisotropic”、“gaussian”。
我们主要关注“modeling”的方式: 使用kinect v2 噪声模型进行滤波,‘Modeling Kinect Sensor Noise for Improved 3D Reconstruction and Tracking’。,需要指定的参数为:

在这里插入图片描述

class Denoising_Filter(object):
	"""
	Denoising filter can be used to improve the resolution of the depth image
	"""
	def __init__(self, flag='modeling',theta=30, threshold=10,depth_min=100,depth_max=4000,
	             ksize=5, sigma=0.1,niter=1,kappa=50,gamma=1,option=1):
		"""
		:param flag: string, specific methods for denoising.
				'modeling': filter with Kinect V2 noise model,  'Modeling Kinect Sensor Noise for Improved 3D Reconstruction and Tracking'
				'modeling_pf': another Kinect V2 noise modeling by Peter Fankhauser, 'Kinect v2 for Mobile Robot Navigation: Evaluation and Modeling'
				'anisotropic': smoothing with anisotropic filtering, 'Scale-space and edge detection using anisotropic diffusion'
				'gaussian': smoothing with Gaussian filtering
		:param theta: float, the average angle between Kinect z-axis and the object plane.
				Used to calculate noise in the 'modeling'  and 'modeling_pf' method
		:param threshold: int, thrshold for 'modeling' and 'modeling_pf' method.
		:param depth_min: float,  minimum valid depth, we only filter the area of depth > depth_min
		:param depth_max: float,  maximum valid depth, we only filter the area of depth < depth_max
		:param ksize: int, Gaussian kernel size
		:param sigma: float, Gaussian kernel standard deviation
		:param niter: int, number of iterations for anisotropic filtering
		:param kappa: int, conduction coefficient for anisotropic filtering, 20-100 ?
		:param gamma: float, max value of .25 for stability
		:param option: 1 or 2, options for anisotropic filtering
				1: Perona Malik diffusion equation No. 1
		        2: Perona Malik diffusion equation No. 2
		"""
		self.flag=flag
		self.f_x = 585 #focal length of the Kinect camera in pixel
		if flag=='modeling' or flag=='modeling_pf':
			self.threshold = threshold
			self.depth_min = depth_min
			self.depth_max = depth_max
			self.theta = theta
			self.noise_type='pf' if flag=='modeling_pf' else 'normal'
			self.filter = partial(self.modeling_filter,theta=theta,
			                      threshold=threshold, depth_min=depth_min,
			                      depth_max=depth_max,noise_type=self.noise_type)
		elif flag=='gaussian':
			self.ksize = ksize
			self.sigma = sigma
			self.filter = partial(cv2.GaussianBlur,ksize=(ksize,ksize),sigmaX=0)
		elif flag=='anisotropic':
			self.niter = niter
			self.kappa = kappa
			self.gamma=gamma
			self.sigma=sigma
			self.option=option
			self.filter = partial(self.anisotropic_filter,niter=niter,kappa=kappa,
			                      gamma=gamma,sigma=sigma)

		if flag not in self.all_flags:
			raise('invalid  flags. Only support:', self.all_flags)

结论

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183835.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring源码】插播一个创建代理对象的wrapIfNecessary()方法

在文章【分析向】没有三级缓存会导致什么&#xff1f; 中&#xff0c;提到过一个方法——wrapIfNecessary()&#xff0c;就是在这个方法中为Bean创建的代理对象&#xff0c;介于篇幅原因&#xff0c;当时并咩有详细&#x1f50e;分析这个方法&#xff0c;这篇文章我们进去wrapI…

第三章 ArcGIS坐标系与投影变换

文章目录第一节 坐标系的概念1.1 坐标1.2 坐标系2 基准面介绍2.1 基准面概念2.2几种基准面的说明2.3 椭球体参数的区别3 坐标系的分类3.1 两种坐标系3.2 区别3.3 度&#xff08;分、秒&#xff09;和米的转换&#xff08;高级&#xff09;4 投影坐标系4.1 两种投影方法介绍4.2 …

5、判定法

定义 判定表法&#xff1a; 分析和表述若干输入条件下&#xff0c;被测对象针对这些输入做出响应的一种工具在遇到逻辑复杂的业务时&#xff0c;可以利用判定表理清期间的逻辑关系。 重要概念 条件&#xff1a; 条件桩&#xff1a;需求规格说明书定义的被测对象的所有输入条…

图解Attention

深度学习知识点总结 专栏链接: https://blog.csdn.net/qq_39707285/article/details/124005405 此专栏主要总结深度学习中的知识点&#xff0c;从各大数据集比赛开始&#xff0c;介绍历年冠军算法&#xff1b;同时总结深度学习中重要的知识点&#xff0c;包括损失函数、优化器…

面试官:JVM是如何判定对象已死的?

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 知道的越多&#xff0c;才知知道的越少。——苏格拉底 文章目录引用计数算法可达性分析算法引用类型Dead Or Alive永久代真的"永久"吗&#xff1f;垃圾收集算法标记-清除算法标记-复制算法标记-整理…

网络编程基础

1 网络协议栈分层协议栈是指网络中各层协议的总和&#xff0c;反映了一个网络中数据传输的过程&#xff0c;由上层协议到底层协议&#xff0c;使用分层实现提高灵活性以及简化实现。OSI七层模型 和TCP/IP五层模型&#xff1a;物理层&#xff1a;考虑的是怎样才能在连接各种计算…

学长教你学C-day14-C语言文件操作

“我们的C语言学习也马上接近尾声了&#xff0c;今天我们来讲最后一个内容&#xff1a;C语言的文件夹操作。” “那么什么是文件呢&#xff1f;其实C语言里的文件是数据源的一种&#xff0c;最主要的作用是保存数据。例如txt、word、pdf等等都是不同的存储数据的形式。通过C语…

WebView与 JS 交互方式

一 前言 现在很多App里都内置了Web网页&#xff08;Hybrid App&#xff09;&#xff0c;比如说很多电商平台&#xff0c;淘宝、京东、聚划算等等&#xff0c;如下图 上述功能是由Android的WebView实现的&#xff0c;其中涉及到Android客户端与Web网页交互的实现&#xff0c;今…

Vue路由使用的几个注意点

前言 在使用vue的路由的时候&#xff0c;是有几个需要注意的点&#xff0c;下面一一说明 组件的分类 组件分为两种&#xff1a;路由组件和一般组件 路由组件是注册到路由器中&#xff0c;并且是由路由相关标签代码进行展示 一般组件是注册到组件中&#xff0c;通过组件标签…

Linux常用命令——route命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) route 显示并设置Linux中静态路由表 补充说明 route命令用来显示并设置Linux内核中的网络路由表&#xff0c;route命令设置的路由主要是静态路由。要实现两个不同的子网之间的通信&#xff0c;需要一台连接两个…

【软件架构思想系列】从伟人《矛盾论》中悟到的软件架构思想真谛:“对象”即事物,“函数”即运动变化...

引子 形而上学和辩证法两种宇宙观是截然相反的。“所谓形而上学的或庸俗进化论的宇宙观,就是用孤立的、静止的和片面的观点去看世界。这种宇宙观把世界一切事物,一切事物的形态和种类,都看成是永远彼此孤立和永远不变化的”,“和形而上学的宇宙观相反,唯物辩证法的宇宙观主…

元宇宙与数字孪生有区别

在元宇宙爆红之前&#xff0c;有一项技术已经慢慢渗透到各行各业之中&#xff0c;它可以逼真、实时地还原现实世界&#xff0c;它就是——数字孪生。目前很多人认为元宇宙与数字孪生的区别不大&#xff0c;元宇宙是数字孪生在技术层面的进阶与优化。其实不然&#xff0c;元宇宙…

IMX Linux 用户手册 --- 2

IMX Linux 用户手册 — 2 第5章 启用单独仿真 可以在i.MX 6DualLite SABRE-SD和i.MX 6DualLite SABRE-AI板上启用单独仿真。这是通过使用 引导加载程序构建过程中的特定U-Boot配置。 当在i.MX 6DualLite SABRE平台上启用此单独仿真时&#xff0c;i.MX 6DualLite的功能将更改为…

高通开发系列 - MSM8909指示灯操作

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 最近在做内核升级,但是内核串口log始终无法打印,也不清楚是不是内核跑飞了还是什么原因,先尝试点亮一个LED灯来判断下。 这里面我们…

docker start启动容器不报错,却无法正常启动

问题描述&#xff1a;想启动 1e 这个容器 start后&#xff0c;没有报错&#xff0c;但是就是启动不了… 原因 查看一下日志 docker logs 1e1b85322dfa好家伙,虽然它运行命令的时候不报错&#xff0c;但是它运行错误信息写到日志里面去了&#xff0c;查看最新的日记信息看…

回收租赁商城系统功能拆解14讲-分销设置

回收租赁系统适用于物品回收、物品租赁、二手买卖交易等三大场景。 可以快速帮助企业搭建类似闲鱼回收/爱回收/爱租机/人人租等回收租赁商城。 回收租赁系统支持智能评估回收价格&#xff0c;后台调整最终回收价&#xff0c;用户同意回收后系统即刻放款&#xff0c;用户微信零…

MySQL8.0版本怎样进行CentOS系统配置?

MySQL安装完成后&#xff0c;会自动配置为名称叫做&#xff1a;mysqld的服务&#xff0c;可以被systemctl所管理&#xff0c;我们在进行系统的配置时&#xff0c;主要修改root密码和允许root远程登录。 # 通过grep命令&#xff0c;在/var/log/mysqld.log文件中&#xff0c;过滤…

深度学习论文: Multi-modal Sensor Fusion for Auto Driving Perception: A Survey

深度学习论文: Multi-modal Sensor Fusion for Auto Driving Perception: A Survey Multi-modal Sensor Fusion for Auto Driving Perception: A Survey PDF: https://arxiv.org/pdf/2202.02703.pdf PyTorch代码: https://github.com/shanglianlm0525/CvPytorch PyTorch代码: h…

图论中的GLM模型

下面是我对GLM模型的理解&#xff1a; 数据编码的方式 在一般统计中&#xff0c;常用的coding方式有dummy&#xff0c;effect和cell.mean&#xff0c;这个在R和python中都可以实现。 dummy coding 举例 假设有4个组别A, B, C, D&#xff0c;它的自由度是4-13&#xff0c;因此…

自动驾驶专题介绍 ———— APA标准(ISO 16787)

文章目录介绍通用要求泊车控制最大运行速度退出条件建议空间车位水平空间车位垂直空间车位泊车流程流程定义Queiscent ModeSearch ModeSlot FoundMode SelectionAssisted Parking ModeEnd of Assisted Parking Mode人机交互策略车位搜索阶段车位搜索到且未激活泊车驾驶员请求泊…