前段時間看到一篇博客,是這個功能的,參考了那篇博客寫了這個功能玩一玩,沒有做商業用途。發現他的代碼給的有些描述不清晰的,我就自己整理一下發出來記錄一下。 參考博客鏈接:https://www.cnblogs.com/geeking/p/4181450.html 好了 進入正題。 項目環境 項目代碼的 ...
前段時間看到一篇博客,是這個功能的,參考了那篇博客寫了這個功能玩一玩,沒有做商業用途。發現他的代碼給的有些描述不清晰的,我就自己整理一下發出來記錄一下。
參考博客鏈接: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 }View Code
參考文章 https://www.cnblogs.com/geeking/p/4181450.html