将实时镜头从摄像机流式传输到 Unity3D

Posted

技术标签:

【中文标题】将实时镜头从摄像机流式传输到 Unity3D【英文标题】:Streaming live footage from camera to Unity3D 【发布时间】:2016-09-14 16:01:59 【问题描述】:

假设我有一台无线摄像机,我想将镜头实时传输到 Unity。有没有办法做到这一点?

额外问题:

更广角(180 度,甚至 360 度)的相机呢 如果这是我想与之互动的片段,延迟会有多大问题 除了常规镜头之外,是否可以发送更多数据,例如深度感知(使用深度感知相机)? 是我疯了还是已经这样做了?

提前致谢

【问题讨论】:

【参考方案1】:

我假设这是一台带有以太网端口或 Wi-Fi 的相机,您可以连接到它并从中实时流式传输图像。

如果是这样,那么是的,可以使用 Unity 完成。

如何在没有外部库的情况下完成

连接到相机

1.连接到与相机相同的本地网络,或者如果支持unpn,您也可以通过互联网连接到它。通常,您需要摄像机的 IP 和端口来执行此操作。假设摄像机 IP 地址为192.168.1.5,端口号为900。要连接的网址是http://192.168.1.5:900

有时,它只是一个以 .mjpg.bin 结尾的 url,例如 http://192.168.1.5/mjpg/video.mjpghttp://192.168.1.5/mjpg/video.bin

每台相机都是不同的。找到该网址的唯一方法是阅读其手册。如果该手册不可用,请使用其官方应用程序连接到它,然后使用 Wireshark 发现相机图像的 url。 usernamepassword(如果需要)也可以在手册中找到。如果没有,请在 Google 上搜索型号,您需要的所有东西都应找到。

从相机中提取 JPEG

连接到相机后,相机会不断地向您发送数据。您可以扫描这些数据并从中检索图像。

2. 搜索 0xFF 后跟 0xD8 的 JPEG 标头。如果这两个字节彼此相邻,则开始读取字节并继续将它们保存到数组中。您可以使用 index(int) 变量来计算收到的字节数。

int counter = 0;
byte[] completeImageByte = new byte[500000];
byte[] receivedBytes = new byte[500000];
receivedBytes[counter] = byteFromCamera;
counter++;

3.在从摄像头读取数据时,检查接下来的两个字节是否是JPEG页脚,即0xFF后跟0xD9。如果这是真的,那么您已经收到了完整的图像(1 帧)。

您的图像字节应如下所示:

0xFF0xD8 someotherbytes(数千个).....然后0xFF0xD9

receivedBytes 复制到completeImageByte 变量,以便以后可以使用它来显示图像。将 counter 变量重置为 0。

Buffer.BlockCopy(receivedBytes, 0, completeImageByte, 0, counter);
counter = 0;

在屏幕上显示 JPEG 图像

4.将图像显示到屏幕

由于您每秒将收到许多图像,因此我发现显示此图像的最efficient 方式是使用RawImage 组件。因此,如果您希望它在移动设备上运行,请不要为此使用 ImageSprite Renderer

public RawImage screenDisplay;
if(updateFrame)
Texture2D camTexture = new Texture2D(2, 2);
camTexture.LoadImage(completeImageByte);
screenDisplay.texture = camTexture;

您只需在Start() 函数中执行一次camTexture = new Texture2D(2, 2);

5。跳回步骤2并继续执行,直到您想要完全为止。

用于连接相机的 API:

如果相机需要验证(用户名和密码),请使用HttpWebRequest

对于不需要身份验证的用户,请使用UnityWebRequest。使用UnityWebRequest 时,您必须从DownloadHandlerScript 派生您自己的类,否则您的应用程序将崩溃,因为您将不停地接收数据。

DownloadHandlerScript 派生您自己的类的示例:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class CustomWebRequest : DownloadHandlerScript
    
    // Standard scripted download handler - will allocate memory on each ReceiveData callback
    public CustomWebRequest()
        : base()
    
    

    // Pre-allocated scripted download handler
    // Will reuse the supplied byte array to deliver data.
    // Eliminates memory allocation.
    public CustomWebRequest(byte[] buffer)
        : base(buffer)
    
    

    // Required by DownloadHandler base class. Called when you address the 'bytes' property.
    protected override byte[] GetData()  return null; 

    // Called once per frame when data has been received from the network.
    protected override bool ReceiveData(byte[] byteFromCamera, int dataLength)
    
        if (byteFromCamera == null || byteFromCamera.Length < 1)
        
            //Debug.Log("CustomWebRequest :: ReceiveData - received a null/empty buffer");
            return false;
        

        //Search of JPEG Image here

        return true;
    

    // Called when all data has been received from the server and delivered via ReceiveData
    protected override void CompleteContent()
    
        //Debug.Log("CustomWebRequest :: CompleteContent - DOWNLOAD COMPLETE!");
    

    // Called when a Content-Length header is received from the server.
    protected override void ReceiveContentLength(int contentLength)
    
        //Debug.Log(string.Format("CustomWebRequest :: ReceiveContentLength - length 0", contentLength));
    

用法

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Test : MonoBehaviour


    CustomWebRequest camImage;
    UnityWebRequest webRequest;
    byte[] bytes = new byte[90000];

    void Start()
    
        string url = "http://camUrl/mjpg/video.mjpg";
        webRequest = new UnityWebRequest(url);
        webRequest.downloadHandler = new CustomWebRequest(bytes);
        webRequest.Send();
    

您可以在 ReceiveData 函数中执行步骤 2345 CustomWebRequest 脚本。

控制摄像头

相机具有平移、旋转、翻转、镜像和执行其他功能的命令。这在每个相机中都不同,但它很简单,只需向相机的 url 发出 GET/POST 请求并提供查询。这些命令可以在相机手册中找到。

例如:http://192.168.1.5?pan=50&amp;rotate=90

其他框架

AForge - 一个免费的框架,可以处理来自相机的JPEG/MJPES 和FFMPEG。您必须修改它以使用 Unity,如果您不能执行步骤 2345,则应该修改它

【讨论】:

如果有人想要一个快速的解决方案,可以添加到这个答案中:这是一个无需任何外部库或依赖项即可执行此操作的示例。 github.com/DanielArnett/SampleUnityMjpegViewer @DanielArnett 检查您的链接。我不同意,因为它需要“System.Drawing.dll”。在 Unity 中应该避免这种情况。它根本不适用于每个平台。 感谢您的反馈。有时间我会查看您的回复并更新该存储库以删除 Drawing.dll 依赖项。

以上是关于将实时镜头从摄像机流式传输到 Unity3D的主要内容,如果未能解决你的问题,请参考以下文章

使用 Live555 从连接到 H264 编码器的 IP 摄像机流式传输实时视频

将 iPhone 摄像头实时流式传输到媒体服务器的最佳方式是啥?

将实时网络摄像头流式传输到服务器并返回网络的最佳方式是啥?

使用用户摄像头实时流式传输网页

将实时视频广播从 android 相机流式传输到服务器

寻找一个库/框架将实时视频从 OS X 流式传输到 Wowza 服务器(RTMP)[关闭]