winform 调用摄像头扫码识别二维码的实现步骤
因为公司业务需求,需要在Windows系统下调用摄像头识别二维码需求,就有了这个功能。
我根据网上网友提供的一些资料,自己整合应用到项目中,效果还不错(就是感觉像素不是太好)
现在将调用摄像头+识别二维码这两个功能单独出来写到这里,供大家讨论和参考。
有什么不足或者问题大家可以提出来,共同改进共同进步
创建一个空的winform项目解决方案,我起名叫他:ScanQRCode
将Form1作为主窗体,设置相关属性:
StartPosition:CenterScreen (窗体居中)
添加一个居中标题:
private void LoadTitleCenterData() { string titleMsg ="二维码识别主界面"; Graphics g = this.CreateGraphics(); Double startingPoint = (this.Width / 2) - (g.MeasureString(titleMsg, this.Font).Width / 2); Double widthOfASpace = g.MeasureString(" ", this.Font).Width; String tmp = " "; Double tmpWidth = 0; while ((tmpWidth + widthOfASpace) < startingPoint) { tmp += " "; tmpWidth += widthOfASpace; } this.Text = tmp + titleMsg; }
最大最小化禁用:
public Form1() { this.MinimizeBox = false; this.MaximizeBox = false; InitializeComponent(); LoadTitleCenterData(); }
Form1中添加一个TableLayoutPanel,三行三列,比例按照百分比:10%,80%,10%这样
在TableLayoutPanel的80%中再添加一个TableLayoutPanel,还是行比例:20%,80%这样(二八定律)
在TableLayoutPanel中添加Panel,在其中手动在添加几个按钮和label
最终界面这样(能看就行):
添加一个二维码识别界面CameraQR:
使用Nuget添加引用,搜索AForge,将如下程序包引入:
添加一个识别二维码的窗体,命名名称为:CameraQR
将VideoSourcePlayer添加到窗体中,Fill显示:
窗体中定义几个私有变量:
private AForge.Video.DirectShow.FilterInfoCollection _videoDevices;//摄像设备 System.Timers.Timer timer;//定时器 CameraHelper _cameraHelper = new CameraHelper();//视屏设备操作类
窗体Load事件中获取拍照设备列表,并将第一个设备作为摄像设备(如有前后两个或多个摄像头,自己去改一下代码,设置成可以选择的,在CameraHelper中的CreateFilterInfoCollection()中):
private void CameraQR_Load(object sender, EventArgs e) { // 获取视频输入设备 _videoDevices = _cameraHelper.CreateFilterInfoCollection();//获取拍照设备列表 if (_videoDevices.Count == 0) { MessageBox.Show("无设备"); this.Dispose(); this.Close(); return; } resultStr = "";//二维码识别字符串清空 _cameraHelper.ConnectDevice(videoSourcePlayer1);//连接打开设备 }
组件初始化完成之后,添加一个定时任务,用来阶段性识别摄像设备中的图片资源,我写的是每200毫秒去识别一次,如果图片中有二维码,就识别二维码;识别成功之后,关闭窗体,将识别结果返回给上一个界面,此处需要一个有识别二维码程序包
使用Nuget添加引用,搜索ZXing,将如下程序包引入:
代码如下(核心代码基本就这些):
public CameraQR() { this.MinimizeBox = false; this.MaximizeBox = false; InitializeComponent(); LoadTitleCenterData(); CheckForIllegalCrossThreadCalls = false;//多线程中访问窗体控件资源不会异常 AddTimer();//定时识别图片 } private void AddTimer() { timer = new System.Timers.Timer(); timer.Enabled = true; timer.Interval = 200; timer.Start(); timer.Elapsed += new ElapsedEventHandler(PicToQRCode); } private void PicToQRCode(object sender, ElapsedEventArgs e) { if (_cameraHelper.img == null) return; BinaryBitmap bitmap = null; try { MemoryStream ms = new MemoryStream(); _cameraHelper.img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); byte[] bt = ms.GetBuffer(); ms.Close(); LuminanceSource source = new RGBLuminanceSource(bt, _cameraHelper.img.Width, _cameraHelper.img.Height); bitmap = new BinaryBitmap(new ZXing.Common.HybridBinarizer(source)); } catch (Exception ex) { return; } Result result=null; try { //开始解码 result = new MultiFormatReader().decode(bitmap); } catch (ReaderException ex) { resultStr = ex.ToString(); } if (result != null) { resultStr = result.Text; this.DialogResult = DialogResult.OK; this.Close(); }}
窗体关闭时,记得释放定时器 关闭摄像头(不然异常满天飞):
private void CameraQR_FormClosing(object sender, FormClosingEventArgs e) { if (timer != null) { timer.Dispose(); } _cameraHelper.CloseDevice(); }
CameraHelper类:
public class CameraHelper { public FilterInfoCollection _videoDevices;//本机摄像硬件设备列表 public VideoSourcePlayer _videoSourcePlayer;//视频画布 public Bitmap img = null;//全局变量,保存每一次捕获的图像 public System.Drawing.Image CaptureImage(VideoSourcePlayer sourcePlayer = null) { if (sourcePlayer == null || sourcePlayer.VideoSource == null) { if (_videoSourcePlayer == null) return null; else { sourcePlayer = _videoSourcePlayer; } } try { if (sourcePlayer.IsRunning) { System.Drawing.Image bitmap = sourcePlayer.GetCurrentVideoFrame(); return bitmap; } return null; } catch (Exception ex) { return null; } } public FilterInfoCollection CreateFilterInfoCollection() { if (_videoDevices != null) return _videoDevices; _videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); return _videoDevices; } public VideoCaptureDevice ConnectDevice(VideoSourcePlayer videoSourcePlayer, FilterInfo filterInfo = null) { VideoCaptureDevice videoSource = new VideoCaptureDevice(); if (filterInfo == null) { videoSource = new VideoCaptureDevice(_videoDevices[_videoDevices.Count - 1].MonikerString); } else { videoSource = new VideoCaptureDevice(filterInfo.MonikerString); } videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame); videoSourcePlayer.VideoSource = videoSource; videoSourcePlayer.Start(); _videoSourcePlayer = videoSourcePlayer; return videoSource; } private void video_NewFrame(object sender, NewFrameEventArgs eventArgs) { img = (Bitmap)eventArgs.Frame.Clone(); } public void CloseDevice(VideoSourcePlayer videoSourcePlayer = null) { if (videoSourcePlayer == null) { if (_videoSourcePlayer == null) return; _videoSourcePlayer.SignalToStop(); } else { videoSourcePlayer.SignalToStop(); } } }
我用的测试二维码是:
最终的别结果为:
代码:https://github.com/Binzm/ScanQRCode.git
以上就是winform 调用摄像头扫码识别二维码的实现步骤的详细内容,更多关于winform 调用摄像头识别二维码的资料请关注猪先飞其它相关文章!
相关文章
- 这篇文章主要介绍了Spring AOP 对象内部方法间的嵌套调用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-29
- <?php require('path.inc.php'); header('content-Type: text/html; charset=utf-8'); $borough_id = intval($_GET['id']); if(!$borough_id){ echo ' ...2016-11-25
- 这篇文章主要介绍了c# 三种方法调用WebService接口的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-07
- 本篇文章是对C#中WinForm控件之Dock顺序调整进行了详细的分析介绍,需要的朋友参考下...2020-06-25
- 这篇文章主要介绍了js实现调用网络摄像头及常见错误处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-07
- 这篇文章介绍了c#动态调用Webservice的两种方法实例,有需要的朋友可以参考一下...2020-06-25
- 这篇文章主要介绍了C# Winform中实现主窗口打开登录窗口关闭的方法,这在需要用户名密码的软件项目中是必用的一个技巧,要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了解决Vue watch里调用方法的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-07
- 这篇文章主要给大家介绍了关于c#中的WebService及其调用方式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
- 下面小编就为大家带来一篇C# winform打开Excel文档的方法总结(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 这篇文章主要介绍了解决vue watch数据的方法被调用了两次的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-07
- 这篇文章主要给大家介绍C# winform快捷键设置技巧,涉及到C winform快捷键相关知识,对C winform知识感兴趣的朋友可以参考下本篇文章...2020-06-25
- 下面小编就为大家带来一篇C#中加载dll并调用其函数的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
c#中Winform实现多线程异步更新UI(进度及状态信息)
本篇文章主要介绍了c#中Winform实现多线程异步更新UI(进度及状态信息) ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25- 这篇文章主要介绍了javascript实现方法调用与方法触发小结的相关资料,需要的朋友可以参考下...2016-03-30
- 本文章来给大家详细介绍在php中如何来调用执行mysql存储过程然后返回由存储过程返回的值了,有需要了解的同学可进入参考。 。调用存储过程的方法。 a。如果存储过...2016-11-25
- 我们要明确,为什么要进行异步回调?众所周知,普通方法运行,是单线程的,如果中途有大型操作(如:读取大文件,大批量操作数据库,网络传输等),都会导致方法阻塞,表现在界面上就是,程序卡或者死掉,界面元素不动了,不响应了...2020-06-25
- 这篇文章主要介绍了C#调用python脚本的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
- 这篇文章主要给大家介绍了关于c# winform异步不卡界面的实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用c#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-06-25
C# WinForm程序处理后台繁忙导致前台控件假死现象解决方法
这篇文章主要介绍了C# WinForm程序处理后台繁忙导致前台控件假死现象解决方法,本文通过Application.DoEvents()解决这个问题,并讲解了Application.DoEvents()的作用,需要的朋友可以参考下...2020-06-25