Как заставить AForge VideoCaptureDevice работать с Unity

Я пытаюсь сделать шоу камеры на самолете в Unity3D. Я использую код из документации AForge: http://www.aforgenet.com/framework/docs/html/f4d3c2ba-605c-f066-f969-68260ce5e141.htm за исключением того, что я вставляю веб-камеру через Unity вместо обычного AForges, где она хочет сделать фильтринфоколлекцию. Если я не ошибаюсь, это необходимо для того, чтобы 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);
    }

}

person Jon Dier    schedule 02.11.2016    source источник
comment
Какую версию AForge вы используете?   -  person Alessandro D'Andria    schedule 02.11.2016
comment
@ Алессандро Д'Андриа 2.2.5   -  person Jon Dier    schedule 02.11.2016
comment
У меня проблемы с 2.2.5 и переходом на 2.2.0 (в моем случае событие никогда не возникало).   -  person Alessandro D'Andria    schedule 02.11.2016
comment
Только что сделал тест с понижением версии 2.2.0, точно такая же проблема.   -  person Jon Dier    schedule 02.11.2016
comment
Почему вы используете AForge для доступа к кадрам камеры?   -  person Programmer    schedule 02.11.2016
comment
Можно ли это сделать иначе, исключительно с помощью Unity?   -  person Jon Dier    schedule 02.11.2016
comment
Вопрос: что ты делаешь?   -  person Programmer    schedule 02.11.2016
comment
Я пытаюсь разбить камеру на кадры, на которых затем могу использовать методы AForges.   -  person Jon Dier    schedule 02.11.2016


Ответы (1)


Во-первых, я не уверен, что AForge будет работать в Unity. Причина в том, что он использует .NET 4 или более, а Unity использует .NET 3.5.

Помимо этого, в вашем коде есть несколько проблем.

1.WebCamTexture используется Unity для начала захвата кадров с камеры.

2.VideoCaptureDevice используется AForge для начала захвата кадров с камеры.

4 проблемы:

1. Вы должны использовать один, а не оба. Вы не можете комбинировать их оба, и я считаю, что к камере можно получить доступ из одного места за раз.

Когда вы сделали webCam.Play();, а затем videoSource.Start();, вы пытаетесь использовать одну камеру из нескольких API. VideoCaptureDevice следует использовать, если вы хотите использовать API AForge.

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 или функции обновления, поскольку вы не можете использовать Unity API (Texture2D/originalFeedTexture) в другом Thread.

Начните с приведенного ниже кода, возможно, вы сможете заставить его работать. Не уверен насчет всей этой штуки с AForge+Unity из-за разницы в версии .NET. Проблема #5 не устранена в этом решении. Вы можете использовать Помощник по работе с потоками Unity плагин (бесплатный) для этого.

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();
person Programmer    schedule 02.11.2016
comment
Спасибо за развернутый ответ! Я попробовал ваш первый кусок кода, он не выдает никаких ошибок, но и камера не активируется. Я согласен, что между AForge и Unity может возникнуть проблема, но у меня есть несколько замечаний. Я заранее протестировал AForge с некоторыми функциями оттенков серого на загруженном изображении, и они работали нормально. Если это действительно проблема AForge, можно ли ее исправить, перейдя на более позднюю версию? Я собираюсь протестировать ваш второй фрагмент кода в ближайшее время, так как это может помочь. С уважением - person Jon Dier; 02.11.2016
comment
Я предварительно протестировал AForge с некоторыми функциями оттенков серого на загруженном изображении, и они работали нормально. API AForge разделен на модули. Некоторые модули используют новые .NET API Unity, которые не поддерживаются. Другие не используют API от .NET API и поэтому должны работать нормально. Примером этого является ключевое слово async/await. Я ожидаю, что API обработки изображений будет независимым и даже не нуждается в .NET 4 API. Может быть, найти более низкую версию, а затем собрать ее с .NET 3.5 или меньше. Одна важная вещь, которую нужно сделать, это поместить все DLL AForge в папку Asset. - person Programmer; 02.11.2016
comment
Я вижу, что вы приняли этот ответ. Пожалуйста, скажите мне, что происходит. Я также думаю, что вам следует проверить это. Unity тестирует свои .NET 4.6. Многие хотят скачать это и попробовать. Кстати, пока работает только в Редакторе. Поддержка автономной сборки будет добавлена ​​через несколько месяцев. - person Programmer; 02.11.2016
comment
Я принял ваш комментарий на основе кода разделения кадра, который вы разместили в конце, поскольку он в основном решил мою проблему. Используя это, я могу преобразовать кадры из массива byte[] в растровое изображение, а затем использовать методы AForges для этого растрового изображения. Чтобы ответить на ваш вопрос: что происходит? В приведенном выше коде визуально ничего не происходит. Камера не активируется, но и ошибок не показывает. - person Jon Dier; 02.11.2016
comment
В порядке. Полезно знать, какой из них решил вашу проблему. Когда у меня будет время, я загружу AForge и посмотрю, смогу ли я заставить его работать с текущей версией Unity .NET. - person Programmer; 02.11.2016