欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

winform 调用摄像头扫码识别二维码

程序员文章站 2022-05-18 10:18:51
因为公司业务需求,需要在Windows系统下调用摄像头识别二维码需求,就有了这个功能。 我根据网上网友提供的一些资料,自己整合应用到项目中,效果还不错(就是感觉像素不是太好) 现在将调用摄像头+识别二维码这两个功能单独出来写到这里,供大家讨论和参考。 有什么不足或者问题大家可以提出来,共同改进共同进 ......

因为公司业务需求,需要在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  }

最大最小化禁用:

 

1  public form1()
2 {
3    this.minimizebox = false; 
4    this.maximizebox = false; 
5    initializecomponent();
6    loadtitlecenterdata();
7 }

 

 

 

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

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

在tablelayoutpanel中添加panel,在其中手动在添加几个按钮和label

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

winform 调用摄像头扫码识别二维码

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

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

winform 调用摄像头扫码识别二维码

 

添加一个识别二维码的窗体,命名名称为:cameraqr

将videosourceplayer添加到窗体中,fill显示:

winform 调用摄像头扫码识别二维码

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

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,将如下程序包引入:

winform 调用摄像头扫码识别二维码

 

 

 代码如下(核心代码基本就这些)

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 }

我用的测试二维码是:

winform 调用摄像头扫码识别二维码

最终的别结果为:

winform 调用摄像头扫码识别二维码

 

 

 代码:https://github.com/binzm/scanqrcode.git