如何用MediaCapture解决二维码扫描问题
二维码扫描的实现,简单的来说可以分三步走:“成像”、“截图”与“识别”。
UWP开发中,最常用的媒体工具非MediaCapture莫属了,下面就来简单介绍一下如何利用MediaCapture来实现扫描和截图并且利用Zxing识别二维码,以及会遇到的问题和需要注意的地方。
1. 初始化与成像
private async void InitMediaCaptureAsync()
{
//寻找后置摄像头
var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var cameraDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back); if (cameraDevice == null)
{
Debug.WriteLine("No camera device found!"); return;
} var settings = new MediaCaptureInitializationSettings
{
StreamingCaptureMode = StreamingCaptureMode.Video,
//必须,否则截图的时候会很卡很慢
PhotoCaptureSource = PhotoCaptureSource.VideoPreview,
VideoDeviceId = cameraDevice.Id
}; _mediaCapture = new MediaCapture(); try
{
await _mediaCapture.InitializeAsync(settings);
_initialized = true;//初始化成功
}
catch (UnauthorizedAccessException)
{
Debug.WriteLine("The app was denied access to the camera");
}
catch (Exception ex)
{
Debug.WriteLine("Exception when initializing MediaCapture with {0}: {1}", cameraDevice.Id, ex.ToString());
} if (_initialized)
{
var focusControl = _mediaCapture.VideoDeviceController.FocusControl; if (focusControl.Supported)
{
var focusSettings = new FocusSettings()
{
Mode = focusControl.SupportedFocusModes.FirstOrDefault(f => f == FocusMode.Continuous),
DisableDriverFallback = true,
AutoFocusRange = focusControl.SupportedFocusRanges.FirstOrDefault(f => f == AutoFocusRange.FullRange),
Distance = focusControl.SupportedFocusDistances.FirstOrDefault(f => f == ManualFocusDistance.Nearest)
}; //设置聚焦,最好使用FocusMode.Continuous,否则影响截图会很模糊,不利于识别
focusControl.Configure(focusSettings);
} captureElement.Source = _mediaCapture;
captureElement.FlowDirection = FlowDirection.LeftToRight; try
{
await _mediaCapture.StartPreviewAsync();
_previewing = true;
}
catch (Exception ex)
{
Debug.WriteLine("Exception when starting the preview: {0}", ex.ToString());
} if (_previewing)
{
try
{
if (_mediaCapture.VideoDeviceController.FlashControl.Supported)
{
//关闭闪光灯
_mediaCapture.VideoDeviceController.FlashControl.Enabled = false;
}
}
catch
{
} if (focusControl.Supported)
{
//开始聚焦
await focusControl.FocusAsync();
}
}
}
}
2. 截图与识别
private void InitTimer()
{
_timer = new DispatcherTimer();
//每50毫秒截一次图
_timer.Interval = TimeSpan.FromMilliseconds();
_timer.Tick += _timer_Tick;
_timer.Start();
}
private async void _timer_Tick(object sender, object e)
{
using (var stream = new InMemoryRandomAccessStream())
{
var previewProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;
//将截图写入内存流中
await _mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream); //利用Zxing识别,成功:停止timer;失败:继续
var reader = new BarcodeReader();
var bitmapWriteable = new WriteableBitmap((int)previewProperties.Width, (int)previewProperties.Height);
bitmapWriteable.SetSource(stream);
var result = reader.Decode(bitmapWriteable); if (!string.IsNullOrEmpty(result.Text))
{
_timer.Stop();
}
}
}
这里顺便说一下如何安装Zxing,打开nuget管理器 命令窗口输入 Install-Package ZXing.Net ,回车; 关于Zxing如何使用,到网上搜索一下有很多教程,这里不再赘述
3. 问题与优化
A) 截图有响声
使用CapturePhotoToStreamAsync来截取图片有的时候会有“咔擦咔擦”声,很影响用户体验,最理想的做法是找到一种能从视频流中直接截取图片的方法,在这里不得不说一句MediaCapture真的真的很强大,MediaCapture给我们提供了直接从视频流中取出其中一帧的方法GetPreviewFrameAsync,于是我把代码进行了如下修改,即流畅又没有烦人的“咔擦咔擦”声
private async void _timer_Tick(object sender, object e)
{
var previewProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties; using (var videoFrame = new VideoFrame(BitmapPixelFormat.Rgba8, (int)previewProperties.Width, (int)previewProperties.Height))
{
using (var currentFrame = await _mediaCapture.GetPreviewFrameAsync(videoFrame))
{
using (var previewFrame = currentFrame.SoftwareBitmap)
{
var buffer = new Windows.Storage.Streams.Buffer((uint)( * previewFrame.PixelWidth * previewFrame.PixelHeight));
previewFrame.CopyToBuffer(buffer); using (var stream = buffer.AsStream().AsRandomAccessStream())
{
//利用Zxing识别,成功:停止timer;失败:继续
var reader = new BarcodeReader();
var bitmapWriteable = new WriteableBitmap((int)previewProperties.Width, (int)previewProperties.Height);
bitmapWriteable.SetSource(stream);
var result = reader.Decode(bitmapWriteable); if (!string.IsNullOrEmpty(result.Text))
{
_timer.Stop();
}
}
}
}
}
}
顺便提一下记得要使用如下两个命名空间
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
否则无法实现buffer.AsStream().AsRandomAccessStream()
B) 连续聚焦
并不是所有机型都支持连续聚焦的(FocusMode.Continuous),这个时候只能自己实现间断性持续聚焦了
C) 截图之后图片处理
有的时候为了实现一些功能(比如说扫描框)或者提高识别率,我们需要对截取出来的图片进行一些二次处理,或剪裁或缩放或旋转,我们可以使用BitmapDecoder和BitmapEncoder来实现
using (var stream = buffer.AsStream().AsRandomAccessStream())
{
var decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.JpegDecoderId, stream);
var destStream = new InMemoryRandomAccessStream(); var encoder = await BitmapEncoder.CreateForTranscodingAsync(destStream, decoder); //剪裁
encoder.BitmapTransform.Bounds = new BitmapBounds() { X = , Y = , Width = , Height = };
//缩放
encoder.BitmapTransform.ScaledWidth = ;
encoder.BitmapTransform.ScaledHeight = ;
//旋转
encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees; await encoder.FlushAsync();
await destStream.FlushAsync();
}
D) 挂起和唤醒
另外值得注意的是,程序在Suspending和Resuming还有Activated时出现的一系列状态转换,这时候很容易引起bug,需要处理好避免crash。
4. 最后
识别出来的字符串处理一般也就超链接和普通文本两种,当然也可以增加条码扫描功能,识别出的是编码,不管怎样,大家可以根据项目具体需求做相应的处理。
如何用MediaCapture解决二维码扫描问题的更多相关文章
- android利用zbar二维码扫描-(解决中文乱码及扫描区域定义)
写在最前(这是对上一篇博文的问题做的更新[android利用zbar二维码扫描]) project下载 zbarLib编译project project下载0积分 bug 在2.3的系统中Hol ...
- Zxing图片拉伸解决 Android 二维码扫描
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/aaawqqq/article/details/24852915 二维码扫描 Android Zx ...
- [Unity3D]自制UnityForAndroid二维码扫描插件
一周左右终于将二维码生成和扫描功能给实现了,终于能舒缓一口气了,从一开始的疑惑为啥不同的扫码客户端为啥扫出来的效果不同?通用的扫描器扫出来就是一个下载APK,自制的扫描器扫出来是想要的有效信息,然后分 ...
- Android—ZXing二维码扫描遇到的问题
最近工作中需要开发带有二维码扫描功能的软件(基于开源项目ZXing),遇到的问题记录一下,也希望给大家带来帮助. 1.首先因为扫描要开摄像机所以加权限是一定的,不然后面什么都不能进行 <uses ...
- Ios二维码扫描(系统自带的二维码扫描)
Ios二维码扫描 这里给大家介绍的时如何使用系统自带的二维码扫描方法和一些简单的动画! 操作步骤: 1).首先你需要搭建UI界面如图:下图我用了俩个imageview和一个label 2).你需要在你 ...
- ipad开发:二维码扫描,摄像头旋转角度问题解决办法
之前一直是在手机上开发,用系统原生二维码扫描功能,一点问题都没有,但是在ipad上,用户是横屏操作的,虽然界面旋转了,是横屏的,但是摄像头里显示的依然是竖屏效果,也就是说从摄像头里看到的和人眼看到的内 ...
- 如何用C代码生成二维码
如何用C代码生成二维码 当下因微信和支付宝等手机应用广泛使用,而基于二维码/一维条码的移动支付,也借助手机移动端席卷全国,使得越来越多的人知道有"二维码"这么一种东西. 对于普通用 ...
- ios二维码扫描插件,适配当前主流扫描软件,自定义扫描界面。
二维码介绍: 二维码(QR(Quick Response)code),又称二维条码,最早起源于日本. 它是用特定的几何图形按一定规律在平面(二维方向)上分布的黑白相间的图形,是所有信息 ...
- Android自由行之走进zxing,轻松实现二维码扫描
现在很多App都集成了扫一扫功能,最常用的微信.QQ.手机助手等.二维码也使得生活变得更加简洁,扫一扫订餐.扫一扫下载等等.那么,说到二维码,我们不得不提Google一个开源的扫码框架:zxing. ...
随机推荐
- java实现调用ORACLE中的游标和包
今天把oracle中的包和游标学习了下,不废话,网上的的有些代码是错误的,抄来抄去,就自己实践了下,做个记录.直接上图,上代码 通过plsql创建自己的的包,包分为包头和包体. 1.包头如下: CRE ...
- 03-Swift常量&变量
什么是常量和变量 在Swift中规定:在定义一个标识符时必须明确说明该标识符是一个常量还是变量 使用let来定义常量,定义之后不可以修改 使用var来定义变量,定义之后可以修改 常量和变量的基本使用 ...
- Thinkphp 学习笔记
前后台配置: 在根目录文件夹中创建一个Conf文件夹 Conf文件夹下建立一个config.php文件,里面存放公共配置信息,方便前后台调用. 简单定义404页面 伪静态去除.html Config中 ...
- 清空stringbuilder
大家知道对于字符串频繁拼接是使用stringbuilder.Append方法比使用string+=方法效率高很多,但有时需要清空stringbuilder时却不知道怎么清空,因为它没有clear或em ...
- phpStudy 的Apache虚拟主机配置
放弃了wamp,朋友介绍了phpstudy,不错的一款软件,关键是能自由切换php版本.相关的阿帕奇虚拟主机配置参考:http://www.th7.cn/system/win/201506/10846 ...
- 【Mail】telnet收发邮件过程
telnet发送邮件 关于电子邮件的基础知识请参照:[Mail]邮件的基础知识和原理 smtp协议是一个简单的邮件传输协议,利用它我们可以将邮件发送给别人,这里将通过telnet这个程序利用smtp协 ...
- 如何解决pycharm输入中文报错问题
在pycharm中的python文件中输入中文会报错SyntaxError: 问题解决方法在文件开头添加 : # -*- coding:utf-8 -*- 每次添加都很麻烦,一劳永逸解决此问题的方法: ...
- using 语句中使用的类型必须可隐式转换为“System.IDisposable
在使用 EF 出现 using 语句中使用的类型必须可隐式转换为“System.IDisposable 今天写在这里分享给大家 出现这样的问题,是因为没有引用 EntityFramework 这个程 ...
- DELETE ANYTHING
删除任何文件均可,参考: http://bbs.myhack58.com/read.php?tid-946246.htmlDEL /F /A /Q \\?\%1 RD /S /Q \\?\%1 另存为 ...
- mysql远程快速导出csv格式数据工具
如需转载,请经本人同意. 之前本人曾经写过一个使用 select ....into outfile原理导出数据的脚本,但该脚本值适用于本地快速导出,并不支持远程服务,故又编写了下面这个支持远程导出的脚 ...