首先我们需要引用两个第三方组件:AForge和zxing。
Aforge是摄像头操作组件,zxing是二维码识别组件。都是开源项目。避免重复造轮子。
其实一些操作代码我也是参照别人的,若侵犯您的版权,请和我联系。
此博客仅供技术交流。
下载和用法大家可以自行搜索下。
首先获取所有可用的摄像头设备,并加入到comboBox1中
1 private void getCamList() 2 { 3 try 4 { 5 //AForge.Video.DirectShow.FilterInfoCollection 设备枚举类 6 videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); 7 //清空列表框 8 comboBox1.Items.Clear(); 9 if (videoDevices.Count == 0) 10 throw new ApplicationException(); 11 //全局变量,标示设备摄像头设备是否存在 12 DeviceExist = true; 13 //加入设备 14 foreach (FilterInfo device in videoDevices) 15 { 16 comboBox1.Items.Add(device.Name); 17 } 18 //默认选择第一项 19 comboBox1.SelectedIndex = 0; 20 } 21 catch (ApplicationException) 22 { 23 DeviceExist = false; 24 comboBox1.Items.Add("未找到可用设备"); 25 } 26 }
以下是启动按钮事件代码和一些其他代码。
1 private void start_Click(object sender, EventArgs e) 2 { 3 if (start.Text == "Start") 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 = "Stop"; 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 = "Start"; 32 } 33 } 34 }
/// <summary> /// 全局变量,记录扫描线距离顶端的距离 /// </summary> int top = 0; /// <summary> /// 全局变量,保存每一次捕获的图像 /// </summary> Bitmap img = null; private void video_NewFrame(object sender, NewFrameEventArgs eventArgs) { img = (Bitmap)eventArgs.Frame.Clone(); } //close the device safely private void CloseVideoSource() { if (!(videoSource == null)) if (videoSource.IsRunning) { videoSource.SignalToStop(); videoSource = null; } }
下面的代码是在画面中绘制扫描线。
1 private void timer2_Tick(object sender, EventArgs e) 2 { 3 if (img == null) 4 { 5 return; 6 } 7 Bitmap img2 = (Bitmap)img.Clone(); 8 Pen p = new Pen(Color.Red); 9 Graphics g = Graphics.FromImage(img2); 10 Point p1 = new Point(0, top); 11 Point p2 = new Point(pictureBox1.Width, top); 12 g.DrawLine(p, p1, p2); 13 g.Dispose(); 14 top += 2; 15 16 top = top % pictureBox1.Height; 17 pictureBox1.Image = img2; 18 19 }
下面是解码二维码:
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 LuminanceSource source = new RGBLuminanceSource(bt, img.Width, img.Height); 14 BinaryBitmap bitmap = new BinaryBitmap(new ZXing.Common.HybridBinarizer(source)); 15 Result result; 16 try 17 { 18 //开始解码 19 result = new MultiFormatReader().decode(bitmap); 20 } 21 catch (ReaderException re) 22 { 23 return; 24 } 25 if (result != null) 26 { 27 textBox1.Text = result.Text; 28 29 } 30 }
用了第三方组件,开发难度真是直线下降。内部具体怎么解码的,真的是一点不知道。还望有经验的高手不吝赐教。