将实时镜头从摄像机流式传输到 Unity3D
Streaming live footage from camera to Unity3D
假设我有一个无线摄像头,我想将其实时流式传输到 Unity。有办法实现吗?
奖励问题:
- 更广角(180,甚至可能是 360)的相机呢
- 如果这是我想与之互动的镜头,延迟会有多大的问题
- 是否可以在常规镜头之外发送更多数据,例如深度感知(使用深度感知相机)?
- 我是疯了还是已经完成了?
提前致谢
我假设这是一台带以太网端口的相机或 Wi-Fi,您可以连接到它并从中实时传输图像。
如果是这样,那么是的,可以用Unity来完成。
如何在没有外部库的情况下完成:
正在连接相机:
1.使用相机连接到the-same本地网络,或者如果支持unpn,您也可以通过互联网连接到它。通常,您需要摄像机的 IP 和端口来执行此操作。假设摄像机 IP 地址为 192.168.1.5
,端口号为 900
。要连接的 url 是 http://192.168.1.5:900
。
有时,它只是一个以.mjpg或.bin结尾的url,例如http://192.168.1.5/mjpg/video.mjpg
和 http://192.168.1.5/mjpg/video.bin
每个相机都不一样。找到 url 的唯一方法是阅读其手册。如果手册不可用,请使用其官方应用程序连接到它,然后使用 Wireshark 发现相机图像的 url。 username
和 password
(如果需要)也可以在手册中找到。如果没有,google 型号和您需要的一切都应该找到。
正在从相机中提取 JPEG:
当连接到相机时,相机会向您发送无穷无尽的数据。您可以扫描此数据并从中检索图像。
2。搜索 JPEG header,即 0xFF
后跟 0xD8
。如果这两个字节彼此相邻,则开始读取字节并继续将它们保存到数组中。您可以使用 index(int
) 变量来计算您收到的字节数。
int counter = 0;
byte[] completeImageByte = new byte[500000];
byte[] receivedBytes = new byte[500000];
receivedBytes[counter] = byteFromCamera;
counter++;
3。从相机读取数据时,检查接下来的两个字节是否为 JPEG 页脚,即 0xFF
后跟 0xD9
。如果这是真的,那么您已经收到完整的图像(1 帧)。
您的图像字节应该类似于:
0xFF
0xD8
someotherbytes(数千字节)..... 然后 0xFF
0xD9
将receivedBytes
复制到completeImageByte
变量中,以便稍后可以使用它来显示图像。将 counter
变量重置为 0。
Buffer.BlockCopy(receivedBytes, 0, completeImageByte, 0, counter);
counter = 0;
在屏幕上显示 JPEG 图像:
4. 将图像显示到屏幕
由于您每秒会收到很多图像,因此我发现最 efficient 的显示方式是使用 RawImage
组件。因此,如果您希望它在移动设备上 运行,请不要为此使用 Image
或 Sprite 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
. When using UnityWebRequest
, you must derive your own classes from DownloadHandlerScript
否则您的应用会崩溃,因为您将不停地接收数据。
从 DownloadHandlerScript
导出您自己的 class 的示例:
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();
}
}
您可以让他们执行步骤 2、3、4 和 5 在 CustomWebRequest
脚本的 ReceiveData
函数中。
控制相机:
相机有平移、旋转、翻转、镜像和执行其他操作的命令 function.This 每个相机都不同,但很简单,只需向 url 发出 GET/POST 请求相机并提供查询。这些命令可以在相机手册中找到。
例如:http://192.168.1.5?pan=50&rotate=90
其他框架:
AForge - A free framework that can handle both JPEG/MJPES and FFMPEG 来自相机。你必须修改它以与 Unity 一起工作,如果你不能执行步骤 2,3,4 和 5.
假设我有一个无线摄像头,我想将其实时流式传输到 Unity。有办法实现吗?
奖励问题:
- 更广角(180,甚至可能是 360)的相机呢
- 如果这是我想与之互动的镜头,延迟会有多大的问题
- 是否可以在常规镜头之外发送更多数据,例如深度感知(使用深度感知相机)?
- 我是疯了还是已经完成了?
提前致谢
我假设这是一台带以太网端口的相机或 Wi-Fi,您可以连接到它并从中实时传输图像。
如果是这样,那么是的,可以用Unity来完成。
如何在没有外部库的情况下完成:
正在连接相机:
1.使用相机连接到the-same本地网络,或者如果支持unpn,您也可以通过互联网连接到它。通常,您需要摄像机的 IP 和端口来执行此操作。假设摄像机 IP 地址为 192.168.1.5
,端口号为 900
。要连接的 url 是 http://192.168.1.5:900
。
有时,它只是一个以.mjpg或.bin结尾的url,例如http://192.168.1.5/mjpg/video.mjpg
和 http://192.168.1.5/mjpg/video.bin
每个相机都不一样。找到 url 的唯一方法是阅读其手册。如果手册不可用,请使用其官方应用程序连接到它,然后使用 Wireshark 发现相机图像的 url。 username
和 password
(如果需要)也可以在手册中找到。如果没有,google 型号和您需要的一切都应该找到。
正在从相机中提取 JPEG:
当连接到相机时,相机会向您发送无穷无尽的数据。您可以扫描此数据并从中检索图像。
2。搜索 JPEG header,即 0xFF
后跟 0xD8
。如果这两个字节彼此相邻,则开始读取字节并继续将它们保存到数组中。您可以使用 index(int
) 变量来计算您收到的字节数。
int counter = 0;
byte[] completeImageByte = new byte[500000];
byte[] receivedBytes = new byte[500000];
receivedBytes[counter] = byteFromCamera;
counter++;
3。从相机读取数据时,检查接下来的两个字节是否为 JPEG 页脚,即 0xFF
后跟 0xD9
。如果这是真的,那么您已经收到完整的图像(1 帧)。
您的图像字节应该类似于:
0xFF
0xD8
someotherbytes(数千字节)..... 然后 0xFF
0xD9
将receivedBytes
复制到completeImageByte
变量中,以便稍后可以使用它来显示图像。将 counter
变量重置为 0。
Buffer.BlockCopy(receivedBytes, 0, completeImageByte, 0, counter);
counter = 0;
在屏幕上显示 JPEG 图像:
4. 将图像显示到屏幕
由于您每秒会收到很多图像,因此我发现最 efficient 的显示方式是使用 RawImage
组件。因此,如果您希望它在移动设备上 运行,请不要为此使用 Image
或 Sprite 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
. When using UnityWebRequest
, you must derive your own classes from DownloadHandlerScript
否则您的应用会崩溃,因为您将不停地接收数据。
从 DownloadHandlerScript
导出您自己的 class 的示例:
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();
}
}
您可以让他们执行步骤 2、3、4 和 5 在 CustomWebRequest
脚本的 ReceiveData
函数中。
控制相机:
相机有平移、旋转、翻转、镜像和执行其他操作的命令 function.This 每个相机都不同,但很简单,只需向 url 发出 GET/POST 请求相机并提供查询。这些命令可以在相机手册中找到。
例如:http://192.168.1.5?pan=50&rotate=90
其他框架:
AForge - A free framework that can handle both JPEG/MJPES and FFMPEG 来自相机。你必须修改它以与 Unity 一起工作,如果你不能执行步骤 2,3,4 和 5.