Cámara de fotos y vídeo en Unity

Habilitación de la funcionalidad para el acceso a la cámara

La funcionalidad "WebCam" debe declararse para que una aplicación use la cámara.

  1. En el Editor de Unity, vaya a la configuración del reproductor; para ello, vaya a la página "Editar > reproductor de configuración del > proyecto".
  2. Seleccione la pestaña "Tienda Windows"
  3. En la sección "Funcionalidades de configuración > de publicación", compruebe las funcionalidades de WebCam y Micrófono .

Solo se puede producir una sola operación con la cámara a la vez. Puede comprobar en qué modo está actualmente la cámara en UnityEngine.XR.WSA.WebCam.Mode Unity 2018 y versiones anteriores o UnityEngine.Windows.WebCam.Mode en Unity 2019 y versiones posteriores. Los modos disponibles son foto, vídeo o ninguno.

Captura de fotos

Espacio de nombres (antes de Unity 2019):UnityEngine.XR.WSA.WebCam
Espacio de nombres (Unity 2019 y versiones posteriores):UnityEngine.Windows.WebCam
Type:PhotoCapture

El tipo PhotoCapture le permite tomar fotografías fijas con la cámara de vídeo foto. El patrón general para usar PhotoCapture para tomar una foto es el siguiente:

  1. Crear un objeto PhotoCapture
  2. Cree un objeto CameraParameters con la configuración que desee.
  3. Iniciar el modo de foto a través de StartPhotoModeAsync
  4. Toma la foto que quieres
    • (opcional) Interacción con esa imagen
  5. Detener el modo de foto y limpiar los recursos

Configuración común para PhotoCapture

Para los tres usos, comience con los tres primeros pasos anteriores.

Empiece por crear un objeto PhotoCapture

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

A continuación, almacene el objeto, establezca los parámetros e inicie el modo de foto.

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

Al final, también usará el mismo código de limpieza que se presenta aquí.

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

Después de estos pasos, puede elegir qué tipo de foto se va a capturar.

Capturar una foto a un archivo

La operación más sencilla es capturar una foto directamente en un archivo. La foto se puede guardar como jpg o PNG.

Si ha iniciado correctamente el modo de foto, tome una foto y almacénela en el disco.

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!");
    }
}

Después de capturar la foto en el disco, salga del modo de foto y, a continuación, limpie los objetos.

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");
    }
}

Capturar una foto en un Texture2D con ubicación

Al capturar datos en texture2D, el proceso es similar a la captura en el disco.

Siga el proceso de instalación anterior.

En OnPhotoModeStarted, capture un marco en la memoria.

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

A continuación, aplicará el resultado a una textura y usará el código de limpieza común anterior.

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

Cámara localizable

Para colocar esta textura en la escena y mostrarla mediante las matrices de cámara locables, agregue el código siguiente a OnCapturedPhotoToMemory en la result.success comprobación:

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 ha proporcionado código de ejemplo para aplicar la matriz de proyección a un sombreador específico en sus foros.

Capturar una foto e interactuar con los bytes sin procesar

Para interactuar con los bytes sin procesar de un fotograma en memoria, siga los mismos pasos de configuración anteriores y OnPhotoModeStarted que en la captura de una foto en texture2D. La diferencia está en OnCapturedPhotoToMemory , donde puede obtener los bytes sin procesar e interactuar con ellos.

En este ejemplo, creará una lista para procesarla o aplicarla a una textura mediante 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);
}

Captura de vídeo

Espacio de nombres (antes de Unity 2019):UnityEngine.XR.WSA.WebCam
Espacio de nombres (Unity 2019 y versiones posteriores):UnityEngine.Windows.WebCam
Type:VideoCapture

VideoCapture funciona de forma similar a PhotoCapture. Las únicas dos diferencias son que debe especificar un valor fotogramas por segundo (FPS) y solo puede guardar directamente en el disco como un archivo .mp4. Los pasos para usar VideoCapture son los siguientes:

  1. Creación de un objeto VideoCapture
  2. Cree un objeto CameraParameters con la configuración que desee.
  3. Iniciar el modo de vídeo a través de StartVideoModeAsync
  4. Inicio de la grabación de vídeo
  5. Detener grabación de vídeo
  6. Detener el modo de vídeo y limpiar los recursos

Empiece por crear nuestro objeto VideoCaptureVideoCapture m_VideoCapture = null;

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

A continuación, configure los parámetros que quiera para la grabación e inicie.

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!");
    }
}

Una vez iniciada, comience la grabación.

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

Una vez iniciada la grabación, puede actualizar la interfaz de usuario o los comportamientos para habilitar la detención. Aquí acabas de registrarte.

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.
}

En un momento posterior, querrá detener la grabación mediante un temporizador o una entrada de usuario, por ejemplo.

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

Una vez detenida la grabación, detenga el modo de vídeo y limpie los recursos.

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;
}

Solución de problemas

  • No hay resoluciones disponibles
    • Asegúrese de que la funcionalidad WebCam se especifica en el proyecto.

Siguiente punto de control de desarrollo

Si sigue el recorrido del punto de control de desarrollo de Unity que hemos diseñado, se encuentra en medio de la exploración de las funcionalidades y las API de la plataforma de Mixed Reality. Desde aquí, puede continuar con el siguiente tema:

O bien puede ir directamente a la implementación de la aplicación en un dispositivo o emulador:

Puede volver a los puntos de control de desarrollo de Unity en cualquier momento.

Consulte también