65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 RICOH THETA 相机将 360 度视频流式传输到 VR 头显

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2019年5月23日

CPOL

3分钟阅读

viewsIcon

12122

将来自飞行无人机的 360 度视频实时流式传输到 VR 头显,例如 Oculus Rift 或 HTC Vive

360 度视频流和无人机

无人机被广泛用于工业监控和娱乐,但无法在 Oculus Rift 或 HTC Vive 等 VR 头显中提供沉浸式体验。

沉浸式体验的大部分问题源于使用多个摄像头,这些摄像头可以覆盖无人机的整个全景视野,但当人们在 VR 头显中转头时,无法准确跟踪场景。

为了解决这个问题,Jake Kenin 使用 RICOH THETA V 将视频直播到地面站和 VR 头显。

技术

视频技术

Jake 的解决方案使用 MotionJPEG。这是一种妥协。使用 MotionJPEG 导致分辨率和帧率低于其他技术。虽然相机本身可以以 3840x1920、30fps 的速度传输,但 Jake 目前的解决方案在 0.25 英里的距离上具有以下性能:

  • 在 1920x960 @ 8fps 下约为 250 毫秒的延迟
  • 在 1024x512 @ 30 fps 下约为 100 毫秒的延迟

延迟是指图像在头显中显示所需的时间。 例如,如果您使用控制器移动无人机,您将在大约 1/5 秒后看到移动变化。 您希望延迟尽可能低。 如果延迟太长,将很难驾驶无人机。

当您在头显中观看 360 度视频时,您无法看到整个视频。 大约 2/3 的视频被隐藏。 您转动头部以查看视频的隐藏部分。 1024 像素的视频看起来像 400 像素的视频。

fps 指的是每秒帧数,通常称为帧率。 帧率越高,视频越流畅。 在 8fps 时,视频会明显卡顿。

Jake 测试了其他传输技术,例如 RTMP 和 RTSP,而不是 MotionJPEG。 虽然分辨率和帧率更好,但延迟大于 1 秒,使得无人机难以高速飞行。

由于 MotionJPEG 的限制,Jake 计划使用高压缩视频标准将其项目适配到 4K 视频。

查看器技术

为了将视频流显示到 Oculus Rift 头显中,Jake 使用了带有 NPM 应用程序的 Electron 来提供 OpenVR 绑定。

Jake 还使用了 A-Frame 来实现 VR 功能。

安装技术

为了稳定视频流,Jake 使用了万向节。

获取代码和构建详细信息

构建的详细信息可以在论坛上的一系列 community.theta360.guide 上的帖子中找到。

Jake 编写的 Amelia Viewer 的查看器代码可在 GitHub 上找到

此项目的零件如下所示

由于 MotionJPEG 是一种流,因此您需要读取字节流并显示它。 视频的每一帧都是一张 JPEG 图像。 这是许多开发人员处理实时视频流最困难的部分。 有许多 JavaScript 示例可以读取 bytestream。 这是 Jake 的做法。

        const read = () => {

            reader.read().then(({done, value}) => {
                if (done) {
                    return;
                }
                
                for (let index =0; index < value.length; index++) {
                    
                    // Start of the frame, everything we've till now was header
                    if (value[index] === SOI[0] && value[index+1] === SOI[1]) {
                        contentLength = getLength(headers);
                        imageBuffer = new Uint8Array(
                            new ArrayBuffer(contentLength));
                    }
                    // we're still reading the header.
                    if (contentLength <= 0) {
                        headers += String.fromCharCode(value[index]);
                    }
                    // we're now reading the jpeg. 
                    else if (bytesRead < contentLength){
                        imageBuffer[bytesRead++] = value[index];
                        bytesThisSecond++;
                    }
                    // we're done reading the jpeg. Time to render it. 
                    else {
                        //console.log("jpeg read with bytes : " + bytesRead);
                        
                        // Generate blob of the image and emit event
                        lastFrameImgUrl = URL.createObjectURL(
                            new Blob([imageBuffer], {type: TYPE_JPEG}));
                        var reRenderEvent = new CustomEvent(RERENDER_EVENT, 
                            { detail: lastFrameImgUrl });
                        document.dispatchEvent(
                            reRenderEvent);

                        // Reset for the frame
                        frames++;
                        contentLength = 0;
                        bytesRead = 0;
                        headers = '';
                    }
                }

完整的代码位于他的 GitHub 仓库的这个文件中。

社区认可

Jake 解决了社区已经研究了 3 年的问题。 他赢得了 他成功的项目月度奖

飞行无人机的变化

Jake 的概念类似于 Hugues Perret 的 Fox Sewer Rover。

FOX SEWER ROVER 项目的传输代码可在此处找到:here

在 Raspberry Pi 上测试

Hugues 的代码是用 Python 编写的,可以在 Raspberry Pi 上运行。 如果您想在汽车上试验无人机,这是一个不错的选择。

加入先驱讨论

还有很多事情要做和探索。 这个领域确实处于新生状态。 爱好者有可能取得突破和做出贡献。 如果您有任何问题、意见或贡献,请随时将它们放入我们用作平台的 RICOH THETA 360 相机的开发社区论坛中。

© . All rights reserved.