使AForge VideoCaptureDevice与Unity协同工作

时间:2016-11-02 14:38:20

标签: c# unity3d aforge

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

}

1 个答案:

答案 0 :(得分:1)

首先,我不确定 AForge 是否适用于Unity。原因是它使用.NET 4或更多,而Unity使用.NET 3.5。

除此之外,您的代码中存在一些问题。

1 Unity 使用WebCamTexture开始从相机捕获帧。

AForge 使用

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_NewFrameUpdate函数中使用。

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();