Фото- и видеокамера в Unity

Включение возможности доступа к камере

Чтобы приложение использовало камеру, необходимо объявить возможность "WebCam".

  1. В редакторе Unity перейдите к параметрам проигрывателя, перейдя на страницу "Изменение > проигрывателя параметров > проекта".
  2. Выберите вкладку "Магазин Windows"
  3. В разделе "Возможности параметров > публикации" проверка возможности веб-камеры и микрофона.

Одновременно с камерой может выполняться только одна операция. Вы можете проверка, в каком режиме камера сейчас находится в UnityEngine.XR.WSA.WebCam.Mode Unity 2018 и более ранних версиях или UnityEngine.Windows.WebCam.Mode в Unity 2019 и более поздних версиях. Доступные режимы: фото, видео или нет.

Фотосъемка

Пространство имен (до Unity 2019):UnityEngine.XR.WSA.WebCam
Пространство имен (Unity 2019 и более поздние версии):UnityEngine.Windows.WebCam
Тип:PhotoCapture

Тип PhotoCapture позволяет делать неподвижные фотографии с помощью камеры photo video. Общий шаблон использования PhotoCapture для создания фотографии выглядит следующим образом:

  1. Создание объекта PhotoCapture
  2. Создание объекта CameraParameters с нужными параметрами
  3. Запуск режима фотографии с помощью StartPhotoModeAsync
  4. Сделайте нужную фотографию
    • (необязательно) Взаимодействие с этим рисунком
  5. Остановка фоторежимов и очистка ресурсов

Общая настройка для PhotoCapture

Для всех трех вариантов использования начните с первых трех шагов, описанных выше.

Начните с создания объекта PhotoCapture

private void Start()
{
    PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}

Затем сохраните объект, задайте параметры и запустите фоторежим.

private PhotoCapture photoCaptureObject = null;

void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
    photoCaptureObject = captureObject;

    Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

    CameraParameters c = new CameraParameters();
    c.hologramOpacity = 0.0f;
    c.cameraResolutionWidth = cameraResolution.width;
    c.cameraResolutionHeight = cameraResolution.height;
    c.pixelFormat = CapturePixelFormat.BGRA32;

    captureObject.StartPhotoModeAsync(c, false, OnPhotoModeStarted);
}

В конце концов, вы также будете использовать тот же код очистки, который представлен здесь.

void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
    photoCaptureObject.Dispose();
    photoCaptureObject = null;
}

После выполнения этих действий вы можете выбрать тип фотографии для захвата.

Фотозахват в файл

Самая простая операция — захватить фотографию непосредственно в файл. Фотография может быть сохранена в формате JPG или PNG.

Если режим фотографии успешно запущен, сделайте фотографию и сохраните ее на диске.

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        string filename = string.Format(@"CapturedImage{0}_n.jpg", Time.time);
        string filePath = System.IO.Path.Combine(Application.persistentDataPath, filename);

        photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}

После записи фотографии на диск выйдите из фоторежима, а затем очистите объекты.

void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        Debug.Log("Saved Photo to disk!");
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
    }
    else
    {
        Debug.Log("Failed to save Photo to disk");
    }
}

Запись фотографии в Texture2D с расположением

При записи данных в Texture2D процесс аналогичен записи на диск.

Выполните описанный выше процесс настройки.

В OnPhotoModeStarted запишите кадр в память.

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}

Затем вы примените результат к текстуре и используйте приведенный выше общий код очистки.

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        // Create our Texture2D for use and set the correct resolution
        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
        // Copy the raw image data into our target texture
        photoCaptureFrame.UploadImageDataToTexture(targetTexture);
        // Do as we wish with the texture such as apply it to a material, etc.
    }
    // Clean up
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

Камера с определяемым местоположением

Чтобы поместить эту текстуру в сцену и отобразить ее с помощью матриц камеры с поддержкой locatable, добавьте следующий код в OnCapturedPhotoToMemory в result.success проверка:

if (photoCaptureFrame.hasLocationData)
{
    photoCaptureFrame.TryGetCameraToWorldMatrix(out Matrix4x4 cameraToWorldMatrix);

    Vector3 position = cameraToWorldMatrix.GetColumn(3) - cameraToWorldMatrix.GetColumn(2);
    Quaternion rotation = Quaternion.LookRotation(-cameraToWorldMatrix.GetColumn(2), cameraToWorldMatrix.GetColumn(1));

    photoCaptureFrame.TryGetProjectionMatrix(Camera.main.nearClipPlane, Camera.main.farClipPlane, out Matrix4x4 projectionMatrix);
}

Unity предоставил пример кода для применения матрицы проекции к определенному шейдеру на своих форумах.

Захватить фотографию и взаимодействовать с необработанными байтами

Чтобы взаимодействовать с необработанными байтами кадра в памяти, выполните те же действия по настройке, что и OnPhotoModeStarted , как при захвате фотографии в Texture2D. Разница заключается в OnCapturedPhotoToMemory , где можно получить необработанные байты и взаимодействовать с ними.

В этом примере вы создадите список для дальнейшей обработки или применения к текстуре с помощью SetPixels()

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        List<byte> imageBufferList = new List<byte>();
        // Copy the raw IMFMediaBuffer data into our empty byte list.
        photoCaptureFrame.CopyRawImageDataIntoBuffer(imageBufferList);

        // In this example, we captured the image using the BGRA32 format.
        // So our stride will be 4 since we have a byte for each rgba channel.
        // The raw image data will also be flipped so we access our pixel data
        // in the reverse order.
        int stride = 4;
        float denominator = 1.0f / 255.0f;
        List<Color> colorArray = new List<Color>();
        for (int i = imageBufferList.Count - 1; i >= 0; i -= stride)
        {
            float a = (int)(imageBufferList[i - 0]) * denominator;
            float r = (int)(imageBufferList[i - 1]) * denominator;
            float g = (int)(imageBufferList[i - 2]) * denominator;
            float b = (int)(imageBufferList[i - 3]) * denominator;

            colorArray.Add(new Color(r, g, b, a));
        }
        // Now we could do something with the array such as texture.SetPixels() or run image processing on the list
    }
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

Видеозахват

Пространство имен (до Unity 2019):UnityEngine.XR.WSA.WebCam
Пространство имен (Unity 2019 и более поздние версии):UnityEngine.Windows.WebCam
Тип:VideoCapture

Функция VideoCapture аналогична функции PhotoCapture. Единственное отличие заключается в том, что необходимо указать значение кадров в секунду (FPS) и сохранять их можно только непосредственно на диск в виде файла .mp4. Ниже приведены инструкции по использованию VideoCapture .

  1. Создание объекта VideoCapture
  2. Создание объекта CameraParameters с нужными параметрами
  3. Запуск видеорежима через StartVideoModeAsync
  4. Начать запись видео
  5. Остановка записи видео
  6. Остановка режима видео и очистка ресурсов

Начните с создания объекта VideoCaptureVideoCapture m_VideoCapture = null;

void Start ()
{
    VideoCapture.CreateAsync(false, OnVideoCaptureCreated);
}

Затем настройте параметры для записи и запустите.

void OnVideoCaptureCreated(VideoCapture videoCapture)
{
    if (videoCapture != null)
    {
        m_VideoCapture = videoCapture;

        Resolution cameraResolution = VideoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        float cameraFramerate = VideoCapture.GetSupportedFrameRatesForResolution(cameraResolution).OrderByDescending((fps) => fps).First();

        CameraParameters cameraParameters = new CameraParameters();
        cameraParameters.hologramOpacity = 0.0f;
        cameraParameters.frameRate = cameraFramerate;
        cameraParameters.cameraResolutionWidth = cameraResolution.width;
        cameraParameters.cameraResolutionHeight = cameraResolution.height;
        cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;

        m_VideoCapture.StartVideoModeAsync(cameraParameters,
                                            VideoCapture.AudioState.None,
                                            OnStartedVideoCaptureMode);
    }
    else
    {
        Debug.LogError("Failed to create VideoCapture Instance!");
    }
}

После запуска начните запись.

void OnStartedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    if (result.success)
    {
        string filename = string.Format("MyVideo_{0}.mp4", Time.time);
        string filepath = System.IO.Path.Combine(Application.persistentDataPath, filename);

        m_VideoCapture.StartRecordingAsync(filepath, OnStartedRecordingVideo);
    }
}

После начала записи можно обновить пользовательский интерфейс или поведение, чтобы включить остановку. Здесь вы просто зайдите в журнал.

void OnStartedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Started Recording Video!");
    // We will stop the video from recording via other input such as a timer or a tap, etc.
}

Позже вы захотите остановить запись, например, с помощью таймера или ввода данных пользователем.

// The user has indicated to stop recording
void StopRecordingVideo()
{
    m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}

После остановки записи остановите режим видео и очистите ресурсы.

void OnStoppedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Stopped Recording Video!");
    m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
}

void OnStoppedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    m_VideoCapture.Dispose();
    m_VideoCapture = null;
}

Устранение неполадок

  • Нет доступных разрешений
    • Убедитесь, что в проекте указана возможность WebCam .

Следующий этап разработки

Если вы выполняете описанный нами путь создания контрольных точек разработки Unity, вы находитесь в разгаре изучения возможностей платформы Смешанная реальность и API. Вы можете перейти к следующей статье:

Или сразу перейдите к развертыванию приложения на устройстве или эмуляторе:

Вы можете в любой момент вернуться к этапам разработки для Unity.

См. также раздел