我正在尝试在Unity3D的飞机上制作相机。我正在使用AForge文档中的代码:http://www.aforgenet.com/framework/docs/html/f4d3c2ba-605c-f066-f969-68260ce5e141.htm 除了我通过Unity而不是AForges通常的方式插入网络摄像头,它想要制作FilterInfoCollection。如果我没错,Unity需要识别网络摄像头。
然而,我的代码无法正常工作,网络摄像头启动(因为我的webCam.Play()),但没有其他事情发生。通过调试我发现程序没有到达我的video_NewFrame函数,我相信在使用Unity时我需要以某种方式进行初始化?
如何正确设置?
using UnityEngine;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Imaging.Filters;
using AForge.Imaging;
using AForge;
public class LoadVideo : MonoBehaviour {
public VideoCaptureDevice videoSource;
WebCamTexture webCam;
void Start(){
webCam = new WebCamTexture();
webCam.Play();
}
// Update is called once per frame
object b;
public WebCamDevice wc;
public GameObject originalFeed;
void Update () {
videoSource = new VideoCaptureDevice(webCam.deviceName);
videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
videoSource.Start();
originalFeed.GetComponent<Renderer>().material.mainTexture = originalFeedTexture;
}
public delegate void EventPrototype(System.EventArgs args);
Texture2D originalFeedTexture;
void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Debug.Log("you here mate");
Bitmap video = (Bitmap)eventArgs.Frame.Clone();
MemoryStream memoryStream = new MemoryStream();
video.Save(memoryStream, ImageFormat.Jpeg);
byte[] bitmapRecord = memoryStream.ToArray();
originalFeedTexture.LoadImage(bitmapRecord);
}
}
答案 0 :(得分:1)
首先,我不确定 AForge 是否适用于Unity。原因是它使用.NET 4或更多,而Unity使用.NET 3.5。
除此之外,您的代码中存在一些问题。
1 。 Unity 使用WebCamTexture
开始从相机捕获帧。
2 。VideoCaptureDevice
开始从相机捕获帧。
4个问题:
1 。你必须使用一个而不是两个。你无法将两者结合起来,我相信一次只能从一个地方访问摄像机。
当您执行webCam.Play();
然后videoSource.Start();
时,您正尝试使用多个API中的一个摄像头。如果您想使用 AForge API,则应使用VideoCaptureDevice
。
2 。您正在呼叫videoSource = new VideoCaptureDevice(webCam.deviceName);
,并在videoSource.Start();
功能的每一帧启动Update
相机。这应该通过将其移动到Start
函数来完成一次。您还需要注册一次NewFrame
事件。
第3 即可。 originalFeedTexture
未初始化,但在video_NewFrame
和Update
函数中使用。
4 。您可以使用WebCamDevice
课程获取网络摄像头名称。最后的示例代码显示了如何。不要使用WebCamTexture
。
5 。极有可能从另一个videoSource.NewFrame
调用/调用Thread
。因此,当调用video_NewFrame
函数时,originalFeedTexture.LoadImage(bitmapRecord);
代码行将抛出如下所示的异常:
....只能从主线程中调用
您必须找到一种方法在Unity的主线程或更新功能中调用该行代码,因为您无法在另一个Thread
中使用Unity API(Texture2D / originalFeedTexture)。
从下面的代码开始,也许你可以让它运作起来。由于.NET
版本差异,不确定这整个 AForge + Unity 的事情。问题#5 未在此解决方案中修复。您可以使用Unity Threading Helper插件(免费)。
public class LoadVideo : MonoBehaviour
{
public VideoCaptureDevice videoSource;
public GameObject originalFeed;
Texture2D originalFeedTexture;
void Start()
{
init();
}
void init()
{
originalFeedTexture = new Texture2D(128, 128);
//Get WebCam names
WebCamDevice[] devices = WebCamTexture.devices;
if (devices.Length <= 0)
{
Debug.LogError("No Web Cam Found....Exiting");
return; //Exit
}
videoSource = new VideoCaptureDevice(devices[0].name);
videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
videoSource.Start();
}
void stop()
{
videoSource.SignalToStop();
}
void Update ()
{
originalFeed.GetComponent<Renderer>().material.mainTexture = originalFeedTexture;
}
public delegate void EventPrototype(System.EventArgs args);
void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Debug.Log("you here mate");
Bitmap video = (Bitmap)eventArgs.Frame.Clone();
MemoryStream memoryStream = new MemoryStream();
video.Save(memoryStream, ImageFormat.Jpeg);
byte[] bitmapRecord = memoryStream.ToArray();
originalFeedTexture.LoadImage(bitmapRecord);
}
//Make sure to stop when run time ends
void OnDisable()
{
stop();
}
}
我正在尝试将相机分成帧,然后我就可以使用了 AForges方法。
如果这就是你想要做的,你可以使用Unity WebCamTexture
然后将其转换为Texture2D
:
WebCamTexture webCam = new WebCamTexture (160, 120);
webCam.play();
Texture2D originalFeedTexture = new Texture2D(webCam.width, webCam.height);
originalFeedTexture.SetPixels(webCam.GetPixels());
originalFeedTexture.Apply();
///Use it then destroy it
Object.Destroy(originalFeedTexture);
框架现在存储在originalFeedTexture
变量中。
如果您需要Texture2D
帧作为字节,可能需要通过网络发送:
JPG
字节:
byte[] bytes = originalFeedTexture.EncodeToJPG();
PNG
字节:
byte[] bytes = originalFeedTexture.EncodeToPNG();