使 AForge VideoCaptureDevice 与 Unity 一起工作

Making AForge VideoCaptureDevice work with Unity

我正在尝试在 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);
    }

}

首先,我不确定 AForge 是否可以在 Unity 中运行。原因是因为它使用.NET 4或更高版本,而Unity使用.NET 3.5。

除此之外,您的代码中还有几个问题。

1WebCamTextureUnity 用于开始从相机捕获帧。

2VideoCaptureDeviceAForge 用于开始从相机捕获帧。

4个问题:

1。您必须使用一个,不能同时使用两个。你不能将两者结合起来,我相信一次可以从一个位置访问相机。

当您 webCam.Play(); 然后 videoSource.Start(); 时,您正在尝试使用多个 API 中的一个摄像头。如果要使用 AForge API.

,则应使用 VideoCaptureDevice

2。您正在调用 videoSource = new VideoCaptureDevice(webCam.deviceName); 并在 Update 函数中每帧以 videoSource.Start(); 启动相机。这应该通过将其移动到 Start 函数来完成一次。您还需要注册一次NewFrame活动。

3originalFeedTexture 未初始化,但在 video_NewFrameUpdate 函数中使用。

4。您可以使用 WebCamDevice class 获取网络摄像头名称。最后的示例代码显示了如何。不要为此使用 WebCamTexture

5。极有可能videoSource.NewFrame是另一个Thread的invoked/called。因此,当您的 video_NewFrame 函数被调用时,originalFeedTexture.LoadImage(bitmapRecord); 行代码将抛出如下所示的异常:

.... can only be called from the main thread

您可能必须找到一种方法在 Unity 的主线程或更新函数中调用该行代码,因为您不能在另一个 [=30] 中使用 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();
    }
}

I am trying to split the camera into frames, on which I then can use AForges methods.

如果这就是你想要做的,你可以使用 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();