カメラからプレビュー フレームを取得する

この記事では、WinUI 3 デスクトップ アプリのカメラ プレビュー ストリームから 1 つのプレビュー フレームをキャプチャする方法について説明します。 完全な写真を記録することなく、バーコード スキャンや顔検出などの軽量な画像分析にプレビュー フレームを使用できます。

前提条件

この記事では、 MediaCapture インスタンスを初期化し、カメラ プレビューを開始していることを前提としています。 詳細については、「 WinUI アプリでのカメラ プレビューの表示 」または 「カメラ プレビュー アクセス 」を参照してください。

プレビュー フレームを SoftwareBitmap として取得する

GetPreviewFrameAsync を呼び出して、プレビュー ストリームから 1 つのフレームを取得します。 空の VideoFrame を渡して、プレビュー ストリームの現在の形式でフレームを受信したり、特定のピクセル形式の VideoFrame を渡したりできます。

using Windows.Media;
using Windows.Media.Capture;
using Windows.Media.MediaProperties;
using Windows.Graphics.Imaging;

private async Task<SoftwareBitmap> GetPreviewFrameAsSoftwareBitmapAsync()
{
    // Get the preview stream dimensions using VideoEncodingProperties
    var previewProperties =
        _mediaCapture.VideoDeviceController
            .GetMediaStreamProperties(MediaStreamType.VideoPreview)
            as VideoEncodingProperties;

    // Create a VideoFrame to receive the preview frame.
    // VideoFrame implements IDisposable — use a using statement.
    using var previewFrame = new VideoFrame(
        BitmapPixelFormat.Bgra8,
        (int)previewProperties.Width,
        (int)previewProperties.Height);

    await _mediaCapture.GetPreviewFrameAsync(previewFrame);

    // Return a copy of the SoftwareBitmap because the
    // VideoFrame is disposed when this method returns.
    return SoftwareBitmap.Copy(previewFrame.SoftwareBitmap);
}

パラメーターを指定せずに GetPreviewFrameAsync を呼び出して、ネイティブ形式のフレームを取得することもできます。

var previewFrame = await _mediaCapture.GetPreviewFrameAsync();
SoftwareBitmap previewBitmap = previewFrame.SoftwareBitmap;

UI にプレビュー フレームを表示する

キャプチャしたフレームを Image コントロールに表示するには、 SoftwareBitmapSource に変換します。

using Microsoft.UI.Xaml.Media.Imaging;

private async Task DisplayPreviewFrameAsync(
    SoftwareBitmap softwareBitmap)
{
    // SoftwareBitmapSource requires Bgra8 with premultiplied alpha
    if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 ||
        softwareBitmap.BitmapAlphaMode != BitmapAlphaMode.Premultiplied)
    {
        softwareBitmap = SoftwareBitmap.Convert(
            softwareBitmap,
            BitmapPixelFormat.Bgra8,
            BitmapAlphaMode.Premultiplied);
    }

    var source = new SoftwareBitmapSource();
    await source.SetBitmapAsync(softwareBitmap);

    // Set the Image control's source on the UI thread
    DispatcherQueue.TryEnqueue(() =>
    {
        PreviewImage.Source = source;
    });
}

Important

WinUI 3 では、SoftwareBitmapSourceMicrosoft.UI.Xaml.Media.Imagingではなく、Windows.UI.Xaml.Media.Imaging名前空間にあります。 DispatcherQueue.TryEnqueueを使用して、CoreDispatcher.RunAsyncではなく UI を更新します。

プレビュー フレームを処理する

SoftwareBitmapを取得したら、任意の画像分析ライブラリで処理できます。 たとえば、顔検出Windows組み込みの API を使用できます。

using Windows.Media;

private async Task AnalyzePreviewFrameAsync()
{
    var previewFrame = await _mediaCapture.GetPreviewFrameAsync();
    SoftwareBitmap bitmap = previewFrame.SoftwareBitmap;

    if (bitmap != null)
    {
        // Use the bitmap for image analysis
        // For example, pass it to a face detector or
        // barcode scanner

        bitmap.Dispose();
    }

    previewFrame.Dispose();
}

Tip

処理後に VideoFrameSoftwareBitmap を破棄して、基になるメモリ バッファーをすぐに解放します。