Séquence de photos variable

Cet article vous montre comment capturer une séquence de photos variable, qui vous permet de capturer plusieurs images en succession rapide et de configurer chaque image pour utiliser différents paramètres de focus, flash, ISO, exposition et compensation d’exposition. Cette fonctionnalité permet des scénarios tels que la création d’images HDR (High Dynamic Range).

Si vous souhaitez capturer des images HDR mais que vous ne souhaitez pas implémenter votre propre algorithme de traitement, vous pouvez utiliser l’API AdvancedPhotoCapture pour utiliser les fonctionnalités HDR intégrées à Windows. Pour plus d’informations, consultez la capture de photos HDR (High Dynamic Range).

Remarque

Cet article repose sur les concepts et le code décrits dans Capture photo, vidéo et audio de base à l’aide de MediaCapture, qui décrit comment implémenter la capture photo et vidéo de base. Il est recommandé de vous familiariser avec le modèle de capture multimédia de base dans cet article avant de passer à des scénarios de capture plus avancés. Le code de cet article suppose que votre application a déjà une instance de MediaCapture qui a été correctement initialisée.

Configurer votre application pour utiliser la capture de séquences de photos variables

Outre les espaces de noms requis pour la capture multimédia de base, l’implémentation d’une capture de séquence de photos variable nécessite les espaces de noms suivants.

using Windows.Media.Capture.Core;
using Windows.Media.Devices.Core;

Déclarez une variable membre pour stocker l’objet VariablePhotoSequenceCapture , qui est utilisé pour lancer la capture de séquence de photos. Déclarez un tableau d’objets SoftwareBitmap pour stocker chaque image capturée dans la séquence. Déclarez également un tableau pour stocker l’objet CapturedFrameControlValues pour chaque image. Cela peut être utilisé par votre algorithme de traitement d’images pour déterminer quels paramètres ont été utilisés pour capturer chaque image. Enfin, déclarez un index qui sera utilisé pour suivre l’image de la séquence en cours de capture.

VariablePhotoSequenceCapture _photoSequenceCapture;
SoftwareBitmap[] _images;
CapturedFrameControlValues[] _frameControlValues;
int _photoIndex;

Préparer la capture de séquence de photos variable

Une fois que vous avez initialisé votre MediaCapture, assurez-vous que les séquences de photos variables sont prises en charge sur l’appareil actuel en obtenant une instance de VariablePhotoSequenceController à partir de VideoDeviceController de la capture multimédia et en vérifiant la propriété Supported.

var varPhotoSeqController = _mediaCapture.VideoDeviceController.VariablePhotoSequenceController;

if (!varPhotoSeqController.Supported)
{
    ShowMessageToUser("Variable Photo Sequence is not supported");
    return;
}

Obtenez un objet FrameControlCapabilities à partir du contrôleur de séquence de photos variable. Cet objet a une propriété pour chaque paramètre qui peut être configuré par cadre d’une séquence de photos. Il s’agit notamment des paramètres suivants :

Cet exemple définit une valeur de compensation d’exposition différente pour chaque image. Pour vérifier que la compensation de l’exposition est prise en charge pour les séquences de photos sur l’appareil actuel, vérifiez la propriété Supported de l’objet FrameExposureCompensationCapabilities accessible via la propriété ExposureCompensation.

var frameCapabilities = varPhotoSeqController.FrameCapabilities;

if (!frameCapabilities.ExposureCompensation.Supported)
{
    ShowMessageToUser("EVCompenstaion is not supported in FrameController");
    return;
}

Créez un objet FrameController pour chaque image que vous souhaitez capturer. Cet exemple capture trois images. Définissez les valeurs des contrôles que vous souhaitez modifier pour chaque image. Effacez ensuite la collection DesiredFrameControllers de VariablePhotoSequenceController et ajoutez chaque contrôleur d’images à la collection.

var frame0 = new FrameController();
var frame1 = new FrameController();
var frame2 = new FrameController();

frame0.ExposureCompensationControl.Value = -1.0f;
frame1.ExposureCompensationControl.Value = 0.0f;
frame2.ExposureCompensationControl.Value = 1.0f;

varPhotoSeqController.DesiredFrameControllers.Clear();
varPhotoSeqController.DesiredFrameControllers.Add(frame0);
varPhotoSeqController.DesiredFrameControllers.Add(frame1);
varPhotoSeqController.DesiredFrameControllers.Add(frame2);

Créez un objet ImageEncodingProperties pour définir l’encodage que vous souhaitez utiliser pour les images capturées. Appelez la méthode statique MediaCapture.PrepareVariablePhotoSequenceCaptureAsync, en passant les propriétés d’encodage. Cette méthode retourne un objet VariablePhotoSequenceCapture. Enfin, inscrivez des gestionnaires d’événements pour les événements PhotoCaptured et Stopped.

try
{
    var imageEncodingProperties = ImageEncodingProperties.CreateJpeg();

    _photoSequenceCapture = await _mediaCapture.PrepareVariablePhotoSequenceCaptureAsync(imageEncodingProperties);

    _photoSequenceCapture.PhotoCaptured += OnPhotoCaptured;
    _photoSequenceCapture.Stopped += OnStopped;
}
catch (Exception ex)
{
    ShowMessageToUser("Exception in PrepareVariablePhotoSequence: " + ex.Message);
}

Démarrer la capture de séquence de photos variable

Pour démarrer la capture de la séquence de photos variable, appelez VariablePhotoSequenceCapture.StartAsync. Veillez à initialiser les tableaux pour stocker les images capturées et les valeurs de contrôle frame et définir l’index actuel sur 0. Définissez la variable d’état d’enregistrement de votre application et mettez à jour votre interface utilisateur pour désactiver le démarrage d’une autre capture pendant que cette capture est en cours.

private async void StartPhotoCapture()
{
    _images = new SoftwareBitmap[3];
    _frameControlValues = new CapturedFrameControlValues[3];
    _photoIndex = 0;
    _isRecording = true;

    await _photoSequenceCapture.StartAsync();
}

Recevoir les images capturées

L’événement PhotoCaptured est déclenché pour chaque cadre capturé. Enregistrez les valeurs du contrôle frame et l’image capturée pour le cadre, puis incrémentez l’index de trame actuel. Cet exemple montre comment obtenir une représentation SoftwareBitmap de chaque image. Pour plus d’informations sur l’utilisation de SoftwareBitmap, consultez Imaging.

void OnPhotoCaptured(VariablePhotoSequenceCapture s, VariablePhotoCapturedEventArgs args)
{

    _images[_photoIndex] = args.Frame.SoftwareBitmap;
    _frameControlValues[_photoIndex] = args.CapturedFrameControlValues;
    _photoIndex++;
}

Gérer l’achèvement de la capture de séquence de photos variable

L’événement Stopped est déclenché lorsque toutes les images de la séquence ont été capturées. Mettez à jour l’état d’enregistrement de votre application et mettez à jour votre interface utilisateur pour permettre à l’utilisateur de lancer de nouvelles captures. À ce stade, vous pouvez transmettre les images capturées et les valeurs de contrôle d’image à votre code de traitement d’images.

void OnStopped(object s, object e)
{
    _isRecording = false;
    MyPostProcessingFunction(_images, _frameControlValues, 3);
}

Mettre à jour les contrôleurs de trame

Si vous souhaitez effectuer une autre capture de séquence de photos variable avec différents paramètres d’image, vous n’avez pas besoin de réinitialiser complètement la variablePhotoSequenceCapture. Vous pouvez effacer la collection DesiredFrameControllers et ajouter de nouveaux contrôleurs d’images ou modifier les valeurs existantes du contrôleur d’images. L’exemple suivant vérifie l’objet FrameFlashCapabilities pour vérifier que l’appareil actuel prend en charge la puissance flash et flash pour les images de séquence de photos variables. Si c’est le cas, chaque image est mise à jour pour activer le flash à 100 % de puissance. Les valeurs de compensation d’exposition qui ont été définies précédemment pour chaque image sont toujours actives.

var varPhotoSeqController = _mediaCapture.VideoDeviceController.VariablePhotoSequenceController;

if (varPhotoSeqController.FrameCapabilities.Flash.Supported &&
    varPhotoSeqController.FrameCapabilities.Flash.PowerSupported)
{
    for (int i = 0; i < varPhotoSeqController.DesiredFrameControllers.Count; i++)
    {
        varPhotoSeqController.DesiredFrameControllers[i].FlashControl.Mode = FrameFlashMode.Enable;
        varPhotoSeqController.DesiredFrameControllers[i].FlashControl.PowerPercent = 100;
    }
}

Nettoyer la capture de séquence de photos variable

Lorsque vous avez terminé de capturer des séquences de photos variables ou que votre application est suspendue, nettoyez l’objet de séquence de photos variable en appelant FinishAsync. Annulez l’inscription des gestionnaires d’événements de l’objet et définissez-le sur Null.

await _photoSequenceCapture.FinishAsync();
_photoSequenceCapture.PhotoCaptured -= OnPhotoCaptured;
_photoSequenceCapture.Stopped -= OnStopped;
_photoSequenceCapture = null;