Variable Fotosequenz

In diesem Artikel wird erläutert, wie Sie eine variable Fotosequenz aufnehmen, um mehrere Frames von Bildern in schneller Folge aufzunehmen und jeden Frame so zu konfigurieren, dass unterschiedliche Einstellungen für Fokus, Blitz, ISO, Belichtung und Belichtungskorrektur verwendet werden. Mit diesem Feature können Sie z. B. HDR-Bilder (High Dynamic Range) erstellen.

Wenn Sie HDR-Bilder aufnehmen, aber nicht Ihre eigenen Algorithmen zur Bildverarbeitung implementieren möchten, können Sie mithilfe der AdvancedPhotoCapture API die in Windows integrierten HDR-Funktionen verwenden. Weitere Informationen finden Sie unter HDR-Fotoaufnahmen (High Dynamic Range).

Hinweis

Dieser Artikel baut auf Konzepten und Code auf, die unter Allgemeine Foto-, Video- und Audioaufnahme mit „MediaCapture“ erläutert werden. Dort werden die Schritte für die Implementierung einer grundlegenden Foto- und Videoaufnahme beschrieben. Es wird empfohlen, dass Sie sich mit dem grundlegenden Muster für die Medienerfassung in diesem Artikel vertraut machen, bevor Sie in fortgeschrittene Aufnahmeszenarien einsteigen. Der Code in diesem Artikel setzt voraus, dass Ihre App bereits über eine korrekt initialisierte MediaCapture-Instanz verfügt.

Einrichten Ihrer App mithilfe der Aufnahme einer variablen Fotosequenz

Neben den Namespaces für die grundlegende Medienerfassung sind für die Implementierung der Aufnahme einer variablen Fotosequenz folgende Namespaces erforderlich.

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

Deklarieren Sie eine Membervariable, um das VariablePhotoSequenceCapture-Objekt zu speichern, das verwendet wird, um die Aufnahme der Fotosequenz zu initiieren. Deklarieren Sie ein Array von SoftwareBitmap-Objekten, um die einzelnen aufgenommenen Bilder in der Sequenz zu speichern. Deklarieren Sie außerdem ein Array, um das CapturedFrameControlValues-Objekt für jeden Frame zu speichern. Dazu können Sie Ihren Algorithmus zur Bildverarbeitung verwenden, um zu ermitteln, welche Einstellungen zum Aufnehmen der einzelnen Frames verwendet wurden. Abschließend deklarieren Sie einen Index, mit dem Sie nachverfolgen können, welches Bild in der Sequenz gerade aufgenommen wird.

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

Vorbereiten der Aufnahme einer variablen Fotosequenz

Nachdem Sie MediaCapture initialisiert haben, müssen Sie sicherstellen, dass die variablen Fotosequenzen auf dem aktuellen Gerät unterstützt werden, indem Sie eine Instanz von VariablePhotoSequenceController aus dem VideoDeviceController der Medienerfassung abrufen und die Supported-Eigenschaft überprüfen.

var varPhotoSeqController = _mediaCapture.VideoDeviceController.VariablePhotoSequenceController;

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

Rufen Sie ein FrameControlCapabilities-Objekt von dem Controller der variablen Fotosequenz ab. Dieses Objekt besitzt eine Eigenschaft für jede Einstellung, die pro Frame einer Fotosequenz konfiguriert werden kann. Dazu gehören:

In diesem Beispiel wird ein anderer Belichtungskorrekturwert für jeden Frame festgelegt. Um sicherzustellen, dass die Belichtungskorrektur für die Fotosequenzen auf dem aktuellen Gerät unterstützt wird, überprüfen Sie die Supported-Eigenschaft des FrameExposureCompensationCapabilities-Objekts, auf das Sie über die ExposureCompensation-Eigenschaft zugreifen.

var frameCapabilities = varPhotoSeqController.FrameCapabilities;

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

Erstellen Sie ein neues FrameController-Objekt für die einzelnen Frames, die Sie aufnehmen möchten. In diesem Beispiel werden drei Frames aufgenommen. Legen Sie die Werte für die Steuerelemente fest, die Sie für jeden Frame variieren möchten. Löschen Sie dann die DesiredFrameControllers-Auflistung von VariablePhotoSequenceController, und fügen Sie der Auflistung die einzelnen Framecontroller hinzu.

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

Erstellen Sie ein ImageEncodingProperties-Objekt, um die Codierung festzulegen, die Sie für die aufgenommenen Bilder verwenden möchten. Rufen Sie die statische Methode MediaCapture.PrepareVariablePhotoSequenceCaptureAsync auf, und übergeben Sie die Codierungseigenschaften. Diese Methode gibt ein VariablePhotoSequenceCapture-Objekt zurück. Registrieren Sie abschließend Ereignishandler für das PhotoCaptured-Ereignis und das Stopped-Ereignis.

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

Starten der Aufnahme einer variablen Fotosequenz

Rufen Sie zum Starten der Aufnahme der variablen Fotosequenz VariablePhotoSequenceCapture.StartAsync auf. Achten Sie darauf, dass Sie Arrays zum Speichern der aufgenommenen Bilder und Werte des Frame-Steuerelements initialisieren und den aktuellen Index auf 0 festlegen. Legen Sie für Ihre App die Aufnahmezustandsvariable fest, und aktualisieren Sie Ihre Benutzeroberfläche, um das Starten einer weiteren Aufnahme zu deaktivieren, während diese Aufnahme läuft.

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

    await _photoSequenceCapture.StartAsync();
}

Empfangen der aufgenommenen Frames

Das PhotoCaptured-Ereignis wird für jeden aufgenommenen Frame ausgelöst. Speichern Sie die Werte des Frame-Steuerelements und das aufgenommene Bild für den Frame, und erhöhen Sie dann den aktuellen Frameindex. Dieses Beispiel zeigt, wie Sie eine SoftwareBitmap-Darstellung der einzelnen Frames abrufen können. Weitere Informationen zur Verwendung von SoftwareBitmap finden Sie unter Bildverarbeitung.

void OnPhotoCaptured(VariablePhotoSequenceCapture s, VariablePhotoCapturedEventArgs args)
{

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

Abschluss der Aufnahme der variablen Fotosequenz

Das Stopped-Ereignis wird ausgelöst, nachdem alle Frames in der Sequenz aufgenommen wurden. Aktualisieren Sie den Aufnahmestatus Ihrer App und Ihre Benutzeroberfläche, damit Benutzer neue Aufzeichnungen initiieren können. An dieser Stelle können Sie die aufgenommenen Bilder und Werte des Frame-Steuerelements an Ihren Bildverarbeitungscode übergeben.

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

Aktualisieren von Framecontrollern

Wenn Sie eine weitere Aufnahme einer variablen Fotosequenz mit anderen Einstellungen pro Frame durchführen möchten, müssen Sie VariablePhotoSequenceCapture nicht komplett neu initialisieren. Löschen Sie entweder die DesiredFrameControllers-Auflistung, und fügen Sie neue Framecontroller hinzu, oder ändern Sie die vorhandenen Framecontrollerwerte. Im folgenden Beispiel wird das FrameFlashCapabilities-Objekt überprüft, um sicherzustellen, dass das aktuelle Gerät Blitz und Blitzleistung für Frames variabler Fotosequenzen unterstützt. In diesem Fall wird jeder Frame aktualisiert, um den Blitz bei 100 % Energieverbrauch zu aktivieren. Die Belichtungskorrekturwerte, die zuvor für jeden Frame festgelegt wurden, sind weiterhin aktiv.

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

Bereinigen der Aufnahme einer variablen Fotosequenz

Bereinigen Sie nach der Aufnahme variabler Fotosequenzen oder nach dem Anhalten Ihrer App das entsprechende Objekt, indem Sie FinishAsync aufrufen. Heben Sie die Registrierung der Ereignishandler für das Objekt auf, und legen Sie es auf NULL fest.

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