顯示具有 QRCode 標籤的文章。 顯示所有文章
顯示具有 QRCode 標籤的文章。 顯示所有文章

2013/9/4

[C#] WebCam QRCode Reader

之前的文章寫到使用WebCam錄影拍照  和 QRCode Reader
有這兩個基礎的功能,我們很容易就可以把WebCam 變成 QRCode Reader


一開始先做畫面
先拉一個button,label,pictureBox
在button的處裡事件裡面寫
開啟攝影機和Timer
這是WebCam錄影拍照  的一些方法
        private void button1_Click(object sender, EventArgs e)
        {
            openWebCam();
            _timer.Start();
        }

觸發Tiemr之後就每0.1秒擷取畫面一次
將畫面顯示在 pictureBox 中
並且將擷取的畫面丟給QRCode Reader去解碼
當成功讀到QRCode時,將當時的影像儲存下來
        private void TimerEventProcessor(object sender, EventArgs e)
        {
            Image<Bgr, Byte> frame = cap.QueryFrame(); // Query 攝影機的畫面

            pictureBox1.Image = frame.ToBitmap(); // 把畫面轉換成bitmap型態,在丟給pictureBox元件

            //宣告 QRCode Reader 物件
            ZXing.IBarcodeReader reader = new ZXing.BarcodeReader();
            // bitmap = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromFile(@"D:\Test\QRCode\temp.png");

            //將攝影影擷取的畫面直接丟進Reader 進行解碼
            ZXing.Result result = reader.Decode(frame.ToBitmap());

            if (result != null)
            {   //如果有成功解讀,則顯示文字

                //在Thread裡面不能直接跟控制項(Text)互動,所以使用委派(Delegate)的方式
                this.Invoke(new InvokeFunction(this.TrueFunction), new object[] { result.Text });

                //將解讀成功的影像存下來
                //儲存路徑
                _fileName = string.Format("{0}{1}{2}", _phtoDirectory, DateTime.Now.ToString("yyyyMMddHmmss"), ".PNG");

                //儲存影像
                frame.Save(_fileName);
            }
        }

當成功讀到QRCode的同時也顯示在畫面上
這邊就要使用委派(Delegate)的方式

        private delegate void InvokeFunction(string msg); 

        private void TrueFunction(string msg)
        {
            //顯示QRCode訊息
            this.label1.Text = msg;
        } 

之後到 D:\Test\QRCode
就可以發現成功讀取時的影像了

討論:
我使用的攝影機是只有500萬畫素沒有自動對焦的WebCam
一開始在測試時都讀不到QRCode,後來慢慢測試各種距離才發現
只有大概在距離60公分左右才讀的到...

當然每一款攝影機的焦距都不一樣,所以就要多試幾次吧
但是如果有自動對焦的WebCam效果應該很好吧

DEMO

2013/8/29

[C#] QRCode Generator & Reader

現在很多海報、廣告等文宣上面角落都會放一個QRCode(二維條碼)
方便智慧型手機讀取資料及連結網站

QRCode 當初的設計就是希望能方便被讀取,希望節省輸入的時間
裡面最多可以藏入1800個中文字,可以提供的服務就相當廣泛....

QRCode 編碼&解碼方式其實沒有什麼機密
很多元件都已經都寫好,就因為是這樣才能廣泛的被利用





使用之前要先下載一個開放的函示庫(DLL) "Zxing"
解壓縮之後找到適合開發環境的版本
在裡面就可以看到 zxing.dll ,這這個檔案複製到開發的專案中

接著打開 Visual Studio 加入參考

這樣就設定完成了
接下來就可以開始寫程式了...(當然是要先拉一下畫面拉)

        private void button1_Click(object sender, EventArgs e)
        {
            System.Drawing.Bitmap bitmap = null;
            //要轉成QRCode 的內容
            string content = textBox1.Text;
            //QRCode的設定
            ZXing.BarcodeWriter writer = new ZXing.BarcodeWriter
            {
                Format = ZXing.BarcodeFormat.QR_CODE,
                Options = new ZXing.QrCode.QrCodeEncodingOptions
                {
                    //產生出圖片的高度
                    Height = 180,
                    //產生出圖片的寬度
                    Width = 180,
                    //文字是使用哪種編碼方式
                    CharacterSet = "UTF-8",

                    //錯誤修正容量
                    //L水平    7%的字碼可被修正
                    //M水平    15%的字碼可被修正
                    //Q水平    25%的字碼可被修正
                    //H水平    30%的字碼可被修正
                    ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H

                }
            };
            //將要編碼的文字產生出QRCode的圖檔
            bitmap = writer.Write(content);
            //儲存圖片
            bitmap.Save(@"D:\Test\QRCode\temp.png", System.Drawing.Imaging.ImageFormat.Png);
            //顯示在畫面中
            pictureBox1.Image = bitmap;
        }

到這邊就可以產生出QRCode的圖檔了

編碼跟產生檔案很簡單就完成了
有發現產生的QRCode的複雜程度會跟裡面包含的文字長度成正比嗎?

解碼也一樣很簡單

        private void button2_Click(object sender, EventArgs e)
        {
            System.Drawing.Bitmap bitmap = null;
            //宣告 QRCode Reader 物件
            ZXing.IBarcodeReader reader = new ZXing.BarcodeReader();

            //讀取要解碼的圖片
            FileStream fs = new FileStream(@"D:\Test\QRCode\temp.png", FileMode.Open);
            Byte[] data = new Byte[fs.Length];
            // 把檔案讀取到位元組陣列
            fs.Read(data, 0, data.Length);
            fs.Close();
            // 實例化一個記憶體資料流 MemoryStream,將位元組陣列放入
            MemoryStream ms = new MemoryStream(data);
            // 將記憶體資料流的資料放到 BitMap的物件中
            bitmap = (Bitmap)Image.FromStream(ms);

           //將圖片顯示於 PictureBox 中
            pictureBox2.Image = bitmap;
            //進行解碼的動作
            ZXing.Result result = reader.Decode(bitmap);
            
            if (result != null)
            {   //如果有成功解讀,則顯示文字
                label1.Text = result.Text;
            }
        }

在讀取圖檔的時候有遇到一些問題
原本讀取的寫法是
bitmap = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromFile(@"D:\Test\QRCode\temp.png");

這樣的寫法在讀取後要再產生新的圖片就會發生錯誤


研究了一下發現Image還在開啟的狀態,不能進行寫入的動作
所以一開始將圖片讀出來放到Memory就可以了

參考文獻: http://blog.miniasp.com/post/2009/05/30/A-generic-error-occurred-in-GDI-plus.aspx

很簡單就可以自己製作QRCode吧
雖然Google上可以找到很多工具可以使用
但是還是自己做比較有FU~~

下次就可以連結攝影機來解讀QRcode了!!

DEMO