流式直播镜头从相机到Unity3D

本文关键字:相机 Unity3D 直播 | 更新日期: 2023-09-27 18:06:56

假设我有一个无线摄像机,我想实时地将镜头流式传输到unity。有办法做到这一点吗?

奖金问题:

  • 广角相机呢(180,甚至360)
  • 如果这是一个我想与之交互的素材,延迟会有多大的问题?
  • 可能发送更多的数据,如深度感知(使用深度感知相机)除了常规镜头之外?
  • 是我疯了还是这已经完成了?

Thanks in advance

流式直播镜头从相机到Unity3D

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

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

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

连接到相机:

1

。与摄像机连接到同一个本地网络,如果支持unpn,也可以通过internet连接。通常,你需要IP和摄像头的端口来做这个。假设摄像机的IP地址为192.168.1.5,端口号为900。连接的url为http://192.168.1.5:900

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

每个相机都是不同的。找到url的唯一方法是阅读它的手册。如果没有手册,请使用其官方应用程序连接,然后使用Wireshark发现相机图像的url。usernamepassword(如果需要)也可以在手册中找到。如果没有,谷歌一下型号,你需要的一切都可以找到。

从相机中提取JPEG :

当连接到相机时,相机将向您发送无尽的数据。您可以扫描这些数据并从中检索图像。

2

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

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

3 。当从相机读取数据时,检查接下来的两个字节是否为JPEG页脚,即0xFF0xD9。如果这是真的,那么你已经收到了完整的图像(1帧)。

您的图像字节应该看起来像:

0xFF 0xD8 someotherbytes(数千个).....then 0xFF 0xD9

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

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

显示JPEG图像到屏幕:

4

。显示图像到屏幕

由于您将每秒接收许多图像,因此我发现显示此内容的最有效方法是使用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();
    }
}

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

控制相机

:

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

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

其他框架

:

AForge -一个可以处理JPEG/MJPES和FFMPEG的免费框架。你必须修改它以与Unity一起工作,如果你不能执行步骤2345