Appareil photo et caméra vidéo dans Unity

Activation de la fonctionnalité d’accès à la caméra

La fonctionnalité « WebCam » doit être déclarée pour qu’une application utilise l’appareil photo.

  1. Dans l’éditeur Unity, accédez aux paramètres du lecteur en accédant à la page « Modifier > le lecteur des paramètres > du projet »
  2. Sélectionnez l’onglet « Windows Store »
  3. Dans la section « Fonctionnalités des paramètres > de publication », case activée les fonctionnalités WebCam et Microphone

Une seule opération peut se produire avec la caméra à la fois. Vous pouvez case activée le mode dans lequel se trouve actuellement UnityEngine.XR.WSA.WebCam.Mode l’appareil photo dans Unity 2018 et versions antérieures ou UnityEngine.Windows.WebCam.Mode dans Unity 2019 et versions ultérieures. Les modes disponibles sont photo, vidéo ou aucun.

Capture photo

Espace de noms (avant Unity 2019):UnityEngine.XR.WSA.WebCam
Espace de noms (Unity 2019 et versions ultérieures) :UnityEngine.Windows.WebCam
Type :PhotoCapture

Le type PhotoCapture vous permet de prendre des photos fixes avec l’appareil photo vidéo. Le modèle général d’utilisation de PhotoCapture pour prendre une photo est le suivant :

  1. Créer un objet PhotoCapture
  2. Créer un objet CameraParameters avec les paramètres souhaités
  3. Démarrer le mode Photo via StartPhotoModeAsync
  4. Prenez la photo souhaitée
    • (facultatif) Interagir avec cette image
  5. Arrêter le mode Photo et propre ressources

Configuration courante pour PhotoCapture

Pour les trois utilisations, commencez par les trois premières étapes ci-dessus

Commencez par créer un objet PhotoCapture

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

Ensuite, stockez votre objet, définissez vos paramètres et démarrez le mode Photo

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

En fin de compte, vous utiliserez également le même code propre présenté ici

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

Après ces étapes, vous pouvez choisir le type de photo à capturer.

Capturer une photo dans un fichier

L’opération la plus simple consiste à capturer une photo directement dans un fichier. La photo peut être enregistrée au format JPG ou PNG.

Si vous avez correctement démarré le mode photo, prenez une photo et stockez-la sur le disque

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

Après avoir capturé la photo sur le disque, quittez le mode photo, puis propre vos objets

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

Capturer une photo sur un Texture2D avec un emplacement

Lors de la capture de données dans un Texture2D, le processus est similaire à la capture sur disque.

Suivez le processus d’installation ci-dessus.

Dans OnPhotoModeStarted, capturez un frame en mémoire.

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

Vous allez ensuite appliquer votre résultat à une texture et utiliser le code propre commun ci-dessus.

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

Appareil photo localisable

Pour placer cette texture dans la scène et l’afficher à l’aide des matrices d’appareil photo locatables, ajoutez le code suivant à OnCapturedPhotoToMemory dans le result.success case activée :

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 a fourni un exemple de code pour l’application de la matrice de projection à un nuanceur spécifique sur leurs forums.

Capturer une photo et interagir avec les octets bruts

Pour interagir avec les octets bruts d’un frame en mémoire, suivez les mêmes étapes de configuration que ci-dessus et OnPhotoModeStarted que dans la capture d’une photo dans un Texture2D. La différence réside dans OnCapturedPhotoToMemory , où vous pouvez obtenir les octets bruts et interagir avec eux.

Dans cet exemple, vous allez créer une liste à traiter ou à appliquer à une texture via 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);
}

Capture vidéo

Espace de noms (avant Unity 2019):UnityEngine.XR.WSA.WebCam
Espace de noms (Unity 2019 et versions ultérieures) :UnityEngine.Windows.WebCam
Type:VideoCapture

VideoCapture fonctionne de la même façon que PhotoCapture. Les deux seules différences sont que vous devez spécifier une valeur Images par seconde (FPS) et que vous pouvez uniquement enregistrer directement sur le disque en tant que fichier .mp4. Les étapes d’utilisation de VideoCapture sont les suivantes :

  1. Créer un objet VideoCapture
  2. Créer un objet CameraParameters avec les paramètres souhaités
  3. Démarrer le mode vidéo via StartVideoModeAsync
  4. Démarrer l’enregistrement de la vidéo
  5. Arrêter l’enregistrement vidéo
  6. Arrêter le mode vidéo et propre des ressources

Commencez par créer notre objet VideoCaptureVideoCapture m_VideoCapture = null ;

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

Ensuite, configurez les paramètres souhaités pour l’enregistrement et démarrez.

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

Une fois démarré, commencez l’enregistrement

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

Une fois l’enregistrement démarré, vous pouvez mettre à jour votre interface utilisateur ou vos comportements pour activer l’arrêt. Ici, il vous suffit de vous connecter.

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

À un moment ultérieur, vous souhaiterez arrêter l’enregistrement à l’aide d’un minuteur ou d’une entrée utilisateur, pour instance.

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

Une fois l’enregistrement arrêté, arrêtez le mode vidéo et propre vos ressources.

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

Dépannage

  • Aucune résolution n’est disponible
    • Vérifiez que la fonctionnalité WebCam est spécifiée dans votre projet.

Point de contrôle de développement suivant

Si vous suivez le parcours du point de contrôle de développement Unity que nous avons mis en place, vous êtes en train d’explorer les fonctionnalités et LES API de la plateforme Mixed Reality. À partir d’ici, vous pouvez passer au sujet suivant :

Ou accéder directement au déploiement de votre application sur un appareil ou un émulateur :

Vous pouvez revenir aux points de contrôle de développement Unity à tout moment.

Voir aussi