【问题标题】:How to get preview buffer of MediaCapture - Universal app如何获取 MediaCapture 的预览缓冲区 - 通用应用程序
【发布时间】:2015-02-08 06:40:38
【问题描述】:

在 Windows phone silverlight 中,我使用 PhotoCamera 在启动预览视频时获取缓冲区帧,在通用应用程序中我使用 MediaCapture,但我不知道如何获取预览缓冲区。

谢谢

【问题讨论】:

  • 这个答案现在是used elsewhere,这表明它是正确的。如果您同意,您是否可以接受它来帮助其他人解决这个问题。
  • 不是重复的。另一个答案很好,但我认为它只适用于 Windows 10,并且需要允许不安全的代码。我的回答使用 Lumia Imaging SDK,并且没有任何限制(尽管我认为它的效率要低得多)。
  • @Liero Windows 10 未在问题标题和标签中指定。这个问题是在 2014 年 12 月提出的,但 Windows 10 直到 2015 年 7 月才发布。遗憾的是,微软在 Windows 8.1 时代也使用了“通用应用程序”一词来表示跨设备应用程序。我想这就是混乱的来源。你的评论还是很有用的。 UWP 应用可以轻松访问预览帧,我将添加一个指向这一点的答案。
  • 你是对的。我删除了我的评论,你也可以。谢谢

标签: windows win-universal-app windows-store


【解决方案1】:

由于 Windows 运行时没有 Silverlight 的 PhotoCaptureDevice 类,因此非常有用的 GetPreviewBufferARGB()GetPreviewBufferYCbCr() 方法不可用。

您正在寻找的解决方案是使用MediaCapture.StartPreviewToCustomSinkAsync() 方法,但这需要比我更好的C++ 技能。似乎没有人解决了这个问题并分享了他们的代码。

现在有一个非常漂亮的解决方案,使用 Lumia Imaging SDK,它不使用 MediaCapture 类,但可能会更好地解决您的问题。

首先查看微软的example on Github。这很好用,但相当复杂,因为它同时针对 Windows 8.1 和 Windows Phone 8.1。

为了我自己的理解,我编写了一些更简单的代码,仅针对 Windows Phone。这可能会有所帮助。

从一个新的 C# Windows Phone 8.1(应用商店)应用开始,并通过 NuGet PM 安装 Lumia Imaging SDK。这个例子在MainPage.xaml 中使用x:Name="previewImage" 绘制到一个图像元素,所以请确保添加它。您还需要对MainPage.xaml.cs 进行相关导入,我认为是这样。

using Lumia.Imaging;
using System.Threading.Tasks;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Core;
using System.ComponentModel;

然后您只需在MainPage.xaml.cs 的正确位置添加以下内容。

private CameraPreviewImageSource _cameraPreviewImageSource; // Using camera as our image source
private WriteableBitmap _writeableBitmap;
private FilterEffect _effect;
private WriteableBitmapRenderer _writeableBitmapRenderer; // renderer for our images
private bool _isRendering = false; // Used to prevent multiple renderers running at once

public MainPage()
{
    this.InitializeComponent();
    this.NavigationCacheMode = NavigationCacheMode.Required;
    startCameraPreview();
}

private async Task startCameraPreview()
{
    // Create a camera preview image source (from the Lumia Imaging SDK)
    _cameraPreviewImageSource = new CameraPreviewImageSource();
    await _cameraPreviewImageSource.InitializeAsync(string.Empty); // use the first available camera (ask  me if you want code to access other camera)
    var previewProperties = await _cameraPreviewImageSource.StartPreviewAsync();
    _cameraPreviewImageSource.PreviewFrameAvailable += drawPreview; // call the drawPreview method every time a new frame is available

    // Create a preview bitmap with the correct aspect ratio using the properties object returned when the preview started.
    var width = 640.0;
    var height = (width / previewProperties.Width) * previewProperties.Height;
    var bitmap = new WriteableBitmap((int)width, (int)height);
    _writeableBitmap = bitmap;

    // Create a BitmapRenderer to turn the preview Image Source into a bitmap we hold in the PreviewBitmap object
    _effect = new FilterEffect(_cameraPreviewImageSource);
    _effect.Filters = new IFilter[0]; // null filter for now
    _writeableBitmapRenderer = new WriteableBitmapRenderer(_effect, _writeableBitmap);
}

private async void drawPreview(IImageSize args)
{
    // Prevent multiple rendering attempts at once
    if (_isRendering == false)
    {
        _isRendering = true;
        await _writeableBitmapRenderer.RenderAsync(); // Render the image (with no filter)
        // Draw the image onto the previewImage XAML element
        await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.High,
            () =>
            {
                previewImage.Source = _writeableBitmap; // previewImage is an image element in MainPage.xaml
                _writeableBitmap.Invalidate(); // force the PreviewBitmap to redraw
            });
        _isRendering = false;
    }
}

您可能想知道...如何获取 previewBuffer?你不需要!

_writeableBitmap 对象始终保存来自相机的最新帧,因此您可以用它做任何您喜欢的事情。

【讨论】:

  • XAML中的CaptureElement是否应该有一行链接到CameraPreviewImageSource?
  • 嗨,Paulina,我不这么认为。在此代码示例中,XAML 中没有 CaptureElement。每次有新帧可用时,我们调用 drawPreview 方法将其呈现为位图,然后将其绘制到 XAML 中的 previewImage 图像。这不是很有效,但它很有效,而且似乎在 Windows 10 中进行了一些优化,使其更高效。
  • 谢谢托马斯! :) 好吧,似乎从头开始是要走的路,因为我已经到处使用了 MediaCapture 对象和 CaptureElement >_
  • 在调用 _cameraPreviewImageSource.InitializeAsync 时为什么会收到“拒绝访问”消息的任何线索?
  • Paulina -- 你是否在Package.appxmanifest>Capabilities 中启用了Webcam?这是我唯一的猜测。
【解决方案2】:

我的另一个答案仍然适用于面向 Windows 8.1 的通用应用程序——但对于那些使用 UWP 应用程序以 Windows 10 为目标的用户来说,现在有一个更简单的答案。

Grabbing a preview frame in UWP is easy and well-documented -- 从现有的 MediaCapture 对象可以分三行完成。

// Get information about the preview
var previewProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;

// Create a video frame in the desired format for the preview frame
VideoFrame videoFrame = new VideoFrame(BitmapPixelFormat.Bgra8, (int)previewProperties.Height, (int)previewProperties.Width);

// Grave a preview frame        
VideoFrame previewFrame = await _mediaCapture.GetPreviewFrameAsync(videoFrame);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多