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 Project Configuración > Player".
  2. Seleccione la pestaña "Windows Store"
  3. En la sección "Publishing Configuración Capabilities" (Funcionalidades de Configuración > publicación), compruebe las funcionalidades >y Microphone.

Solo se puede realizar una sola operación con la cámara a la vez. Puede comprobar con qué modo está actualmente la cámara en Unity 2018 y versiones anteriores o UnityEngine.XR.WSA.WebCam.ModeUnityEngine.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
Tipo:PhotoCapture

El tipo PhotoCapture permite tomar fotografías con la cámara photo video. El patrón general para usar PhotoCapture para tomar una foto es el siguiente:

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

Configuración común de PhotoCapture

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

Para empezar, cree un objeto PhotoCapture.

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

A continuación, almacene el objeto, establezca los parámetros e inicie el modo 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 guárdala 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");
    }
}

Captura de una foto en un objeto 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 fotograma en la memoria.

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

Después, 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 localizables, agregue el código siguiente a OnCapturedPhotoToMemory en la 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.

Captura de una foto e interacción con los bytes sin procesar

Para interactuar con los bytes sin procesar de un marco en memoria, siga los mismos pasos de configuración anteriores y OnPhotoModeStarted como 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 a través de 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
Tipo: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 segundo. 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 el objeto VideoCaptureVideoCapture m_VideoCapture = null;

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

A continuación, configure los parámetros que deseará 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 iniciado, 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í solo tiene que iniciar sesión.

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 soluciones disponibles
    • Asegúrese de que la funcionalidad WebCam está especificada en el proyecto.

Siguiente punto de control de desarrollo

Si va a seguir el recorrido del punto de control de desarrollo de Unity que hemos diseñado, está a punto de explorar las API y las funcionalidades de Mixed Reality plataforma. 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