【问题标题】:Making AForge VideoCaptureDevice work with Unity使 AForge VideoCaptureDevice 与 Unity 一起工作
【发布时间】:2016-11-02 14:38:20
【问题描述】:

我正在尝试在 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
  • @AlessandroD'Andria 2.2.5
  • 我在使用 2.2.5 时遇到问题并降级到 2.2.0(在我的情况下,该事件从未引发)。
  • 刚刚做了一个2.2.0降级的测试,完全相同的问题。
  • 为什么要使用 AForge 访问相机帧?

标签: c# unity3d aforge


【解决方案1】:

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

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

1.WebCamTextureUnity 用来开始从相机中捕捉帧。

2.VideoCaptureDeviceAForge 用来开始从相机捕捉帧。

四个问题

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 类获取网络摄像头名称。最后的示例代码显示了如何。不要为此使用WebCamTexture

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

....只能从主线程调用

您必须找到一种方法来调用 Unity 的主线程或 Update 函数中的那行代码,因为您不能在另一个 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();

【讨论】:

  • 感谢您的详尽回答!我尝试了您的第一段代码,它没有给出任何错误,但相机也没有激活。我同意 AForge 和 Unity 之间可能存在问题,但我有几点意见。我事先在加载的图像上使用一些灰度函数测试了 AForge,效果很好。如果这确实是 AForge 问题,是否可以通过降级到更高版本来解决?我很快就会测试你的第二段代码,因为这可能会奏效。亲切的问候
  • “我事先在加载的图像上使用一些灰度函数测试了 AForge,效果很好” AForge API 分为模块。一些模块使用了新的.NET API Unity 不支持。其他人不使用来自.NET API 的 API,因此应该可以正常工作。这方面的一个例子是 async/await 关键字。我希望图像处理 API 是独立的,甚至不需要 .NET 4 API。也许,找到低版本,然后用.NET 3.5 或更少的版本构建它。要做的一件重要事情是将 AForge 的所有 DLL 放在 Asset 文件夹中
  • 我看到你接受了这个答案。请告诉我会发生什么。我还认为您应该检查this。 Unity 正在测试他们的.NET 4.6。你们很多人都想下载并尝试一下。顺便说一句,它现在只能在编辑器中使用。独立构建支持将在几个月后添加。
  • 我根据您最后发布的拆分框架代码接受了您的评论,因为它基本上解决了我的问题。使用它,我可以将 byte[] 数组中的帧制作成位图,然后在该位图上使用 AForges 方法。回答你的问题:会发生什么?上面的代码在视觉上没有任何反应。摄像头没有启动,但也没有显示任何错误。
  • 好的。很高兴知道哪一个解决了您的问题。当我有时间时,我会下载 AForge,看看我是否可以让它与当前的 Unity .NET 版本一起使用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-07
  • 2013-10-03
  • 2011-11-13
  • 2012-09-13
  • 2015-07-23
相关资源
最近更新 更多