カメラ フレームの分析の効果

この記事では、SceneAnalysisEffectFaceDetectionEffect を使ってメディア キャプチャのプレビュー ストリームの内容を分析する方法について説明します。

シーン分析効果

SceneAnalysisEffect は、メディア キャプチャのプレビュー ストリームに含まれるビデオ フレームを分析し、キャプチャ結果を向上させるための処理オプションを推奨します。 現時点では、ハイ ダイナミック レンジ (HDR) 処理を使用してキャプチャを向上できるかどうかの検出がサポートされています。

HDR の使用が推奨された場合は、次の方法で実行できます。

シーン分析の名前空間

シーン分析を使うには、基本的なメディア キャプチャに必要な名前空間に加え、次の名前空間をアプリに追加する必要があります。

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

シーン分析効果を初期化してプレビュー ストリームに追加する

ビデオ効果は、2 つの API を使って実装されます。1 つは効果の定義であり、キャプチャ デバイスで効果を初期化するために必要となる設定を提供します。もう 1 つは効果のインスタンスであり、効果を制御するために使用できます。 効果のインスタンスには、コードのいたるところからアクセスする必要があるので、通常はそのオブジェクトを保持するメンバー変数を宣言する必要があります。

private SceneAnalysisEffect _sceneAnalysisEffect;

アプリで、MediaCapture オブジェクトを初期化した後、SceneAnalysisEffectDefinition の新しいインスタンスを作成します。

MediaCapture オブジェクトに対して AddVideoEffectAsync を呼び出すことで、効果をキャプチャ デバイスに登録します。このとき、SceneAnalysisEffectDefinition を指定し、さらに MediaStreamType.VideoPreview を指定することで、効果をキャプチャ ストリームではなくビデオ プレビュー ストリームに適用することを示します。 AddVideoEffectAsync は追加されたエフェクトのインスタンスを返します。 このメソッドは複数の種類の効果について使用できるため、返されたインスタンスは SceneAnalysisEffect オブジェクトにキャストする必要があります。

シーン分析の結果を受け取るには、SceneAnalyzed イベントのハンドラーを登録する必要があります。

現時点では、シーン分析効果にはハイ ダイナミック レンジ アナライザーのみが含まれます。 効果の HighDynamicRangeControl.Enabled を true に設定して、HDR 分析を有効にします。

// Create the definition
var definition = new SceneAnalysisEffectDefinition();

// Add the effect to the video record stream
_sceneAnalysisEffect = (SceneAnalysisEffect)await _mediaCapture.AddVideoEffectAsync(definition, MediaStreamType.VideoPreview);

// Subscribe to notifications about scene information
_sceneAnalysisEffect.SceneAnalyzed += SceneAnalysisEffect_SceneAnalyzed;

// Enable HDR analysis
_sceneAnalysisEffect.HighDynamicRangeAnalyzer.Enabled = true;

SceneAnalyzed イベント ハンドラーを実装する

シーン分析の結果は、SceneAnalyzed イベント ハンドラーに返されます。 ハンドラーに渡された SceneAnalyzedEventArgs オブジェクトには、SceneAnalysisEffectFrame オブジェクトが含まれ、これには HighDynamicRangeOutput オブジェクトが含まれています。 ハイ ダイナミック レンジ出力の Certainty プロパティの値は、0 ~ 1.0 となります。0 は、HDR 処理によってキャプチャの結果が向上しないことを示します。1.0 は、HDR 処理によって結果が向上することを示します。 HDR を使うかどうかのしきい値を決めておくか、またはユーザーに結果を表示してユーザーが決めるようにすることもできます。

private void SceneAnalysisEffect_SceneAnalyzed(SceneAnalysisEffect sender, SceneAnalyzedEventArgs args)
{
    double hdrCertainty = args.ResultFrame.HighDynamicRange.Certainty;
    
    // Certainty value is between 0.0 and 1.0
    if(hdrCertainty > MyCertaintyCap)
    {
        ShowMessageToUser("Enabling HDR capture is recommended.");
    }
}

ハンドラーに渡された HighDynamicRangeOutput オブジェクトには、FrameControllers プロパティもあります。このプロパティは、HDR 処理用の可変の写真シーケンスをキャプチャするために推奨されるフレーム コントローラーを指定します。 詳しくは、「可変の写真シーケンス」をご覧ください。

シーン分析効果をクリーンアップする

キャプチャが終了したら、MediaCapture オブジェクトを破棄する前に、効果の HighDynamicRangeAnalyzer.Enabled プロパティを false に設定してシーン分析効果を無効にし、SceneAnalyzed イベント ハンドラーの登録を解除する必要があります。 効果が追加されたのはビデオ プレビュー ストリームであるため、ビデオ プレビュー ストリームを指定して MediaCapture.ClearEffectsAsync を呼び出します。 最後に、メンバー変数を null に設定します。

// Disable detection
_sceneAnalysisEffect.HighDynamicRangeAnalyzer.Enabled = false;

_sceneAnalysisEffect.SceneAnalyzed -= SceneAnalysisEffect_SceneAnalyzed;

// Remove the effect from the preview stream
await _mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);

// Clear the member variable that held the effect instance
_sceneAnalysisEffect = null;

顔検出効果

FaceDetectionEffect は、メディア キャプチャのプレビュー ストリーム内で顔の位置を特定します。 この効果によって、プレビュー ストリーム内で顔が検出されたときに通知を受け取ることができ、プレビュー フレーム内で検出された顔ごとに境界ボックスが表示されます。 サポートされているデバイスでは、シーン内の最も重要な顔に対して露出の強化やフォーカスが行われます。

顔検出の名前空間

顔検出を使うには、基本的なメディア キャプチャに必要な名前空間に加え、次の名前空間をアプリに追加する必要があります。

using Windows.Media.Core;

顔検出効果を初期化してプレビュー ストリームに追加する

ビデオ効果は、2 つの API を使って実装されます。1 つは効果の定義であり、キャプチャ デバイスで効果を初期化するために必要となる設定を提供します。もう 1 つは効果のインスタンスであり、効果を制御するために使用できます。 効果のインスタンスには、コードのいたるところからアクセスする必要があるので、通常はそのオブジェクトを保持するメンバー変数を宣言する必要があります。

FaceDetectionEffect _faceDetectionEffect;

アプリで、MediaCapture オブジェクトを初期化した後、FaceDetectionEffectDefinition の新しいインスタンスを作成します。 DetectionMode プロパティを設定して、より高速な顔検出とより正確な顔検出のどちらを優先するかを決めます。 顔検出が完了するまで待機して着信フレームが遅延すると、プレビューがぎくしゃくした感じになる場合があるため、SynchronousDetectionEnabled を設定して、顔検出を待機しないよう指定します。

MediaCapture オブジェクトに対して AddVideoEffectAsync を呼び出すことで、効果をキャプチャ デバイスに登録します。このとき、FaceDetectionEffectDefinition を指定し、さらに MediaStreamType.VideoPreview を指定することで、効果をキャプチャ ストリームではなくビデオ プレビュー ストリームに適用することを示します。 AddVideoEffectAsync は追加されたエフェクトのインスタンスを返します。 このメソッドは複数の種類の効果について使用できるため、返されたインスタンスは FaceDetectionEffect オブジェクトにキャストする必要があります。

FaceDetectionEffect.Enabled プロパティを設定して、効果を有効または無効にします。 FaceDetectionEffect.DesiredDetectionInterval プロパティを設定して、フレームを分析する頻度を調整します。 これらのプロパティはいずれも、メディア キャプチャの進行中に調整できます。


// Create the definition, which will contain some initialization settings
var definition = new FaceDetectionEffectDefinition();

// To ensure preview smoothness, do not delay incoming samples
definition.SynchronousDetectionEnabled = false;

// In this scenario, choose detection speed over accuracy
definition.DetectionMode = FaceDetectionMode.HighPerformance;

// Add the effect to the preview stream
_faceDetectionEffect = (FaceDetectionEffect)await _mediaCapture.AddVideoEffectAsync(definition, MediaStreamType.VideoPreview);

// Choose the shortest interval between detection events
_faceDetectionEffect.DesiredDetectionInterval = TimeSpan.FromMilliseconds(33);

// Start detecting faces
_faceDetectionEffect.Enabled = true;

顔が検出されたときに通知を受け取る

顔が検出されたときに、ビデオ プレビュー内で検出された顔の周りにボックスを描画するなど、特定の操作を実行するには、FaceDetected イベントに登録します。

// Register for face detection events
_faceDetectionEffect.FaceDetected += FaceDetectionEffect_FaceDetected;

イベントのハンドラーで、FaceDetectedEventArgsFaceDetectionEffectFrame.DetectedFaces プロパティにアクセスすることにより、フレームで検出されたすべての顔の一覧を取得できます。 FaceBox プロパティは、プレビュー ストリームのサイズを基準とした単位で検出された顔を含む四角形を描画する BitmapBounds 構造体です。 プレビュー ストリームの座標を画面座標に変換するサンプル コードについては、「顔検出 UWP のサンプル」をご覧ください。

private void FaceDetectionEffect_FaceDetected(FaceDetectionEffect sender, FaceDetectedEventArgs args)
{
    foreach (Windows.Media.FaceAnalysis.DetectedFace face in args.ResultFrame.DetectedFaces)
    {
        BitmapBounds faceRect = face.FaceBox;

        // Draw a rectangle on the preview stream for each face
    }
}

顔検出効果をクリーンアップする

キャプチャが終了したら、MediaCapture オブジェクトを破棄する前に、FaceDetectionEffect.Enabled で顔検出効果を無効にし、FaceDetected イベント ハンドラーを登録していた場合は登録を解除する必要があります。 効果が追加されたのはビデオ プレビュー ストリームであるため、ビデオ プレビュー ストリームを指定して MediaCapture.ClearEffectsAsync を呼び出します。 最後に、メンバー変数を null に設定します。

// Disable detection
_faceDetectionEffect.Enabled = false;

// Unregister the event handler
_faceDetectionEffect.FaceDetected -= FaceDetectionEffect_FaceDetected;

// Remove the effect from the preview stream
await _mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);

// Clear the member variable that held the effect instance
_faceDetectionEffect = null;

検出された顔に対するフォーカスや露出のサポートを確認する

すべてのデバイスに、検出された顔に基づいてフォーカスや露出を調整できるキャプチャ デバイスが搭載されているとは限りません。 顔検出はデバイス リソースを消費するため、キャプチャを強化する機能を使用できるデバイスでのみ顔検出を有効にすることもできます。 顔に基づくキャプチャの最適化が利用可能かどうかを確認するには、初期化された MediaCapture に対する VideoDeviceController を取得してから、ビデオ デバイス コントローラーの RegionsOfInterestControl を取得します。 MaxRegions で少なくとも 1 つの領域がサポートされているかどうかを確認します。 次に、AutoExposureSupported または AutoFocusSupported のいずれかが true であるかどうかを確認します。 これらの条件が満たされている場合は、デバイスで顔検出を利用してキャプチャを強化できます。

var regionsControl = _mediaCapture.VideoDeviceController.RegionsOfInterestControl;
bool faceDetectionFocusAndExposureSupported =
    regionsControl.MaxRegions > 0 &&
    (regionsControl.AutoExposureSupported || regionsControl.AutoFocusSupported);