浅论3DGS溅射模型在VR眼镜上的应用
摆烂仙君小课堂开课了,本期将介绍如何手搓VR眼镜,并将随手拍的电影变成3D视频。
一、3DGS模型介绍
3D 高斯模型是基于高斯函数构建的用于描述三维空间中数据分布概率的模型,高斯函数在数学和物理领域有着广泛应用,其在 3D 情境下的拓展为我们理解和处理三维数据提供了强大工具。在三维空间中,高斯模型的概率密度函数形式较为复杂,涉及多个参数。中心点坐标 (μ_x, μ_y, μ_z) 决定了分布的中心位置,即数据最可能聚集的点。而协方差矩阵则描述了数据在各个方向上的分布范围和相关性。协方差矩阵是一个对称的 3×3 矩阵,其对角线元素 (σ_x², σ_y², σ_z²) 分别代表数据在 x、y、z 轴上的方差,方差越大,说明数据在该轴方向上的分散程度越高;非对角线元素 σ_xy、σ_xz、σ_yz 反映了不同坐标轴之间的协方差,衡量了两个变量之间的线性相关程度,比如 σ_xy 为正,表明 x 和 y 方向的数据变化呈正相关趋势。
该模型在诸多领域都有重要应用,其中最重要的就是可以恶搞自己的室友,如图。
但是我们本期要讲的是如何通过3D溅射模型把普通视频变成3D视频。
二、VR眼镜盒子
VR眼镜盒子是一种较为基础且便捷的虚拟现实设备。其外观通常小巧轻便,便于携带和使用,主体部分多为一个类似眼镜的框架结构,中间有可容纳显示屏的区域,两侧设有绑带或夹子等固定装置,用于将设备稳固地佩戴在头上,确保使用者在使用过程中不会轻易滑落或移位。它的工作原理在于借助智能手机等具备显示功能的设备来作为显示屏,将手机放入盒子中特定的位置后,通过盒子内部的光学镜片等元器件对手机屏幕上的画面进行放大和聚焦,营造出一种身临其境的立体视觉效果。当使用者转动头部时,借助手机内部的陀螺仪等传感器,可实时感知头部的运动方向和角度变化,并将这些信息反馈给正在运行的VR应用,从而使得画面能够相应地进行切换或调整,让使用者仿佛置身于一个全方位、沉浸式的虚拟场景之中,无论是观看3D电影、体验虚拟旅游还是进行一些简单的VR游戏,都能提供较为出色的沉浸感体验。不过,由于其成本相对较低,技术也较为基础,在画面的清晰度、视场角以及帧率等方面可能不如一些高端的VR头显设备,但其亲民的价格和便捷的操作方式使其在普通消费者群体中有着较为广泛的应用,为大众接触和体验虚拟现实技术提供了一个入门级的便捷选择。
假设透镜的焦距为f,透镜与显示屏之间的距离为d,显示屏上的图像高度为h,经过透镜放大后的像高度为H。根据透镜成像公式:
f1=u1+v1
其中,u 为物体到透镜的距离(即显示屏到透镜的距离),v 为像到透镜的距离。对于VR眼镜盒子来说,透镜通常被设计为靠近显示屏的一侧,因此 u 是一个较小的正值。根据成像公式,可以求出像距 v。
像的放大率 M 可以表示为:
M=hH=uv
通过调整透镜的焦距 f 和物体距 u,可以控制像的放大率和成像位置,从而优化用户的视觉体验。VR眼镜盒子利用双眼视觉和视差原理来营造三维立体效果。人类的双眼分别位于头部的两侧,两眼之间的距离(称为瞳距)导致两眼看到的物体图像存在细微差异,这种差异称为视差。大脑通过对两眼图像的融合和处理,能够感知物体的深度和立体感。在VR眼镜盒子中,左右两个透镜分别将两幅略有差异的图像(通常由VR应用生成)投射到用户的左右眼中,模拟了人眼观察真实世界时的视差效果。这种视差信息被大脑处理后,用户就会感受到虚拟场景的深度和立体感。
三、博主的实操记录
1.手搓VR眼镜
VR眼镜的技术原理在之前已经讲的很清楚了,无非就是双目视差罢了,所以实现起来也很简单,找个空纸壳然后折叠成下图这个样子,然后放上两个放大镜片就好了,是不是有手就行。
什么?说没有放大镜片,没事儿,仙君教你:在塑料瓶的上半部分中裁出两个圆片,然后将这两个圆片用胶水粘起来,里面放满水,一个放大镜片这不就做出来了吗?还不会的同学就自己上网买一个吧,也就十来块的样子,没钱的可以在评论区找博主报销。
2.普通视频转成VR视频
这种VR视频比较普通,就是将一个视频变成两个分视角的图片,多的不说,上干货:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt# 加载预训练的深度估计模型和相关文件
def load_depth_model():# 模型和配置文件路径(假设已下载对应的模型文件)model_path = "models/midas_v2_1_small.onnx"# 加载模型depth_model = cv.dnn.readNet(model_path)return depth_model# 深度估计函数
def estimate_depth(frame, depth_model):# 将图片转换为模型需要的格式img = cv.cvtColor(frame, cv.COLOR_BGR2RGB)img = cv.resize(img, (256, 256), interpolation=cv.INTER_AREA)# 创建blobblob = cv.dnn.blobFromImage(img, 1/255., (256, 256), (123.675, 116.28, 103.53), swapRB=True, crop=False)# 设置输入并前向传播depth_model.setInput(blob)depth_map = depth_model.forward()depth_map = depth_map.reshape((256, 256))# 归一化深度图depth_map = cv.normalize(depth_map, None, 0, 1, cv.NORM_MINMAX)return depth_map# 根据深度图计算视差图
def compute_disparity(depth_map, max_disparity=50):# 计算视差图,简单的将深度图转换为视差图# 实际应用中可能需要更复杂的计算disparity_map = (1.0 - depth_map) * max_disparityreturn disparity_map.astype(np.int32)# 根据视差图生成右视图
def generate_right_view(left_view, disparity_map):height, width = left_view.shape[:2]# 将视差图扩展到与图像相同的尺寸disparity_map_img = cv.resize(disparity_map, (width, height), interpolation=cv.INTER_NEAREST)# 创建右视图right_view = np.zeros_like(left_view)# 沿x轴移动每个像素,根据视差图的值(简单的水平位移)for y in range(height):for x in range(width):disp = disparity_map_img[y, x]new_x = x - dispif new_x >= 0 and new_x < width:right_view[y, new_x] = left_view[y, x]else:# 处理边界情况,使用原图的边缘像素填充if new_x < 0:right_view[y, 0] = left_view[y, x]elif new_x >= width:right_view[y, width - 1] = left_view[y, x]return right_view# 读取视频文件
input_video_path = 'input_video.mp4'
output_video_path = 'output_3d_video.mp4'# 打开视频文件
cap = cv.VideoCapture(input_video_path)
if not cap.isOpened():print("Error: Could not open video.")exit()# 获取视频属性
frame_width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv.CAP_PROP_FPS)# 定义视频输出
fourcc = cv.VideoWriter_fourcc(*'MP4V')
out = cv.VideoWriter(output_video_path, fourcc, fps, (frame_width * 2, frame_height))# 加载深度估计模型
depth_model = load_depth_model()# 处理视频的每一帧
while cap.isOpened():ret, frame = cap.read()if not ret:break# 估计深度depth_map = estimate_depth(frame, depth_model)# 计算视差图disparity_map = compute_disparity(depth_map)# 生成右视图right_view = generate_right_view(frame, disparity_map)# 创建左右分屏的3D视频帧stereo_frame = cv.hconcat([frame, right_view])# 写入输出视频文件out.write(stereo_frame)# 显示处理后的帧(可选)cv.imshow('3D Video', cv.resize(stereo_frame, (frame_width * 2 // 2, frame_height // 2)))# 按'q'键退出循环if cv.waitKey(1) & 0xFF == ord('q'):break# 释放资源
cap.release()
out.release()
cv.destroyAllWindows()
以上代码使用深度估计模型来估计每一帧图像的深度,然后根据深度图计算视差图,最后根据视差图生成右视图。需要注意的是,这种方法的效果可能不是非常好,实际应用中可能需要更复杂的视差计算方法,例如使用立体匹配算法等。
相关文章:

浅论3DGS溅射模型在VR眼镜上的应用
摆烂仙君小课堂开课了,本期将介绍如何手搓VR眼镜,并将随手拍的电影变成3D视频。 一、3DGS模型介绍 3D 高斯模型是基于高斯函数构建的用于描述三维空间中数据分布概率的模型,高斯函数在数学和物理领域有着广泛应用,其在 3D 情境下…...

6种方式来探究数据集的的方法worldquant
覆盖率百分比 指金融数据字段(如股价、成交量、财务指标)在时间或空间上的有效数据比例。 时间维度:数据在历史周期内的完整度(如:某股票过去 1 年中,95% 的交易日有收盘价)。空间维度…...

深度学习中的归一化:提升模型性能的关键因素
📌 友情提示: 本文内容由银河易创AI(https://ai.eaigx.com)创作平台的gpt-4-turbo模型辅助完成,旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证,建议读者通过官方文档或实践进一步确认…...

vue+threeJS 大理石贴图
嗨,我是小路。今天主要和大家分享的主题是“vuethreeJS 大理石贴图”。 通过 Vue 3 和 Three.js 实现大理石纹理效果,并将这种技术应用于产品展示、虚拟展览、甚至是互动游戏之中,其潜力无穷。今天主要介绍基础的大理石贴图。 vueth…...

WebGL 3着色器和GLSL
我们之前提到过着色器和GLSL,但是没有涉及细节,你可能已经对此有所了解, 但以防万一,这里将详细讲解着色器和GLSL。 在工作原理中我们提到,WebGL每次绘制需要两个着色器, 一个顶点着色器和一个片段着色器&…...
vscode debug node + 前端
方法 2:调试全栈(Node 前端) 如果需同时调试后端和前端: 分别启动两个调试会话 一个配置调试 Node.js 后端(server.js)。 另一个配置调试浏览器前端(如上)。 {// Use IntelliS…...
Python训练营打卡 Day27
函数专题2:装饰器 知识点回顾: 装饰器的思想:进一步复用函数的装饰器写法注意内部函数的返回值 昨天我们接触到了函数大部分的功能,然后在你日常ctrl点进某个复杂的项目,发现函数上方有一个xxx,它就是装饰器 装饰器本质…...

华为OD机试真题——通信系统策略调度(用户调度问题)(2025B卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
2025 B卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…...
SQL实战:06交叉日期打折问题求解
文章目录 概述题目:交叉打折问题求解题解第一步:使用滑动窗口统计当前活动前的最大结束日期步骤二:拆分出交叉部分步骤三:计算每次活动的持续天数步骤四:分组统计最终结果完整SQL 概述 最近刷题时遇到一些比较有意思的…...
升级kafka4.0.0,无ZK版本
设备规划: 172.20.192.47 kafka-0 172.20.192.48 kafka-1 172.20.192.49 kafka-2 单机块7TB Nvme磁盘一共9块 # 格式化成GPT分区 sudo parted /dev/nvme0n1 --script mklabel gpt sudo parted /dev/nvme1n1 --script mklabel gpt sudo parted /dev/nvme2n1 --s…...

llamafactory SFT 从断点恢复训练
背景 我使用llamafactory sft 微调模型的时候。gpu停止运行了。日志文件没有任何的报错信息。 显存还是占用状态。 查看llamafactory的进程是下述信息: 151312 151306 91 17:42 ? 03:58:10 [llamafactory-cl] 既然如此,那就只能从断点恢复训练了。 …...
PCL 计算一条射线与二次曲面的交点
文章目录 一、简介二、实现代码三、实现效果一、简介 对于二次曲面而言,其一般方程可以写为: z = a 0 + a 1 x + a 2 y + a...

计算机网络-----6分层结构
目录 “分层” 的设计思想: 计算机网络要完成的功能: 计算机网络的分层结构: 网络体系结构的概念: 各层之间的关系: 数据的传输过程 水平视角: 垂直视角: 相关概念 协议三要素&#x…...

运算放大器相关的电路
1运算放大器介绍 解释:运算放大器本质就是一个放大倍数很大的元件,就如上图公式所示 Vp和Vn相差很小但是放大后输出还是会很大。 运算放大器不止上面的三个引脚,他需要独立供电; 如图比较器: 解释:Vp&…...
BM25 算法与关键词提取在向量数据库中的实践优化
BM25 算法与关键词提取在向量数据库中的实践优化 在实际构建问答系统或语义检索场景中,向量数据库(如 Weaviate)提供了基于语义匹配的检索能力,然而我们发现 BM25 关键词检索效果不理想,甚至出现了召回率过低、查询必…...

python版本管理工具-pyenv轻松切换多个Python版本
在使用python环境开发时,相信肯定被使用版本所烦恼,在用第三方库时依赖兼容的python版本不一样,有没有一个能同时安装多个python并能自由切换的工具呢,那就是pyenv,让你可以轻松切换多个Python 版本。 pyenv是什么 p…...
Elasticsearch索引全生命周期管理指南之一
#作者:猎人 文章目录 一、索引常规操作二、索引mapping和别名管理 一、索引常规操作 索引数据特点: 索引中的数据随着时间,持续不断增长 按照时间序列划分索引的好处&挑战: 按照时间进行划分索引,会使得管理更加…...
STM32F407VET6的HAL库使用CRC校验的思路
CRC校验在数据传输快,且量大的时候使用。 步骤实现: CubeMX配置 c // 在CubeMX中启用CRC模块 // AHB总线时钟自动启用 HAL库代码 c // 初始化(main函数中) CRC_HandleTypeDef hcrc; hcrc.Instance CRC; hcrc.Init.Default…...
【Manim】使用manim画一个高斯分布的动画
1 Manim例子一 最近接触到manim,觉得挺有趣的,来玩一玩把。如下是一个使用manim画的高斯分布的动画。 from manim import * import numpy as npclass GaussianDistribution(Scene):def construct(self):# 创建坐标系axes Axes(x_range[-4, 4, 1],y_ra…...

elementUI 循环出来的表单,怎么做表单校验?
数据结构如下: diversionParamList: [ { length: null, positionNumber: null, value: null, } ] 思路:可根据 index 动态绑定 :props 属性值,校验规则写在:rules <div class"config-item" v-for"(item, index) in form.…...

Leetcode76覆盖最小子串
覆盖最小子串 代码来自b站左程云 class Solution {public String minWindow(String str, String tar) {char[] s str.toCharArray();char[] t tar.toCharArray();int[] cnt new int[256];for (char cha : t) { cnt[cha]--;}int len Integer.MAX_VALUE;int debt t.length…...

电力杆塔安全监测解决方案
一、方案背景 在台风、滑坡等自然灾害出现时,极易产生倒杆、断杆、杆塔倾斜、塔基滑动等致使杆塔失稳的状况,进而引发导线断线、线路跳闸等事故,给电网的安全稳定运行造成影响。可借助在铁塔上装设的传感器,能够感知铁塔的工作状态…...

AD 常用系统快捷键
(1) L: 打开层设置开关选项(在元件移动状态下,按下“L”键换层) (2) S: 打开选择,如SL(线选)、SI(框选)、SE(滑动选择) (3) J: 跳转,如JC(跳转到元件)、JN(跳转到网络) (4) CtrlQ: 英寸和毫米相互切换。 (5) Delete: 删除已被选择的对象 E…...

今日行情明日机会——20250516
上证缩量收阴线,小盘股表现相对更好,上涨的个股大于下跌的,日线已到前期压力位附近,注意风险。 深证缩量收假阳线,临近日线周期上涨末端,注意风险。 2025年5月16日涨停股行业方向分析 机器人概念&#x…...

AlphaEvolve:LLM驱动的算法进化革命与科学发现新范式
AlphaEvolve:LLM驱动的算法进化革命与科学发现新范式 本文聚焦Google DeepMind最新发布的AlphaEvolve,探讨其如何通过LLM与进化算法的结合,在数学难题突破、计算基础设施优化等领域实现革命性进展。从48次乘法优化44矩阵相乘到数据中心资源利…...

多尺度对比度调整
一、背景介绍 受到了前面锐化算法实现的启发,对高频层做增强是锐化,那么对中低频一起做增强,就应该能有局域对比度增强效果。 直接暴力实现了个基本版本,确实有对比度增强效果。然后搜了下关键字,还真找到了已经有人这…...

解决IDEA Maven编译时@spring.profiles.active@没有替换成具体环境变量的问题
如果不加filtering true,编译后的文件还是 spring.profiles.active 编译前的application.yml 编译后的application.yml【环境变量没有改变】 解决方案 找到 SpringBoot 启动类所在的pom.xml,在 resources 增加 filtering true,然后重新…...
博客系统技术需求文档(基于 Flask)
以下内容是AI基于要求生成的技术文档,仅供参考~ 🧱 一、系统架构设计概览 层级 内容 前端层 HTML Jinja2 模板引擎,集成 Markdown 编辑器、代码高亮 后端层 Flask 框架,RESTful 风格,Jinja2 渲染 数据库 SQLi…...

记参加一次数学建模
题目请到全国大学生数学建模竞赛下载查看。 注:过程更新了很多文件,所有这里贴上的有些内容不是最新的(而是草稿)。 注:我们队伍并没有获奖,文章内容仅供一乐。 从这次比赛,给出以下赛前建议 …...
TC8:SOMEIP_ETS_029-030
SOMEIP_ETS_029: echoUINT8Array16Bitlength 目的 检查当method echoUINT8Array16BitLength的参数中长度字段为16bit时,SOME/IP协议层是否能对参数进行序列化和反序列化。 对于可变长度的数组而言,必须用长度字段表示数组长度。否则接收方无法判断有效数据。 SOMEIP_ETS_02…...