深度图和RGB图对齐
坐标系间的转换_坐标系转换-CSDN博客
深度图与彩色图的配准与对齐_彩色 深度 配准-CSDN博客
kinect 2.0 SDK学习笔记(四)--深度图与彩色图对齐_mapdepthframetocolorspace-CSDN博客
相机标定(三)-相机成像模型_相机小孔成像模型-CSDN博客
1.原理部分
立体视觉往往会设计到:世界坐标系、相机坐标系、图像坐标系和像素坐标系。
世界坐标系是为了更好的描述相机的位置,双目立体视觉中一般将世界坐标系原点定在左相机或者右相机又或者两者x轴方向的中点。
①首先从世界坐标系到相机坐标系
世界坐标系中的某一个点通过平移旋转可以获得相机坐标系的位置。
详细推理请看第一篇博客。
②从相机坐标系到图像坐标系,透视变换,从3d到2d,投影点的单位是mm,将它转换到像素坐标系单位才会变成pixel。
图像坐标系的原点为相机光轴与成像平面的交点,通常情况下是成像平面的中点或者叫principal point。图像坐标系的单位是mm,属于物理单位,而像素坐标系的单位是pixel。
一个三维中的坐标点,的确可以在图像中找到一个对应的像素点,但是反过来,通过图像中的一个点找到它在三维中对应的点就很成了一个问题,因为我们并不知道等式左边的Zc的值。
2.深度图和彩色图的配准
深度图和彩色图的配准又叫对齐,之所以需要进行配准,是因为深度图中的坐标点是在深度相机坐标系下获得,彩色图的坐标点是在RGB相机坐标系下获得的。
需要先使用张正友标定等标定法,对深度相机和RGB相机分别进行标定,获得相机的内外参矩阵。
设P_ir为在深度摄像头坐标下某点的空间坐标,p_ir为该点在像平面上的投影坐标(x、y单位为像素,z等于深度值,单位为毫米),H_ir为深度摄像头的内参矩阵,由小孔成像模型可知:(公式一)
小孔成像模型实际上是透视投影(perspective projection)的一种最简单的形式。假设我们要将真实世界中的三维点( X , Y , Z ) 投影为二维图像上的点p = ( x , y ) 则有:
设P_rgb为在RGB摄像头坐标下同一点的空间坐标,p_rgb为该点在RGB像平面上的投影坐标,H_rgb为RGB摄像头的内参矩阵。由于深度摄像头的坐标和RGB摄像头的坐标不同,他们之间可以用一个旋转平移变换联系起来,即:(公式二)
其中R为旋转矩阵,T为平移向量。最后再用H_rgb对P_rgb投影,即可得到该点对应的RGB坐标(空间坐标到像素坐标的关系):(公式三)
p_ir和p_rgb使用的都是齐次坐标,在构造p_ir时,应将原始的像素坐标(x,y)乘以深度值,而最终的RGB像素坐标必须将p_rgb除以z分量,即(x/z,y/z),且z分量的值即为该点到RGB摄像头的距离(单位为毫米)。
如何求联系两个坐标系的旋转矩阵和平移向量。这就要用到摄像头的外参了。
外参矩阵实际上也是由一个旋转矩阵R_ir(R_rgb)和平移向量T_ir(T_rgb)构成的,它表示将一个世界坐标系下的点P变换到摄像头坐标系下,分别对深度摄像头和RGB摄像头进行变换,有以下关系:(公式四) 世界坐标系与相机坐标系的关系,用到外参矩阵。
上式中先将P用P_ir、R_ir和T_ir的表达式表示,再代入第二个公式,可得:
上式可以看出,这是在将P_ir变换为P_rgb,对比之前的式子:
可以求出:
这就是最终两个深度相机坐标系和RGB坐标系之间的坐标转换关系,就是博客三中获得的关系式,但是当时看他的博客,没看懂它是怎么出来的公式,现在才明白。建议大家看第二篇博客更好懂一点,但是每个人理解能力不一样,说不定有的人看第三篇更好懂,个人看法。
小孔成像模型:
因此,我们只需在同一场景下,得到棋盘相对于深度摄像头和RGB摄像头的外参矩阵,即可算出联系两摄像头坐标系的变换矩阵(注意,所有旋转矩阵都是正交阵,因此可用转置运算代替求逆运算)。虽然不同场景下得到的外参矩阵都不同,计算得到的R和T也有一些变化。
import cv2
import numpy as np
import oppenni as opp
from openni import openni2dframe_data = cv2.imread('depth.png',)
frame = cv2.imread('frame.png')#
#dframe_data = np.array(frame.get_buffer_as_triplet()).reshape([480, 640, 2])
dpt1 = np.asarray(dframe_data[:, :, 0], dtype='float32')
dpt2 = np.asarray(dframe_data[:, :, 1], dtype='float32')dpt2 *= 255
#对于为什么要乘于255的解答
#深度图像的深度值 是按照16位长度(两字节)的数据格式存储的,也可以认为前八位是高字节,后八位是低字节。
#因此一张深度图像如果是 640480分辨率的话,那么图像字节大小 就是 640480*2,其中一个字节是8位(255)
# 乘以 255 是为了将低字节部分从0-255的范围转换到0-65535的范围,这样就可以与高字节部分相加得到完整的16位深度值
dpt = dpt1 + dpt2
#cv2里面的函数,就是类似于一种筛选
'假设我们需要让我们的深度摄像头感兴趣的距离范围有差别地显示,那么我们就需要确定一个合适的alpha值,公式为:有效距离*alpha=255,' \
'假设我们想让深度摄像头8m距离内的深度被显示,>8m的与8m的颜色显示相同,那么alpha=255/(8*10^3)≈0.03,' \
'假设我们想让深度摄像头6m距离内的深度被显示,>6m的与6m的颜色显示相同,那么alpha=255/(6*10^3)≈0.0425'
cv2.imshow('depth_src', dpt)
dim_gray = cv2.convertScaleAbs(dpt, alpha=0.17)
#对深度图像进行一种图像的渲染,目前有11种渲染方式,大家可以逐一去试下
depth_colormap = cv2.applyColorMap(dim_gray, 2) # 有0~11种渲染的模式
cv2.imshow('depth', depth_colormap)
ret, frame = cap.read()
cv2.imshow('color', frame)key = cv2.waitKey(1)
if int(key) == ord('q'):break # rgb相机的内参矩阵(旋转矩阵 平移矩阵) 相机坐标系到图像坐标系
RK_rgb = np.array([(0.999993, 0.00372933, -0.000414306), (-0.00372927, 0.999993, 0.000135122), (0.000414807, -0.000133576, 1)])
#TK_rgb = np.array([-0.0148581, -8.0544e-05, 2.60393e-05])# 深度相机的内参矩阵
RK_dep = np.array([(0.999993, 0.00372933, -0.000414306), (-0.00372927, 0.999993, 0.000135122), (0.000414807, -0.000133576, 1)])
#TK_dep = np.array([-0.0148581, -8.0544e-05, 2.60393e-05])# rgb相机的外参矩阵(旋转矩阵 平移矩阵) 世界坐标系到相机坐标系
R_rgb = np.array([(0.999993, 0.00372933, -0.000414306), (-0.00372927, 0.999993, 0.000135122), (0.000414807, -0.000133576, 1)])
T_rgb = np.array([-0.0148581, -8.0544e-05, 2.60393e-05])# 深度相机的外参矩阵
R_dep = np.array([(0.999993, 0.00372933, -0.000414306), (-0.00372927, 0.999993, 0.000135122), (0.000414807, -0.000133576, 1)])
T_dep = np.array([-0.0148581, -8.0544e-05, 2.60393e-05])Rir_rgb = np.dot(R_rgb @ np.linalg.inv(R_dep)) # 两个相机坐标系之间的变换矩阵
Tir_rgb = T_rgb-R_rgb@np.linalg.inv(R_dep)@T_dep
R = RK_rgb@Rir_rgb@np.linalg.inv(RK_dep) # 像素点之间的变换关系矩阵
T = RK_rgb@Tir_rgb# 形状
result = np.zeros((dpt.shape[0], dpt.shape[1], 3), dtype=np.uint8)
i = 0
# 遍历的深度图 深度图在rgb图上对齐 找到对应的像素点
for row in range(dpt.shape[0]):for col in range(dpt.shape[1]):depth_value = dpt[row, col] # 获取深度值if depth_value != 0 and depth_value != 65535:# 投影到彩色坐标系上的坐标uv_depth = np.array([col, row, 1.0]) # 齐次坐标 uv_color = depth_value / 1000.0 * np.dot(R, uv_depth) + T / 1000.0 # Z_rgb*p_rgb=R*Z_ir*p_ir+T;; (除以1000,是为了从毫米变米) 深度坐标系下的其次标点加上旋转平移获得egb坐标系下的点print("uv_color is:", uv_color, '\n', uv_color.shape)X = int(uv_color[0] / uv_color[2]) # 除以齐次坐标的最后一个元素获得像素值Y = int(uv_color[1] / uv_color[2]) # // Z_rgb*p_rgb -> p_rgbif 0 <= X < frame.shape[0] and 0 <= Y < frame.shape[1]:result[row, col] = frame[Y, X]else:result[row, col] = [0, 0, 0]i += 1
cv2.imwrite(save_path+'registrationResult.png', result)
cv2.imwrite(save_path+'src_depth.png', dpt)
cv2.imwrite(save_path+'color_depth.png', depth_colormap)
cv2.imwrite(save_path+'rgb.png', frame)
代码是根据其他博客和相关技术写的,还未进行测试,如果有什么问题,大家可以提出来,马上修改。
相关文章:

深度图和RGB图对齐
坐标系间的转换_坐标系转换-CSDN博客 深度图与彩色图的配准与对齐_彩色 深度 配准-CSDN博客 kinect 2.0 SDK学习笔记(四)--深度图与彩色图对齐_mapdepthframetocolorspace-CSDN博客 相机标定(三)-相机成像模型_相机小孔成像模型…...
滑动窗口与TCP的缓冲区(buff)的关系
滑动窗口与TCP的缓冲区(buff)有直接关联。 滑动窗口机制是TCP协议中用于流量控制和拥塞控制的重要机制。滑动窗口实际上是一个操作系统开辟的缓存空间,用于指定无需等待确认应答即可继续发送数据的最大值。这个窗口大小(win&…...

一款好用的搜索软件——everthing(搜索比文件资源管理器快)
everthing官网链接 在官网选择下载 1.下载后双击打开 2.点击OK(需要其他语言自己选择) 3.选择安装位置(路径最好别带中文和空格) 继续点击下一步 4. 点击下一步 5.继续点击安装 6.然后就完成了 7.点击打开然后就可以搜索了...
C#WPF的App.xaml启动第一个窗体的3种方式
WPF的App.xaml启动第一个窗体的3种方式 1.使用App.xaml的StartupUri属性启动(推荐使用) 在App.xaml文件中,你可以设置StartupUri属性来指定启动时显示的第一个窗口: <Application x:Class"浅看一眼WPF.App"xmlns&…...

【JAVA毕设】基于JAVA的酒店管理系统
一、项目介绍 本系统前端框架采用了比较流行的渐进式JavaScript框架Vue.js。使用Vue-Router实现动态路由,Ajax实现前后端通信,Element-plus组件库使页面快速成型。后端部分:采用SpringBoot作为开发框架,同时集成MyBatis、Redis、…...
聚类--机器学习西瓜书阅读笔记(六)
无监督学习:通过对无标记训练样本的学习,揭示数据内在规律和性质。 聚类试图将数据集中的样本划分为若干不相交的子集,聚类过程自动形成簇结构,簇对应的语义需要子集命名把握。 聚类过程可以作为单独的过程,寻找数据…...

OpenHarmony(1)开发环境搭建
一:开源项目 OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,基于开源的方式,搭建一个智能终端设备操作系统的框架和平台࿰…...

Triton服务在ASR语音识别系统中的实现
Triton服务在ASR语音识别系统中的实现 一、引言二、环境准备1. 硬件环境2. 软件环境 三、模型选择与训练1. 数据准备2. 模型架构3. 模型训练 四、模型转换与优化1. 模型转换2. 模型优化 五、配置Triton服务1. 安装Triton服务2. 创建模型仓库 一、引言 自动语音识别(…...

Typora一款极简Markdown文档编辑、阅读器,实时预览,所见即所得,多主题,免费生成序列号!
文章目录 Typora下载安装Typora序列号生成 Typora是一款Markdown编辑器和阅读器,风格极简,实时预览,所见即所得,支持MacOS、Windows、Linux操作系统,有图片和文字、代码块、数学公式、图表、目录大纲、文件管理、导入导…...

python机器人编程——用python调用API控制wifi小车的实例程序
目录 一、前言二、一个客户端的简单实现2.1 首先定义一个类及属性2.2 其次定义连接方法2.3 定义一些回调函数2.4 定义发送小车指令方法2.5 定义一个正常关闭方法 三、python编程控制小车的demo实现四、小结PS.扩展阅读ps1.六自由度机器人相关文章资源ps2.四轴机器相关文章资源p…...

面试学习整理-线程池
线程池 简介JUC包线程池介绍线程池最常问也最常用-参数线程执行分析-线程是怎么运行的进程和线程的区别Executors工厂类提供四种线程池Executors和ThreaPoolExecutor创建线程池的区别两种提交任务的方法spring集成的线程池 简介 线程池作为实际使用和面试较多的技能区, 学习是…...
Debian会取代CentOS成为更主流的操作系统吗?
我们知道,其实之前的话,国内用户对centos几乎是情有独钟的偏爱,很多人都喜欢选择centos系统,可能是受到一些原因的影响导致的吧,比如他相当于免费的红帽子系统,或者一些教程和网上的资料都推荐这个系统&…...

网络安全领域推荐证书介绍及备考指南
在网络安全领域,拥有专业认证不仅可以证明个人的专业能力,还能帮助在实际工作中应用先进的技术和知识。以下是几种热门的网络安全证书介绍及备考指南。 1. OSCP (Offensive Security Certified Professional) 证书简介 OSCP是针对渗透测试领域的入门级…...

SpringBoot项目ES6.8升级ES7.4.0
SpringBoot项目ES6.8.15 升级到 ES7.4.0 前言 由于公司内部资产统一整理,并且公司内部部署有多个版本的es集群,所以有必要将目前负责项目的ES集群升级到公司同一版本7.4.0。es6到es7的升级变化还是挺大的,因此在这里做一下简单记录…...

深度学习 之 模型部署 使用Flask和PyTorch构建图像分类Web服务
引言 随着深度学习的发展,图像分类已成为一项基础的技术,被广泛应用于各种场景之中。本文将介绍如何使用Flask框架和PyTorch库来构建一个简单的图像分类Web服务。通过这个服务,用户可以通过HTTP POST请求上传花朵图片,然后由后端…...

MFC工控项目实例二十六创建数据库
承接专栏《MFC工控项目实例二十五多媒体定时计时器》 用选取的型号为文件名建立文件夹,再在下面用测试的当天的时间创建文件夹,在这个文件中用测试的时/分/秒为数据库名创建Adcess数据库。 1、在StdAfx.h文件最下面添加代码 #import "C:/Program F…...

springmvc源码流程解析(一)
Springmvc 是基于servlet 规范来完成的一个请求响应模块,也是spring 中比较大的一个 模块,现在基本上都是零xml 配置了,采用的是约定大于配置的方式,所以我们的springmvc 也是采用这种零xml 配置的方式。 要完成这种过程ÿ…...
【论文阅读】SRGAN
学习资料 论文题目:基于生成对抗网络的照片级单幅图像超分辨率(Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network)论文地址:https://arxiv.org/abs/1609.04802代码:GitHub - xiph/daala: Modern video compression for the interne…...

kubelet PLEG实现
概述 kubelet的主要作用是确保pod状态和podspec保持一致,这里的pod状态包括pod中的container状态,个数等。 为了达到这个目的,kubelet需要从多个来源watch pod spec的变化,并周期从container runtime获取最新的container状态。比如…...

leetcode49:字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs ["eat", "tea", "tan", "ate", "nat", &…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...

实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...