C# winfrom調用攝像頭掃描二維碼(完整版)

来源:https://www.cnblogs.com/Grande/archive/2019/11/27/11942119.html
-Advertisement-
Play Games

前段時間看到一篇博客,是這個功能的,參考了那篇博客寫了這個功能玩一玩,沒有做商業用途。發現他的代碼給的有些描述不清晰的,我就自己整理一下發出來記錄一下。 參考博客鏈接: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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 修改屏幕DPI,會觸發控制項的Unloaded/Loaded 現象/重現案例 對Unloaded/Loaded的印象: FrameworkElement, 第一次載入顯示時,會觸發Loaded。元素被釋放時,會觸發Unloaded。視窗Show/Close時,視覺樹變化都會觸發載入事件 MenuIte ...
  • 最近做項目的時候,需要對接廠商提供的 IP 攝像頭。但是他們只提供了 C++ 的 SDK,沒辦法,只能開始擼 C 的 SDK Helper 類。本篇文章主要記錄了對接 C++ DLL 需要註意的幾個地方,以及常見類型的轉換。 要對接 C++ 的 DLL,首先得知道如何引用 DLL 內的方法。在 C ...
  • 現象: 項目中導入Ocelot後,swagger頁面無法正常顯示,查看異常發現 Ocelot.Raft.RaftController 中的 Action 配置不完全,swagger掃描時不能正確生成 swagger.json 解決方法: 在掃描中隱藏Ocelot的controller,避免被swag ...
  • 一、NetworkStream的作用 和先前的流有所不同,NetworkStream的特殊性可以在它的命名空間中得以瞭解(System.Net.Sockets),聰明的你馬上就會反應過來:既然是在網路中傳輸的流,那必然有某種協議或者規則約束他,不錯,這種協議就是Tcp/Ip協議。這個是什麼東西?別急 ...
  • .net core mvc 發佈有很長時間了,但是一直沒有用過,最近突然想開發一個導航網站,於是就抽時間開發了一個專門為開發者使用的導航站點,想看的話請移步我的上一篇博客 "https://www.cnblogs.com/weiwin/p/11941684/" 這個網站雖然小但是網站該有的功能它都有 ...
  • 騰訊雲驗證碼是為網頁、App、小程式開發者提供的安全驗證服務,基於騰訊多年的大數據積累和人工智慧決策引擎,構建智能分級驗證模型,最大程度保護業務安全的同時,提供更精細化的用戶體驗。 騰訊雲-->驗證碼控制台 騰訊雲-->驗證碼控制台 在驗證碼控制台註冊 AppID 和 AppSecret,註冊後在控 ...
  • 一、介紹:圖片的上傳直接使用ajax就可以了,截取圖片的話使用到Jcrop插件。 圖片上傳資料:https://www.jb51.net/article/87654.htm 截取圖片插件:http://code.ciaoca.com/jquery/jcrop/ 前端 添加引用 1 <script s ...
  • /// <summary> /// 按前臺分頁樣式為datatable增加空行 /// </summary> /// <param name="gridPageSize">grid分頁行數</param> /// <param name="dt"></param> /// <returns></re ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...