C# winfrom调用摄像头扫描二维码(完整版)
程序员文章站
2023-10-16 17:44:14
前段时间看到一篇博客,是这个功能的,参考了那篇博客写了这个功能玩一玩,没有做商业用途。发现他的代码给的有些描述不清晰的,我就自己整理一下发出来记录一下。 参考博客链接:https://www.cnblogs.com/geeking/p/4181450.html 好了 进入正题。 项目环境 项目代码的 ......
前段时间看到一篇博客,是这个功能的,参考了那篇博客写了这个功能玩一玩,没有做商业用途。发现他的代码给的有些描述不清晰的,我就自己整理一下发出来记录一下。
参考博客链接:
好了 进入正题。
项目环境
项目代码的版本是.net4.0的
主要采用的插件是
都是我在网上找的资源插件 版本的话 随意吧 我也不知道哪个版本最适用了。
aforge主要是调用摄像头的
zxing是调用解析二维码的 其实还有生成二维码的功能。
前台界面
这里的窗体只是放了一个列表标签,存储电脑上面的摄像头设备(如果没有就不能用这个功能了) 另外的一个开启关闭按钮,一个图片控件控制显示图片。一个文本框展示解析出来的二维码地址。
另外还有两个time控件完成图片的刷新,控制图片刷新的频率。
代码部分
后台代码如下:(不想看解析的直接划到最后 有全部的源码展示)
首先是加载部分的代码,主要用于调用插件获取摄像头设备。
1 private void form1_load(object sender, eventargs e) 2 { 3 //获取摄像头列表 4 getcamlist(); 5 }
1 /// <summary> 2 /// 获取摄像头列表 3 /// </summary> 4 private void getcamlist() 5 { 6 try 7 { 8 //aforge.video.directshow.filterinfocollection 设备枚举类 9 videodevices = new filterinfocollection(filtercategory.videoinputdevice); 10 //清空列表框 11 combobox1.items.clear(); 12 if (videodevices.count == 0) 13 throw new applicationexception(); 14 deviceexist = true; 15 //加入设备 16 foreach (filterinfo device in videodevices) 17 { 18 combobox1.items.add(device.name); 19 } 20 //默认选择第一项 21 combobox1.selectedindex = 0; 22 } 23 catch (applicationexception) 24 { 25 deviceexist = false; 26 combobox1.items.add("未找到可用设备"); 27 } 28 }
下一步 是声明的全局变量代码
filterinfocollection videodevices; //所有摄像头 videocapturedevice videosource; //当前摄像头 public int selecteddeviceindex = 0; /// <summary> /// 全局变量,标示设备摄像头设备是否存在 /// </summary> bool deviceexist; /// <summary> /// 全局变量,记录扫描线距离顶端的距离 /// </summary> int top = 0; /// <summary> /// 全局变量,保存每一次捕获的图像 /// </summary> bitmap img = null;
然后是点击开始按钮的代码
1 private void start_click(object sender, eventargs e) 2 { 3 if (start.text == "开始") 4 { 5 if (deviceexist) 6 { 7 //视频捕获设备 8 videosource = new videocapturedevice(videodevices[combobox1.selectedindex].monikerstring); 9 //捕获到新画面时触发 10 videosource.newframe += new newframeeventhandler(video_newframe); 11 //先关一下,下面再打开。避免重复打开的错误 12 closevideosource(); 13 //设置画面大小 14 videosource.desiredframesize = new size(160, 120); 15 //启动视频组件 16 videosource.start(); 17 start.text = "结束"; 18 //启动定时解析二维码 19 timer1.enabled = true; 20 //启动绘制视频中的扫描线 21 timer2.enabled = true; 22 } 23 } 24 else 25 { 26 if (videosource.isrunning) 27 { 28 timer2.enabled = false; 29 timer1.enabled = false; 30 closevideosource(); 31 start.text = "开始"; 32 } 33 } 34 }
两个timer控件的代码
1 private void timer1_tick(object sender, eventargs e) 2 { 3 if (img == null) 4 { 5 return; 6 } 7 #region 将图片转换成byte数组 8 memorystream ms = new memorystream(); 9 img.save(ms, system.drawing.imaging.imageformat.bmp); 10 byte[] bt = ms.getbuffer(); 11 ms.close(); 12 #endregion 13 #region 不稳定的二维码解析端口 14 luminancesource source = new rgbluminancesource(bt, img.width, img.height); 15 binarybitmap bitmap = new binarybitmap(new zxing.common.hybridbinarizer(source)); 16 17 result result; 18 19 multiformatreader multiformatreader = new multiformatreader(); 20 21 try 22 { 23 //开始解码 24 result = multiformatreader.decode(bitmap);//(不定期暴毙) 25 } 26 catch (exception ex) 27 { 28 return; 29 } 30 finally 31 { 32 multiformatreader.reset(); 33 34 } 35 36 37 if (result != null) 38 { 39 textbox1.text = result.text; 40 41 } 42 #endregion 43 44 45 46 } 47 private void timer2_tick(object sender, eventargs e) 48 { 49 if (img == null) 50 { 51 return; 52 } 53 bitmap img2 = (bitmap)img.clone(); 54 pen p = new pen(color.red); 55 graphics g = graphics.fromimage(img2); 56 point p1 = new point(0, top); 57 point p2 = new point(picturebox1.width, top); 58 g.drawline(p, p1, p2); 59 g.dispose(); 60 top += 2; 61 62 top = top % picturebox1.height; 63 picturebox1.image = img2; 64 65 }
以及关闭摄像头的方法:
1 /// <summary> 2 /// 关闭摄像头 3 /// </summary> 4 private void closevideosource() 5 { 6 if (!(videosource == null)) 7 if (videosource.isrunning) 8 { 9 videosource.signaltostop(); 10 videosource = null; 11 } 12 }
基本的操作都是在dll方法里面封装的,zxing代码好像是用java写的吧 ,我自己的电脑上运行这里的代码 有时候会报错,所以对于源代码改了一下,现在至少跑起来应该还行,此文章只是为了自己总结知识点用的,如果涉及侵权,请通知,会立即删除。
另附所有代码内容
1 public partial class form1 : form 2 { 3 filterinfocollection videodevices; //所有摄像头 4 videocapturedevice videosource; //当前摄像头 5 public int selecteddeviceindex = 0; 6 public form1() 7 { 8 initializecomponent(); 9 } 10 /// <summary> 11 /// 全局变量,标示设备摄像头设备是否存在 12 /// </summary> 13 bool deviceexist; 14 /// <summary> 15 /// 全局变量,记录扫描线距离顶端的距离 16 /// </summary> 17 int top = 0; 18 /// <summary> 19 /// 全局变量,保存每一次捕获的图像 20 /// </summary> 21 bitmap img = null; 22 23 private void video_newframe(object sender, newframeeventargs eventargs) 24 { 25 img = (bitmap)eventargs.frame.clone(); 26 27 } 28 29 /// <summary> 30 /// 关闭摄像头 31 /// </summary> 32 private void closevideosource() 33 { 34 if (!(videosource == null)) 35 if (videosource.isrunning) 36 { 37 videosource.signaltostop(); 38 videosource = null; 39 } 40 } 41 /// <summary> 42 /// 获取摄像头列表 43 /// </summary> 44 private void getcamlist() 45 { 46 try 47 { 48 //aforge.video.directshow.filterinfocollection 设备枚举类 49 videodevices = new filterinfocollection(filtercategory.videoinputdevice); 50 //清空列表框 51 combobox1.items.clear(); 52 if (videodevices.count == 0) 53 throw new applicationexception(); 54 deviceexist = true; 55 //加入设备 56 foreach (filterinfo device in videodevices) 57 { 58 combobox1.items.add(device.name); 59 } 60 //默认选择第一项 61 combobox1.selectedindex = 0; 62 } 63 catch (applicationexception) 64 { 65 deviceexist = false; 66 combobox1.items.add("未找到可用设备"); 67 } 68 } 69 70 private void start_click(object sender, eventargs e) 71 { 72 if (start.text == "开始") 73 { 74 if (deviceexist) 75 { 76 //视频捕获设备 77 videosource = new videocapturedevice(videodevices[combobox1.selectedindex].monikerstring); 78 //捕获到新画面时触发 79 videosource.newframe += new newframeeventhandler(video_newframe); 80 //先关一下,下面再打开。避免重复打开的错误 81 closevideosource(); 82 //设置画面大小 83 videosource.desiredframesize = new size(160, 120); 84 //启动视频组件 85 videosource.start(); 86 start.text = "结束"; 87 //启动定时解析二维码 88 timer1.enabled = true; 89 //启动绘制视频中的扫描线 90 timer2.enabled = true; 91 } 92 } 93 else 94 { 95 if (videosource.isrunning) 96 { 97 timer2.enabled = false; 98 timer1.enabled = false; 99 closevideosource(); 100 start.text = "开始"; 101 } 102 } 103 } 104 private void timer1_tick(object sender, eventargs e) 105 { 106 if (img == null) 107 { 108 return; 109 } 110 #region 将图片转换成byte数组 111 memorystream ms = new memorystream(); 112 img.save(ms, system.drawing.imaging.imageformat.bmp); 113 byte[] bt = ms.getbuffer(); 114 ms.close(); 115 #endregion 116 #region 不稳定的二维码解析端口 117 luminancesource source = new rgbluminancesource(bt, img.width, img.height); 118 binarybitmap bitmap = new binarybitmap(new zxing.common.hybridbinarizer(source)); 119 120 result result; 121 122 multiformatreader multiformatreader = new multiformatreader(); 123 124 try 125 { 126 //开始解码 127 result = multiformatreader.decode(bitmap);//(不定期暴毙) 128 } 129 catch (exception ex) 130 { 131 return; 132 } 133 finally 134 { 135 multiformatreader.reset(); 136 137 } 138 139 140 if (result != null) 141 { 142 textbox1.text = result.text; 143 144 } 145 #endregion 146 147 148 149 } 150 private void timer2_tick(object sender, eventargs e) 151 { 152 if (img == null) 153 { 154 return; 155 } 156 bitmap img2 = (bitmap)img.clone(); 157 pen p = new pen(color.red); 158 graphics g = graphics.fromimage(img2); 159 point p1 = new point(0, top); 160 point p2 = new point(picturebox1.width, top); 161 g.drawline(p, p1, p2); 162 g.dispose(); 163 top += 2; 164 165 top = top % picturebox1.height; 166 picturebox1.image = img2; 167 168 } 169 170 private void form1_load(object sender, eventargs e) 171 { 172 //获取摄像头列表 173 getcamlist(); 174 } 175 176 }
参考文章