前段时间看到一篇博客,是这个功能的,参考了那篇博客写了这个功能玩一玩,没有做商业用途。发现他的代码给的有些描述不清晰的,我就自己整理一下发出来记录一下。
参考博客链接: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 else25 {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 #endregion13 #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 try22 {23 //开始解码24 result = multiFormatReader.decode(bitmap);//(不定期暴毙)25 }26 catch (Exception ex)27 {28 return;29 }30 finally31 {32 multiFormatReader.reset();33 34 }35 36 37 if (result != null)38 {39 textBox1.Text = result.Text;40 41 }42 #endregion43 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 #endregion116 #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 try125 {126 //开始解码127 result = multiFormatReader.decode(bitmap);//(不定期暴毙)128 }129 catch (Exception ex)130 {131 return;132 }133 finally134 {135 multiFormatReader.reset();136 137 }138 139 140 if (result != null)141 {142 textBox1.Text = result.Text;143 144 }145 #endregion146 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 }
参考文章 https://www.cnblogs.com/geeking/p/4181450.html
联系客服