首页 技术 正文
技术 2022年11月15日
0 收藏 771 点赞 3,078 浏览 4554 个字

因为公司业务需求,需要在Windows系统下调用摄像头识别二维码需求,就有了这个功能。

我根据网上网友提供的一些资料,自己整合应用到项目中,效果还不错(就是感觉像素不是太好)

现在将调用摄像头+识别二维码这两个功能单独出来写到这里,供大家讨论和参考。

有什么不足或者问题大家可以提出来,共同改进共同进步

创建一个空的winform项目解决方案,我起名叫他:ScanQRCode

将Form1作为主窗体,设置相关属性:

  StartPosition:CenterScreen (窗体居中)

  添加一个居中标题:

 1   private void LoadTitleCenterData()
2 {
3 string titleMsg ="二维码识别主界面";
4 Graphics g = this.CreateGraphics();
5 Double startingPoint = (this.Width / 2) - (g.MeasureString(titleMsg, this.Font).Width / 2);
6 Double widthOfASpace = g.MeasureString(" ", this.Font).Width;
7 String tmp = " ";
8 Double tmpWidth = 0;
9
10 while ((tmpWidth + widthOfASpace) < startingPoint)
11 {
12 tmp += " ";
13 tmpWidth += widthOfASpace;
14 }
15 this.Text = tmp + titleMsg;
16 }

  最大最小化禁用:

Form1中添加一个TableLayoutPanel,三行三列,比例按照百分比:10%,80%,10%这样

在TableLayoutPanel的80%中再添加一个TableLayoutPanel,还是行比例:20%,80%这样(二八定律)

在TableLayoutPanel中添加Panel,在其中手动在添加几个按钮和label

最终界面这样(能看就行):

添加一个二维码识别界面CameraQR:

使用Nuget添加引用,搜索AForge,将如下程序包引入:

将VideoSourcePlayer添加到窗体中,Fill显示:

窗体中定义几个私有变量:

1 private AForge.Video.DirectShow.FilterInfoCollection _videoDevices;//摄像设备
2 System.Timers.Timer timer;//定时器
3 CameraHelper _cameraHelper = new CameraHelper();//视屏设备操作类

窗体Load事件中获取拍照设备列表,并将第一个设备作为摄像设备(如有前后两个或多个摄像头,自己去改一下代码,设置成可以选择的,在CameraHelper中的CreateFilterInfoCollection()中):

 1  private void CameraQR_Load(object sender, EventArgs e)
2 {
3 // 获取视频输入设备
4 _videoDevices = _cameraHelper.CreateFilterInfoCollection();//获取拍照设备列表
5 if (_videoDevices.Count == 0)
6 {
7 MessageBox.Show("无设备");
8 this.Dispose();
9 this.Close();
10 return;
11 }
12 resultStr = "";//二维码识别字符串清空
13 _cameraHelper.ConnectDevice(videoSourcePlayer1);//连接打开设备
14 }

组件初始化完成之后,添加一个定时任务,用来阶段性识别摄像设备中的图片资源,我写的是每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类:

 1 public class CameraHelper
2 {
3 public FilterInfoCollection _videoDevices;//本机摄像硬件设备列表
4 public VideoSourcePlayer _videoSourcePlayer;//视频画布
5 public Bitmap img = null;//全局变量,保存每一次捕获的图像
6 public System.Drawing.Image CaptureImage(VideoSourcePlayer sourcePlayer = null)
7 {
8
9 if (sourcePlayer == null || sourcePlayer.VideoSource == null)
10 {
11 if (_videoSourcePlayer == null)
12 return null;
13 else
14 {
15 sourcePlayer = _videoSourcePlayer;
16 }
17 }
18
19 try
20 {
21 if (sourcePlayer.IsRunning)
22 {
23 System.Drawing.Image bitmap = sourcePlayer.GetCurrentVideoFrame();
24 return bitmap;
25 }
26 return null;
27
28 }
29 catch (Exception ex)
30 {
31 return null;
32 }
33 }
34
35 public FilterInfoCollection CreateFilterInfoCollection()
36 {
37 if (_videoDevices != null)
38 return _videoDevices;
39 _videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
40 return _videoDevices;
41 }
42
43 public VideoCaptureDevice ConnectDevice(VideoSourcePlayer videoSourcePlayer, FilterInfo filterInfo = null)
44 {
45 VideoCaptureDevice videoSource = new VideoCaptureDevice();
46 if (filterInfo == null)
47 {
48 videoSource = new VideoCaptureDevice(_videoDevices[_videoDevices.Count - 1].MonikerString);
49 }
50 else
51 {
52 videoSource = new VideoCaptureDevice(filterInfo.MonikerString);
53 }
54
55 videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
56 videoSourcePlayer.VideoSource = videoSource;
57 videoSourcePlayer.Start();
58 _videoSourcePlayer = videoSourcePlayer;
59 return videoSource;
60 }
61
62 private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
63 {
64 img = (Bitmap)eventArgs.Frame.Clone();
65 }
66
67 public void CloseDevice(VideoSourcePlayer videoSourcePlayer = null)
68 {
69 if (videoSourcePlayer == null)
70 {
71 if (_videoSourcePlayer == null)
72 return;
73 _videoSourcePlayer.SignalToStop();
74 }
75 else
76 {
77 videoSourcePlayer.SignalToStop();
78 }
79 }
80 }

我用的测试二维码是:

最终的别结果为:

代码:https://github.com/Binzm/ScanQRCode.git

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,083
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,558
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,407
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,180
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,817
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,900