Zxing获得图像流
本文关键字:图像 Zxing | 更新日期: 2023-09-27 18:06:30
我想从QR库zxing获得UWP的视频流。
我打算将流复制成两个输出。因此,底层流可以通过Gaussian Blur Filter
,而顶部的流将在屏幕中心清晰地显示为二次几何(没有失真,就像"剪出窗口"一样)。这就产生了一种效果,用户正在扫描并聚焦于未模糊的区域(在屏幕中间),而周围是模糊的。
我打算用Lumia SDK
或新的Composition API
做模糊,这两个都应该是非常快的视频处理。
我怎样才能做到这一点?对于QR扫描仪来说,这绝对是一个漂亮的糖果,同时不会对CPU/GPU造成太大的负担。
我想从QR库zxing获得UWP的视频流
基于ZXing.Mobile
的源代码,目前还没有从ZXing
获取视频流的API,但我们可以自己实现。
让我们看看Zxing。Mobile:
-
在
MobileBarcodeScanner.Scan
方法中,它实际上导航到ScanPage
视图rootFrame.Navigate(typeof(ScanPage), new ScanPageNavigationParameters {//...... }
-
ScanPage
视图,ZXingScannerControl
控件将用于承担主要任务:<zxing:ZXingScannerControl x:Name="scannerControl"> </zxing:ZXingScannerControl>
-
在
StartScanningAsync
方法中,原理是使用MediaCapture
API启动相机预览,并调用GetPreviewFrameAsync
方法在定时器中获得预览帧,该帧可以转换为LuminanceSource
,通过BarcodeReader.Decode
方法解码该图像中的条形码。// Set the capture element's source to show it in the UI captureElement.Source = mediaCapture; // Start the preview await mediaCapture.StartPreviewAsync();
……
SoftwareBitmapLuminanceSource luminanceSource = null; try { // Get preview var frame = await mediaCapture.GetPreviewFrameAsync(videoFrame); // Create our luminance source luminanceSource = new SoftwareBitmapLuminanceSource(frame.SoftwareBitmap);
……
ZXing.Result result = null; try { // Try decoding the image if (luminanceSource != null) result = zxing.Decode(luminanceSource);
所以底层的流可以通过高斯模糊滤镜,而顶部的流将在屏幕中心清晰地显示为二次几何(没有失真,就像"剪出窗口")。
你可以先试试MediaCapture.CapturePhotoToStreamAsync
,这里也有类似的讨论
如果你想在屏幕中央显示一个二次几何图形,你可以放置一个Canvas
来包含这些几何对象,参见官方的Basic人脸跟踪示例
<CaptureElement Name="CamPreview" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stretch="Fill" Margin="0,10,0,0" />
<Canvas Name="VisualizationCanvas" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,10,0,0" />
背后的代码:
private void SetupVisualization(Windows.Foundation.Size framePizelSize, IList<DetectedFace> foundFaces)
{
this.VisualizationCanvas.Children.Clear();
double actualWidth = this.VisualizationCanvas.ActualWidth;
double actualHeight = this.VisualizationCanvas.ActualHeight;
if (this.currentState == ScenarioState.Streaming && foundFaces != null && actualWidth != 0 && actualHeight != 0)
{
double widthScale = framePizelSize.Width / actualWidth;
double heightScale = framePizelSize.Height / actualHeight;
foreach (DetectedFace face in foundFaces)
{
// Create a rectangle element for displaying the face box but since we're using a Canvas
// we must scale the rectangles according to the frames's actual size.
Rectangle box = new Rectangle();
box.Width = (uint)(face.FaceBox.Width / widthScale);
box.Height = (uint)(face.FaceBox.Height / heightScale);
box.Fill = this.fillBrush;
box.Stroke = this.lineBrush;
box.StrokeThickness = this.lineThickness;
box.Margin = new Thickness((uint)(face.FaceBox.X / widthScale), (uint)(face.FaceBox.Y / heightScale), 0, 0);
this.VisualizationCanvas.Children.Add(box);
}
}
}