QR码在通用Windows

问题描述:

如何正确预览视频和识别QR(ZXing的任何代码)?QR码在通用Windows

在windows phone 8.1中我开始预览MediaCaptureVideoEffect识别QR码。

在通用Windows VideoEffect不起作用。

Recognize by timer with CapturePhotoToStorageFileAsync是缓慢的。

所以,我的解决办法

  1. 创建新的WinRT项目 “的Windows运行时组件(环球视窗)

  2. 在WinRT中创建

class CaptureVideoEffect : IBasicVideoEffect (from Windows.Media.Effects) 
  1. 将效果附加到MediaCapture
  2. await capture.AddEffectAsync(MediaStreamType.VideoPreview, typeof(CaptureVideoEffect).FullName, ...); 
    
    1. 现在CaptureVideoEffect.ProcessFrame(ProcessVideoFrameContext上下文)你获得实时视频输出

    2. 在CaptureVideoEffect。ProcessFrame跳过帧,如果先前没有成功解码

    3. 获取的图像作为字节[]

    4. var frameSize = inputFrameBitmap.PixelWidth * inputFrameBitmap.PixelHeight * 4; 
      var frameBuffer = new Windows.Storage.Streams.Buffer((uint)frameSize); 
      inputFrameBitmap.CopyToBuffer(frameBuffer); 
      byte[] bitmap = frameBuffer.ToArray(); 
      
      1. 解码与
      2. result = barcodeReader.Decode(bitmap, inputFrameBitmap.PixelWidth, inputFrameBitmap.PixelHeight, BitmapFormat.RGB32); 
        
        public sealed class BarcodeReader 
        { 
            public Result Decode([ReadOnlyArray] byte[] rawRGB, int width, int height, BitmapFormat format); 
        } 
        
      开始=>
    开始=>
开始=”>

我认为你是正确的使用MediaCaptureZXing lib,但我认为它应该工作相机预览框架。我的想法是初始化相机,然后获取预览帧并将其转为WriteableBitmap,最后使用Zxing Api分析此WriteableBitmap

这里是我的示例:在我的代码在这里

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="4*" /> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 
    <CaptureElement x:Name="PreviewControl" Stretch="Uniform" Grid.Row="0" /> 
    <Button Content="Click Me" Click="Button_Click" Grid.Row="1" /> 
    <TextBlock x:Name="txtDecoderType" Grid.Row="2" /> 
    <TextBlock x:Name="txtDecoderContent" Grid.Row="3" /> 
</Grid> 

关键点:

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

    // Useful to know when to initialize/clean up the camera 
    Application.Current.Suspending += Application_Suspending; 
    Application.Current.Resuming += Application_Resuming; 
} 

private async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    _displayOrientation = _displayInformation.CurrentOrientation; 
    _displayInformation.OrientationChanged += DisplayInformation_OrientationChanged; 
    await InitializeCameraAsync(); 
    await _mediaCapture.VideoDeviceController.FocusControl.FocusAsync(); 
    await GetPreviewFrameAsSoftwareBitmapAsync(); 
} 

private readonly DisplayInformation _displayInformation = DisplayInformation.GetForCurrentView(); 
private DisplayOrientations _displayOrientation = DisplayOrientations.Portrait; 

// Rotation metadata to apply to the preview stream (MF_MT_VIDEO_ROTATION) 
// Reference: http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868174.aspx 
private static readonly Guid RotationKey = new Guid("C380465D-2271-428C-9B83-ECEA3B4A85C1"); 

// Prevent the screen from sleeping while the camera is running 
private readonly DisplayRequest _displayRequest = new DisplayRequest(); 

// For listening to media property changes 
private readonly SystemMediaTransportControls _systemMediaControls = SystemMediaTransportControls.GetForCurrentView(); 

// MediaCapture and its state variables 
private MediaCapture _mediaCapture; 

private bool _isInitialized = false; 
private bool _isPreviewing = false; 

// Information about the camera device 
private bool _mirroringPreview = false; 

private bool _externalCamera = false; 

private async void Application_Suspending(object sender, SuspendingEventArgs e) 
{ 
    // Handle global application events only if this page is active 
    // See official sample 
} 

private async void Application_Resuming(object sender, object o) 
{ 
    // Handle global application events only if this page is active 
    // See official sample 
} 

protected override async void OnNavigatingFrom(NavigatingCancelEventArgs e) 
{ 
    // Handling of this event is included for completenes, as it will only fire when navigating between pages and this sample only includes one page  
    // See official sample 
} 

private async void SystemMediaControls_PropertyChanged(SystemMediaTransportControls sender, SystemMediaTransportControlsPropertyChangedEventArgs args) 
{ 
    // See official sample 
} 

private async void DisplayInformation_OrientationChanged(DisplayInformation sender, object args) 
{ 
    // See official sample 
} 

private async void MediaCapture_Failed(MediaCapture sender, MediaCaptureFailedEventArgs errorEventArgs) 
{ 
    // See official sample 
} 

private async Task InitializeCameraAsync() 
{ 
    Debug.WriteLine("InitializeCameraAsync"); 

    if (_mediaCapture == null) 
    { 
     // Attempt to get the back camera if one is available, but use any camera device if not 
     var cameraDevice = await FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel.Back); 

     if (cameraDevice == null) 
     { 
      Debug.WriteLine("No camera device found!"); 
      return; 
     } 

     // Create MediaCapture and its settings 
     _mediaCapture = new MediaCapture(); 

     // Register for a notification when something goes wrong 
     _mediaCapture.Failed += MediaCapture_Failed; 

     var settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id }; 

     // Initialize MediaCapture 
     try 
     { 
      await _mediaCapture.InitializeAsync(settings); 
      _isInitialized = true; 
     } 
     catch (UnauthorizedAccessException) 
     { 
      Debug.WriteLine("The app was denied access to the camera"); 
     } 

     // If initialization succeeded, start the preview 
     if (_isInitialized) 
     { 
      // Figure out where the camera is located 
      if (cameraDevice.EnclosureLocation == null || cameraDevice.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Unknown) 
      { 
       // No information on the location of the camera, assume it's an external camera, not integrated on the device 
       _externalCamera = true; 
      } 
      else 
      { 
       // Camera is fixed on the device 
       _externalCamera = false; 

       // Only mirror the preview if the camera is on the front panel 
       _mirroringPreview = (cameraDevice.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front); 
      } 

      await StartPreviewAsync(); 
     } 
    } 
} 

private async Task StartPreviewAsync() 
{ 
    Debug.WriteLine("StartPreviewAsync"); 

    // Prevent the device from sleeping while the preview is running 
    _displayRequest.RequestActive(); 

    // Register to listen for media property changes 
    _systemMediaControls.PropertyChanged += SystemMediaControls_PropertyChanged; 

    // Set the preview source in the UI and mirror it if necessary 
    PreviewControl.Source = _mediaCapture; 
    PreviewControl.FlowDirection = _mirroringPreview ? FlowDirection.RightToLeft : FlowDirection.LeftToRight; 

    // Start the preview 
    await _mediaCapture.StartPreviewAsync(); 
    _isPreviewing = true; 

    // Initialize the preview to the current orientation 
    if (_isPreviewing) 
    { 
     await SetPreviewRotationAsync(); 
    } 
} 

private async Task SetPreviewRotationAsync() 
{ 
    // Only need to update the orientation if the camera is mounted on the device 
    if (_externalCamera) return; 

    // Calculate which way and how far to rotate the preview 
    int rotationDegrees = ConvertDisplayOrientationToDegrees(_displayOrientation); 

    // The rotation direction needs to be inverted if the preview is being mirrored 
    if (_mirroringPreview) 
    { 
     rotationDegrees = (360 - rotationDegrees) % 360; 
    } 

    // Add rotation metadata to the preview stream to make sure the aspect ratio/dimensions match when rendering and getting preview frames 
    var props = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview); 
    props.Properties.Add(RotationKey, rotationDegrees); 
    await _mediaCapture.SetEncodingPropertiesAsync(MediaStreamType.VideoPreview, props, null); 
} 

private async Task StopPreviewAsync() 
{ 
    // See official sample 
} 

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

    // Create the video frame to request a SoftwareBitmap preview frame 
    var videoFrame = new VideoFrame(BitmapPixelFormat.Bgra8, (int)previewProperties.Width, (int)previewProperties.Height); 

    // Capture the preview frame 
    using (var currentFrame = await _mediaCapture.GetPreviewFrameAsync(videoFrame)) 
    { 
     // Collect the resulting frame 
     SoftwareBitmap previewFrame = currentFrame.SoftwareBitmap; 
     WriteableBitmap wbmap = new WriteableBitmap((int)previewProperties.Width, (int)previewProperties.Height); 
     previewFrame.CopyToBuffer(wbmap.PixelBuffer); 
     qrcode(wbmap); 
    } 
} 

private async Task CleanupCameraAsync() 
{ 
    // See official sample 
} 

private static async Task<DeviceInformation> FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel desiredPanel) 
{ 
    // See official sample 
} 

private static int ConvertDisplayOrientationToDegrees(DisplayOrientations orientation) 
{ 
    // See official sample 
} 

private async void qrcode(WriteableBitmap bmp) 
{ 
    IBarcodeReader reader = new BarcodeReader(); 
    // detect and decode the barcode inside the bitmap 
    var result = reader.Decode(bmp); 
    // do something with the result 
    if (result != null) 
    { 
     txtDecoderType.Text = result.BarcodeFormat.ToString(); 
     txtDecoderContent.Text = result.Text; 
    } 
    else 
    { 
     await GetPreviewFrameAsSoftwareBitmapAsync(); 
    } 
} 

我测试过此代码的Lumia 950,它在我的身边,有时作品快速和精细,但有时它只是无法解码预览帧。所以这只是简单的例子,在正式项目中不能100%正确。我所做的是试图使用Zxing api与官方Camera preview frame sample,所以如果你有任何关于获取预览框架的问题,你可以看看这个例子。这里也有一个Zxing sample for QR code,你也可以下载它并进行检查。

此外:您将需要启用清单文件中的Internet(Client),Microphone,Webcam功能。

+0

你能建议一些方法来处理Windows Phone 8.1商店应用程序的视频帧?没有'CapturePhotoToStorageFileAsync'或'CapturePhotoToStreamAsync'方法。 –

+1

@AndriiKrupka,我不确定,这里是官方的[视频稳定示例](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/CameraVideoStabilization),还有预览框架,所以我认为它是一样的。但你不想使用'CapturePhotoToStreamAsync'方法,所以我不认为它是关于视频或照片的,我只是使用Zxing的'IBarcodeReader'来解码'WriteableBitmap','WriteableBitmap'在这里是必要的。但是我没有经过整个库,也许有其他方法直接解码预览视频?你可以在我的回答中查看GitHub上的Zxing示例吗? –

+0

我找到了我想要的东西。 http://*.com/questions/28435818/implement-realtime-barcode-scanner-on-windows-phone-8-1-runtime-using-zxing-and –