QR码在通用Windows
问题描述:
如何正确预览视频和识别QR(ZXing的任何代码)?QR码在通用Windows
在windows phone 8.1中我开始预览MediaCapture和VideoEffect识别QR码。
在通用Windows VideoEffect不起作用。
答
所以,我的解决办法
创建新的WinRT项目 “的Windows运行时组件(环球视窗)
在WinRT中创建
class CaptureVideoEffect : IBasicVideoEffect (from Windows.Media.Effects)
- 将效果附加到MediaCapture
现在CaptureVideoEffect.ProcessFrame(ProcessVideoFrameContext上下文)你获得实时视频输出
在CaptureVideoEffect。ProcessFrame跳过帧,如果先前没有成功解码
获取的图像作为字节[]
- 解码与
await capture.AddEffectAsync(MediaStreamType.VideoPreview, typeof(CaptureVideoEffect).FullName, ...);
var frameSize = inputFrameBitmap.PixelWidth * inputFrameBitmap.PixelHeight * 4;
var frameBuffer = new Windows.Storage.Streams.Buffer((uint)frameSize);
inputFrameBitmap.CopyToBuffer(frameBuffer);
byte[] bitmap = frameBuffer.ToArray();
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);
}
答
我认为你是正确的使用MediaCapture
和ZXing
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
功能。
你能建议一些方法来处理Windows Phone 8.1商店应用程序的视频帧?没有'CapturePhotoToStorageFileAsync'或'CapturePhotoToStreamAsync'方法。 –
@AndriiKrupka,我不确定,这里是官方的[视频稳定示例](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/CameraVideoStabilization),还有预览框架,所以我认为它是一样的。但你不想使用'CapturePhotoToStreamAsync'方法,所以我不认为它是关于视频或照片的,我只是使用Zxing的'IBarcodeReader'来解码'WriteableBitmap','WriteableBitmap'在这里是必要的。但是我没有经过整个库,也许有其他方法直接解码预览视频?你可以在我的回答中查看GitHub上的Zxing示例吗? –
我找到了我想要的东西。 http://*.com/questions/28435818/implement-realtime-barcode-scanner-on-windows-phone-8-1-runtime-using-zxing-and –