笔记本上轻松实现裸眼3D

本文将详细介绍我的一个个人项目:如何仅使用浏览器、一个普通的笔记本摄像头three.js 库,来实现一个“虚拟窗口”特效。这种技术也被称为头部耦合透视(Head-Coupled Perspective)或动态离轴3D错觉,其效果是让电脑屏幕看起来像一扇通往三维世界的窗户,随着你头部的移动,你所看到的景物透视也会实时发生变化。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


一、思路总览:化繁为简

这个项目的灵感来源于一些已有的实现,但那些项目通常需要专门的硬件或复杂的配置流程。我的目标是用更易于获取的工具来达到类似的效果。下面是传统方法与我所采用的、基于Web的简化方法的对比。

步骤类似项目做法我的Web端做法关键差异
1. 摄像头标定拍摄数十张棋盘格照片,并用 OpenCV 精确计算摄像头内参。初始化一个估算参数,然后通过对比计算深度与物理测量深度的偏差,来手动、快速地调整参数。简洁高效。我的方法避免了繁琐的标定流程,对于此应用场景来说“足够好”。
2. 眼动追踪使用 Face Mesh 实时定位虹膜,通过针孔相机模型计算出眼睛的三维位置。与原项目基本一致。MediaPipe 的 Face Mesh 方案成熟且能在浏览器中高效运行。
3. 虚拟世界构建使用原生图形引擎构建3D场景,并将虚拟摄像机放置在眼睛的位置。使用 three.js 框架来构建场景和管理摄像机。高可用性three.js 使项目能够跨平台运行,并且非常容易在网页上分享。
4. 离轴透视投影使用一个离轴(off-axis)投影矩阵来“扭曲”视锥体,确保3D场景始终能完美填充屏幕“窗口”。与原项目基本一致。这是实现整个错觉背后的核心数学原理。
5. 项目演示展示靶心、僵尸或虚拟橱窗等不同场景,让物体有“跳出”屏幕的感觉。复刻经典的“靶心(Targets)”场景来验证和展示效果。简化范围

最终目标是统一的:使用浏览器和普通摄像头,生成一个动态的、基于离轴投影的三维窗口错觉。
在这里插入图片描述


二、第一步:“足够好”的摄像头内参计算

目标: 获取摄像头的内参,主要是焦距(focal length),这是后续计算眼睛空间深度的关键。

传统方法需要使用棋盘格进行繁琐的标定,虽然精确但非常耗时。我问自己:有没有更简单有效的方法?

我的做法: 我利用了视场角(FOV)和焦距之间的数学关系。

焦距 = (图像宽度像素值 / 2) / tan(FOV / 2)

我没有直接去计算焦距,而是决定反过来调整FOV,直到整个系统输出正确的结果。具体流程如下:

  1. 初始化: 为摄像头的FOV设置一个初始猜测值(比如 50 度)。
  2. 计算与对比: 程序会使用这个FOV值实时计算出用户眼睛的深度(Z坐标)并显示在屏幕上。
  3. 物理测量: 我用一把尺子实际测量自己与屏幕之间的距离。
  4. 手动调节: 我通过界面上的控制滑块,不断调整FOV的值,直到屏幕上显示的计算深度与我物理测量的深度基本吻合。

这种交互式的反馈循环使得标定过程非常迅速,并且精度足以满足本项目的需求。

在这里插入图片描述


三、第二步:计算眼睛的三维空间坐标

当摄像头“标定”完成后,我们就可以计算用户眼睛相对于摄像头的三维坐标(X, Y, Z)了。

  1. 2D虹膜检测: 我使用可在浏览器中运行的 MediaPipe Face Mesh 来检测虹膜边缘的关键点。通过这些点,我可以计算出虹膜在视频画面中的像素尺寸

  2. 计算深度(Z坐标): 利用针孔相机模型(其原理是相似三角形),我们可以计算出眼睛到摄像头的距离。公式如下:

    深度 = (焦距 × 真实虹膜尺寸) / 虹膜的像素尺寸

    人眼虹膜的真实直径相当恒定,平均约为 11.7毫米。这为我们的公式提供了一个可靠的“真实尺寸”参考。

  3. 计算X和Y坐标: 在深度已知后,我们同样利用相似三角形原理,可以计算出水平(X)和垂直(Y)方向的坐标:

    X坐标 = (虹膜中心点的像素X偏移 × 深度) / 焦距

    Y坐标 = (虹膜中心点的像素Y偏移 × 深度) / 焦距

    这里的“像素X/Y偏移”指的是虹膜中心相对于摄像头画面中心的2D像素坐标。
    在这里插入图片描述


四、第三步:使用 three.js 构建虚拟场景

目标: 创建一个3D场景,其中虚拟摄像机的位置与用户真实眼睛的位置完美同步。

  1. 场景原点与屏幕: 我将摄像头的位置定义为3D世界的原点(0, 0, 0)。然后,我将物理屏幕建模为这个空间中的一个矩形平面。我测量了我的笔记本屏幕尺寸(长34.5cm,宽19.4cm),并在场景中按这个尺寸和实际距离创建了一个虚拟屏幕。

  2. 虚拟摄像机与眼睛位置同步: 我将上一步计算出的眼睛三维坐标,直接赋值给 three.js 场景中的虚拟摄像机的位置。这样,当我真实世界的眼睛移动时,虚拟世界中的摄像机也随之移动。

  3. 复刻演示场景: 为了展示效果,我复刻了经典的“Targets”场景。这包括:

    • 定义空间感的四周网格。
    • “Targets”文字标签。
    • 多个漂浮在空中的、色彩鲜艳的同心圆环体。
    • 一个简单的“击中”目标的动画效果。

在这里插入图片描述


五、第四步:魔法核心 - 离轴透视投影

目标: 确保无论眼睛(虚拟摄像机)移动到哪里,3D场景的视野都能精确地、不偏不倚地充满整个物理屏幕。

标准的透视投影假设观察者正对着视锥体的中心。如果我们的虚拟摄像机偏离了中心,部分场景就会被裁切掉,错觉就会被打破。

解决方案是 离轴透视投影(Off-Axis Perspective Projection)。它能创建一个不对称(或称“斜视”)的视锥体,这个视锥体被精确地扭曲,使其边界从摄像机当前的位置看去,正好与屏幕的四个边缘对齐。

实现过程如下:

  1. 计算非对称视锥体边界: 根据眼睛的三维位置和虚拟屏幕四个角点的相对位置,利用相似三角形原理,计算出近裁剪平面(near clipping plane)上所需的左、右、上、下边界偏移量。
  2. 构建并应用矩阵: 使用这些计算出的边界值来构建一个新的4x4离轴投影矩阵。在three.js中,可以通过 Camera.projectionMatrix.makePerspective(left, right, top, bottom, near, far) 方法来实现。最后,将这个新矩阵应用到摄像机的 projectionMatrix 属性上。
    在这里插入图片描述

六、项目演示与完整代码

Github完整代码(含完整代码、PPT讲解):https://github.com/aug618/VR-on-2D(觉得有意思或者有帮助的话,麻烦请你点个star哦~)

B站视频演示:https://www.bilibili.com/video/BV1m1TMzuEjL/


七、补充与思考

在这里插入图片描述

这个项目是一次在计算机视觉、3D图形学和创造性解决问题方面的绝佳实践。通过用更简单、Web友好的方案替代复杂、专业的步骤,我们可以让强大的视觉错觉技术变得更加触手可及。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值