この記事では、 AdvancedPhotoCapture クラスを使用してハイ ダイナミック レンジ (HDR) の写真をキャプチャする方法について説明します。 この API では、最終的なイメージの処理が完了する前に、HDR キャプチャから参照フレームを取得することもできます。
HDR キャプチャに関連するその他の記事は次のとおりです。
SceneAnalysisEffect を使用すると、システムがメディア キャプチャ プレビュー ストリームのコンテンツを評価して、HDR 処理によってキャプチャ結果が向上するかどうかを判断できます。 詳細については、「 MediaCapture のシーン解析」を参照してください。
HdrVideoControl を使用して、Windows 組み込みの HDR 処理アルゴリズムを使用してビデオをキャプチャします。 詳細については、「 ビデオ キャプチャ用のデバイス コントロールをキャプチャする」を参照してください。
VariablePhotoSequenceCapture を使用して一連の写真をキャプチャし、それぞれ異なるキャプチャ設定を使用して、独自の HDR またはその他の処理アルゴリズムを実装できます。 詳細については、「 可変写真シーケンス」を参照してください。
注
Windows 10 バージョン 1709 以降では、ビデオの記録と AdvancedPhotoCapture の同時使用がサポートされています。 これは以前のバージョンではサポートされていません。 この変更は、 準備された LowLagMediaRecording と AdvancedPhotoCapture を同時に作成できることを意味します。 MediaCapture.PrepareAdvancedPhotoCaptureAsync と AdvancedPhotoCapture.FinishAsync の呼び出しの間で、ビデオ録画を開始または停止できます。 ビデオの録画中に AdvancedPhotoCapture.CaptureAsync を呼び出すこともできます。 ただし、ビデオの記録中に HDR 写真をキャプチャするなどの一部の AdvancedPhotoCapture シナリオでは、一部のビデオ フレームが HDR キャプチャによって変更され、ユーザー エクスペリエンスが低下します。 このため、 AdvancedPhotoControl.SupportedModes によって返されるモードの一覧は、ビデオの記録中に異なります。 ビデオ録画を開始または停止した直後にこの値を確認して、目的のモードが現在のビデオ記録状態でサポートされていることを確認する必要があります。
注
Windows 10 バージョン 1709 以降では、 AdvancedPhotoCapture が HDR モードに設定されている場合、 FlashControl.Enabled プロパティの設定は無視され、フラッシュは発生しません。 他のキャプチャ モードでは、 FlashControl.Enabled の場合、 AdvancedPhotoCapture 設定がオーバーライドされ、通常の写真がフラッシュでキャプチャされます。 Auto が true に設定されている場合、現在のシーンの条件に対するカメラ ドライバーの既定の動作に応じて、AdvancedPhotoCapture でフラッシュが使用される場合と使用されない場合があります。 以前のリリースでは、 AdvancedPhotoCapture フラッシュ設定は常に FlashControl.Enabled 設定をオーバーライドします。
AdvancedPhotoCapture クラスの使用方法を示す完全なサンプルがあります。このクラスを使用して、コンテキストで使用されている API を確認したり、独自のアプリの開始点として使用したりできます。 詳細については、「 カメラの高度なキャプチャのサンプル」を参照してください。
HDR 写真キャプチャ
現在のデバイスで HDR 写真キャプチャがサポートされているかどうかを確認する
この記事で説明する HDR キャプチャ手法は、 AdvancedPhotoCapture オブジェクトを使用して実行されます。 すべてのデバイスが AdvancedPhotoCapture を使用した HDR キャプチャをサポートしているわけではありません。 MediaCapture オブジェクトの VideoDeviceController を取得し、AdvancedPhotoControl プロパティを取得することで、アプリが現在実行されているデバイスでこの手法がサポートされているかどうかを判断します。 ビデオ デバイス コントローラーの SupportedModes コレクションに AdvancedPhotoMode.Hdr が含まれているかどうかを確認します。その場合は、 AdvancedPhotoCapture を使用した HDR キャプチャがサポートされます。
m_hdrSupported = m_mediaCapture.VideoDeviceController.AdvancedPhotoControl.SupportedModes.Contains(Windows.Media.Devices.AdvancedPhotoMode.Hdr);
AdvancedPhotoCapture オブジェクトを構成して準備する
コード内の複数の場所から AdvancedPhotoCapture インスタンスにアクセスする必要があるため、オブジェクトを保持するメンバー変数を宣言する必要があります。
private AdvancedPhotoCapture m_advancedCapture;
アプリで MediaCapture オブジェクトを初期化したら、 AdvancedPhotoCaptureSettings オブジェクトを作成し、モードを AdvancedPhotoMode.Hdr に設定します。 AdvancedPhotoControl オブジェクトの Configure メソッドを呼び出し、作成した AdvancedPhotoCaptureSettings オブジェクトを 渡します。
MediaCapture オブジェクトの PrepareAdvancedPhotoCaptureAsync を呼び出し、キャプチャで使用するエンコードの種類を指定する ImageEncodingProperties オブジェクトを渡します。 ImageEncodingProperties クラスは、MediaCapture でサポートされているイメージ エンコードを作成するための静的メソッドを提供します。
PrepareAdvancedPhotoCaptureAsync は、写真キャプチャの開始に使用する AdvancedPhotoCapture オブジェクトを返します。 このオブジェクトを使用して、 OptionalReferencePhotoCaptured と AllPhotosCaptured のハンドラーを登録できます。これについては、この記事で後述します。
if (m_hdrSupported == false) return;
// Choose HDR mode
var settings = new AdvancedPhotoCaptureSettings { Mode = AdvancedPhotoMode.Hdr };
// Configure the mode
m_mediaCapture.VideoDeviceController.AdvancedPhotoControl.Configure(settings);
// Prepare for an advanced capture
m_advancedCapture =
await m_mediaCapture.PrepareAdvancedPhotoCaptureAsync(ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Nv12));
// Register for events published by the AdvancedCapture
m_advancedCapture.AllPhotosCaptured += M_advancedCapture_AllPhotosCaptured;
m_advancedCapture.OptionalReferencePhotoCaptured += M_advancedCapture_OptionalReferencePhotoCaptured;
HDR 写真をキャプチャする
AdvancedPhotoCapture オブジェクトの CaptureAsync メソッドを呼び出して HDR 写真をキャプチャします。 このメソッドは、キャプチャされた写真を Frame プロパティに提供する AdvancedCapturedPhoto オブジェクトを返します。 次に、写真がディスクに保存されます。
try
{
// Start capture, and pass the context object
AdvancedCapturedPhoto advancedCapturedPhoto = await m_advancedCapture.CaptureAsync();
using (var frame = advancedCapturedPhoto.Frame)
{
var fileName = String.Format("SimplePhoto_{0}_HDR.jpg", DateTime.Now.ToString("HHmmss"));
StorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync(fileName);
IRandomAccessStream stream = await photoFile.OpenAsync(FileAccessMode.ReadWrite);
await RandomAccessStream.CopyAndCloseAsync(advancedCapturedPhoto.Frame, stream);
}
}
catch (Exception ex)
{
Debug.WriteLine("Exception when taking an HDR photo: {0}", ex.ToString());
}
省略可能な参照フレームを取得する
HDR プロセスは、複数のフレームをキャプチャし、すべてのフレームがキャプチャされた後、それらを 1 つのイメージに合成します。 フレームがキャプチャされた後、HDR プロセス全体が完了する前に OptionalReferencePhotoCaptured イベントを処理することで、フレームにアクセスできます。 最終的な HDR 写真の結果にのみ関心がある場合は、これを行う必要はありません。
Important
OptionalReferencePhotoCaptured は、ハードウェア HDR をサポートするデバイスでは発生しないため、参照フレームを生成しません。 アプリでは、このイベントが発生しないケースを処理する必要があります。
参照フレームは CaptureAsync の呼び出しのコンテキスト外に到着するため、 OptionalReferencePhotoCaptured ハンドラーにコンテキスト情報を渡すメカニズムが提供されます。 まず、コンテキスト情報を含むオブジェクトを呼び出す必要があります。 このオブジェクトの名前と内容はユーザーが指定できます。 次の使用例は、キャプチャのファイル名とカメラの向きを追跡するメンバーを持つオブジェクトを定義します。
public class MyAdvancedCaptureContextObject
{
public string CaptureFileName;
public PhotoOrientation CaptureOrientation;
}
コンテキスト オブジェクトの新しいインスタンスを作成し、そのメンバーを設定してから、オブジェクトをパラメーターとして受け取る CaptureAsync のオーバーロードに渡します。
// Add the the capture time to the file name
var fileName = String.Format("SimplePhoto_{0}_HDR.jpg", DateTime.Now.ToString("HHmmss"));
// Create a context object, to identify the capture in the OptionalReferencePhotoCaptured event
var context = new MyAdvancedCaptureContextObject()
{
CaptureFileName = fileName,
};
// Start capture, and pass the context object
AdvancedCapturedPhoto advancedCapturedPhoto = await m_advancedCapture.CaptureAsync(context);
OptionalReferencePhotoCaptured イベント ハンドラーで、OptionalReferencePhotoCapturedEventArgs オブジェクトの Context プロパティをコンテキスト オブジェクト クラスにキャストします。 次の使用例は、参照フレーム イメージと最終的な HDR イメージを区別するようにファイル名を変更し、イメージをディスクに保存します。
private async void M_advancedCapture_OptionalReferencePhotoCaptured(AdvancedPhotoCapture sender, OptionalReferencePhotoCapturedEventArgs args)
{
// Retrieve the context (i.e. what capture does this belong to?)
var context = args.Context as MyAdvancedCaptureContextObject;
// Remove "_HDR" from the name of the capture to create the name of the reference
var referenceName = context.CaptureFileName.Replace("_HDR", "");
using (var frame = args.Frame)
{
await SaveCapturedFrameAsync(frame, referenceName, context.CaptureOrientation);
}
}
すべてのフレームがキャプチャされたときに通知を受信する
HDR 写真キャプチャには 2 つの手順があります。 まず、複数のフレームがキャプチャされ、次にフレームが最終的な HDR イメージに処理されます。 ソース HDR フレームのキャプチャ中に別のキャプチャを開始することはできませんが、すべてのフレームがキャプチャされた後、HDR 後処理が完了する前にキャプチャを開始できます。 AllPhotosCaptured イベントは、HDR キャプチャが完了すると発生し、別のキャプチャを開始できることを知らせます。 一般的なシナリオは、HDR キャプチャの開始時に UI のキャプチャ ボタンを無効にしてから、 AllPhotosCaptured が発生したときに再度有効にすることです。
private void M_advancedCapture_AllPhotosCaptured(AdvancedPhotoCapture sender, object args)
{
// Update UI to enable capture button
}
AdvancedPhotoCapture オブジェクトをクリーンアップする
アプリのキャプチャが完了したら、MediaCapture オブジェクトを破棄する前に、FinishAsync を呼び出してメンバー変数を null に設定して、AdvancedPhotoCapture オブジェクトをシャットダウンする必要があります。
await m_advancedCapture.FinishAsync();
m_advancedCapture = null;
低光の写真キャプチャ
Windows 10 バージョン 1607 以降では、 AdvancedPhotoCapture を使用して、低光の設定でキャプチャされた写真の品質を向上させる組み込みのアルゴリズムを使用して写真をキャプチャできます。 AdvancedPhotoCapture クラスの低光機能を使用すると、システムは現在のシーンを評価し、必要に応じて、低光条件を補正するアルゴリズムを適用します。 アルゴリズムが不要であるとシステムが判断した場合は、代わりに通常のキャプチャが実行されます。
低照度の写真キャプチャを使用する前に、 MediaCapture オブジェクトの VideoDeviceController を取得し、 AdvancedPhotoControl プロパティを取得することで、アプリが現在実行されているデバイスでこの手法がサポートされているかどうかを確認します。 ビデオ デバイス コントローラーの SupportedModes コレクションに AdvancedPhotoMode.LowLight が含まれているかどうかを確認します。 その場合は、 AdvancedPhotoCapture を使用した低光キャプチャがサポートされます。
m_lowLightSupported = m_mediaCapture.VideoDeviceController.AdvancedPhotoControl.SupportedModes.Contains(Windows.Media.Devices.AdvancedPhotoMode.LowLight);
アプリで MediaCapture オブジェクトを初期化したら、 AdvancedPhotoCaptureSettings オブジェクトを作成し、モードを AdvancedPhotoMode.LowLight に設定します。 AdvancedPhotoControl オブジェクトの Configure メソッドを呼び出し、作成した AdvancedPhotoCaptureSettings オブジェクトを渡します。
MediaCapture オブジェクトの PrepareAdvancedPhotoCaptureAsync を呼び出し、キャプチャで使用するエンコードの種類を指定する ImageEncodingProperties オブジェクトを渡します。
if (m_lowLightSupported == false) return;
// Choose LowLight mode
var settings = new AdvancedPhotoCaptureSettings { Mode = AdvancedPhotoMode.LowLight };
m_mediaCapture.VideoDeviceController.AdvancedPhotoControl.Configure(settings);
// Prepare for an advanced capture
m_advancedCapture =
await m_mediaCapture.PrepareAdvancedPhotoCaptureAsync(ImageEncodingProperties.CreateJpeg());
写真をキャプチャするには、 CaptureAsync を呼び出します。
AdvancedCapturedPhoto advancedCapturedPhoto = await m_advancedCapture.CaptureAsync();
StorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync($"Photo_{advancedCapturedPhoto.Mode}.jpg", CreationCollisionOption.GenerateUniqueName);
IRandomAccessStream stream = await photoFile.OpenAsync(FileAccessMode.ReadWrite);
await RandomAccessStream.CopyAndCloseAsync(advancedCapturedPhoto.Frame, stream);
AdvancedPhotoCapture オブジェクトを再構成せずに複数の低光写真をキャプチャできますが、キャプチャが完了したら FinishAsync を呼び出して、オブジェクトと関連するリソースをクリーンアップする必要があります。
await m_advancedCapture.FinishAsync();
m_advancedCapture = null;
AdvancedCapturedPhoto オブジェクトの操作
AdvancedPhotoCapture.CaptureAsync は、キャプチャされた写真を表す AdvancedCapturedPhoto オブジェクトを返します。 このオブジェクトは、画像を表す CapturedFrame オブジェクトを返す Frame プロパティを公開します。 OptionalReferencePhotoCaptured イベントは、イベント引数に CapturedFrame オブジェクトも提供します。 この種類のオブジェクトを取得すると、 SoftwareBitmap の作成やイメージのファイルへの保存など、さまざまな操作を実行できます。
キャプチャされたフレームから SoftwareBitmap を取得する
オブジェクトの SoftwareBitmap プロパティにアクセスするだけで 、CapturedFrame オブジェクトから SoftwareBitmap を取得します。 ただし、ほとんどのエンコード形式では AdvancedPhotoCapture を使用した SoftwareBitmap がサポートされていないため、使用する前にプロパティが null ではないことを確認する必要があります。
SoftwareBitmap bitmap;
if (advancedCapturedPhoto.Frame.SoftwareBitmap != null)
{
bitmap = advancedCapturedPhoto.Frame.SoftwareBitmap;
}
現在のリリースでは、AdvancedPhotoCapture の SoftwareBitmap をサポートするエンコード形式は非圧縮 NV12 のみです。 そのため、この機能を使用する場合は、 PrepareAdvancedPhotoCaptureAsync を呼び出すときにそのエンコードを指定する必要があります。
m_advancedCapture =
await m_mediaCapture.PrepareAdvancedPhotoCaptureAsync(ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Nv12));
もちろん、イメージをファイルに保存してから、別の手順で ファイルを SoftwareBitmap に読み込むことができます。 SoftwareBitmap の操作の詳細については、「ビットマップ イメージの作成、編集、保存」を参照してください。
Windows developer