從相機取得預覽畫面

本文展示了如何在 WinUI 3 桌面應用程式中,從相機預覽串流中擷取單一預覽畫面。 你可以使用預覽框架進行輕量級影像分析,例如條碼掃描或臉部偵測,而無需錄製完整照片。

先決條件

本文假設你已經初始化了一個 MediaCapture 實例並開始了相機預覽。 詳情請參閱「 在 WinUI 應用程式中顯示相機預覽 」或「 相機預覽權限 」。

取得預覽幀作為 SoftwareBitmap

呼叫 GetPreviewFrameAsync 以取得預覽串流中的單一幀。 你可以傳遞空的 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;

在你的介面中顯示預覽幀

若要在 影像 控制中顯示擷取的影格,請將其轉換為 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 中, 是 SoftwareBitmapSource 位於 Microsoft.UI.Xaml.Media.Imaging 命名空間,不是 Windows.UI.Xaml.Media.Imaging。 使用 DispatcherQueue.TryEnqueue 來更新使用者介面,而不是 CoreDispatcher.RunAsync。

處理預覽幀

取得 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

處理完成後,請釋放 VideoFrame 和 SoftwareBitmap,以便及時釋放底層記憶體緩衝區。