美國做旅游網(wǎng)站寧波seo外包哪個品牌好
0 前言
🔥 優(yōu)質(zhì)競賽項目系列,今天要分享的是
🚩 python+opencv+深度學(xué)習(xí)實現(xiàn)二維碼識別
🥇學(xué)長這里給一個題目綜合評分(每項滿分5分)
- 難度系數(shù):3分
- 工作量:3分
- 創(chuàng)新點:3分
該項目較為新穎,適合作為競賽課題方向,學(xué)長非常推薦!
🧿 更多資料, 項目分享:
https://gitee.com/dancheng-senior/postgraduate
2 二維碼基礎(chǔ)概念
2.1 二維碼介紹
二維條碼/二維碼(2-dimensional bar
code)是用某種特定的幾何圖形按一定規(guī)律在平面(二維方向上)分布的、黑白相間的、記錄數(shù)據(jù)符號信息的圖形;在代碼編制上巧妙地利用構(gòu)成計算機內(nèi)部邏輯基礎(chǔ)的“0”、“1”比特流的概念,使用若干個與二進制相對應(yīng)的幾何形體來表示文字數(shù)值信息,通過圖象輸入設(shè)備或光電掃描設(shè)備自動識讀以實現(xiàn)信息自動處理:它具有條碼技術(shù)的一些共性:每種碼制有其特定的字符集;每個字符占有一定的寬度;具有一定的校驗功能等。同時還具有對不同行的信息自動識別功能、及處理圖形旋轉(zhuǎn)變化點。
2.2 QRCode
常見的二維碼為QR Code,QR全稱Quick Response,是一個近幾年來移動設(shè)備上超流行的一種編碼方式,它比傳統(tǒng)的Bar
Code條形碼能存更多的信息,也能表示更多的數(shù)據(jù)類型。
2.3 QRCode 特點
1、符號規(guī)格從版本1(21×21模塊)到版本40(177×177 模塊),每提高一個版本,每邊增加4個模塊。
2、數(shù)據(jù)類型與容量(參照最大規(guī)格符號版本40-L級):
- 數(shù)字數(shù)據(jù):7,089個字符
- 字母數(shù)據(jù): 4,296個字符
- 8位字節(jié)數(shù)據(jù): 2,953個字符
- 漢字數(shù)據(jù):1,817個字符
3、數(shù)據(jù)表示方法:
- 深色模塊表示二進制"1",淺色模塊表示二進制"0"。
4、糾錯能力:
- L級:約可糾錯7%的數(shù)據(jù)碼字
- M級:約可糾錯15%的數(shù)據(jù)碼字
- Q級:約可糾錯25%的數(shù)據(jù)碼字
- H級:約可糾錯30%的數(shù)據(jù)碼字
5、結(jié)構(gòu)鏈接(可選)
- 可用1-16個QR Code碼符號表示一組信息。每一符號表示100個字符的信息。
3 機器視覺二維碼識別技術(shù)
3.1 二維碼的識別流程
首先, 對采集的彩色圖像進行灰度化, 以提高后繼的運行速度。
其次, 去除噪聲。 采用十字形中值濾波去除噪音對二碼圖像的干擾主要是鹽粒噪聲。
利用灰度直方圖工具, 使用迭代法選取適當(dāng)?shù)拈撝?#xff0c; 對二維碼進行二值化處理,灰度化 去噪 二值化 尋找探測圖形確定旋轉(zhuǎn)角度 定位 旋轉(zhuǎn)
獲得數(shù)據(jù)使其變?yōu)榘椎缀谏珬l碼。
最后, 確定二維碼的位置探測圖形, 對條碼進行定位, 旋轉(zhuǎn)至水平后, 獲得條碼數(shù)據(jù),
以便下一步進行解碼。
3.2 二維碼定位
QR 碼有三個形狀相同的位置探測圖形, 在沒有旋轉(zhuǎn)的情況下, 這三個位置探測圖形分別位于 QR 碼符號的左上角、 右上角和左下角。
三個位置探測圖形共同組成圖像圖形。
每個位置探測圖形可以看作是由 3 個重疊的同心的正方形組成, 它們分別為 7 7 個深色模塊、 5 5 個淺模塊和 3*3 個深色模塊。
位置探測圖形的模塊寬度比為 1: 1:3: 1: 1。
這種 1: 1: 3: 1: 1 的寬度比例特征在圖像的其他位置出現(xiàn)的可能性很小, 故可以將此作為位置探測圖形的掃描特征。 基于此特征,
當(dāng)一條直線上(稱為掃描線) 被黑白相間地截為1: 1: 3:1: 1 時, 可以認為該直線穿過了位置探測圖形。
另外, 該掃描特征不受圖像傾斜的影響。 對比中的兩個 QR 碼符號可以發(fā)現(xiàn), 無論 QR碼符號是否傾斜, 都符合 1: 1: 3:1: 1 的掃描特征。
3.3 常用的掃描方法
- 在 X 方向進行依次掃描。
(1) 固定 Y 坐標(biāo)的取值, 在 X 方向上畫一條水平直線(稱為掃描線) 進行掃描。 當(dāng)掃描線被黑白相間地截為 1: 1: 3: 1: 1 時,
可以認為該直線穿過了位置探測圖形。 在實際判定時, 比例系數(shù)允許 0. 5 的誤差, 即比例系數(shù)為1 的, 允許范圍為 0. 5~1. 5, 比例系數(shù)為 3
的, 允許范圍為 2. 5~3. 5。
(2) 當(dāng)尋找到有直線穿過位置探測圖形時, 記錄下位置探測圖形的外邊緣相遇的第一點和最后一點 A 和 B。 由 A、 B
兩點為端點的線段稱為掃描線段。將掃描線段保存下來。
用相同的方法, 完成圖像中所有水平方向的掃描。
- 在 Y 方向, 使用相同的方法, 進行垂直掃描, 同樣保存掃描得到的掃描線段。
掃描線段分類掃描步驟獲得的掃描線段是沒有經(jīng)過分類的, 也就是對于特定的一條掃描線段, 無法獲知其具體對應(yīng)于三個位置探測圖形中的哪一個。
在計算位置探測圖形中心坐標(biāo)之前, 要將所有的掃描線段按照位置進行歸類。 一般采用距離鄰域法進行掃描線段的分類。
距離鄰域法的思想是: 給定一個距離閾值 dT, 當(dāng)兩條掃描線段的中點的距離小于 d T 時, 認為兩條掃描線段在同一個鄰域內(nèi), 將它們分為一類,
反之則歸為不同的類別。
距離鄰域法的具體步驟如下:
(1) 給定一個距離閾值 dT , d T要求滿足以下條件: 位于同一個位置探測圖形之中的任意兩點之間的距離小于 dT ,
位于不同位置探測圖形中的任意兩點之間的距離大于 d T
(2) 新建一個類別, 將第 1 條掃描線段歸入其中。
(3) 對于第 i 條掃描線段 l i (2≤i≤n), 做以下操作:
a) 求出 l i 的中點 C i 。
b) 分別計算C i與在已存在的每一個類別中的第一條掃描線段的中點的距離d,若 d<d T , 則直接將 l i 加入相應(yīng)類別中。
c) 若無法找到 l i 可以加入的類別, 則新建一個類別, 將 l i 加入其中。
(4) 將所有類別按照包含掃描線段的數(shù)目進行從大到小排序, 保存前 3 個類別(即
包含掃描線段數(shù)目最多的 3 個類別), 其余的視為誤判得到的掃描線段(在位置探測圖形以外的位置得到的符合掃描特征的掃描線段),
直接舍去。距離鄰域法結(jié)束后得到的分好 3 個類別的掃描線段就分別對應(yīng)了 3 個位置探測圖形。距離鄰域法的關(guān)鍵就是距離閾值的選取。 一般對于不同大小的 QR
碼圖像, 要使用不同的距離閾值。
(1) 在 X 方向的掃描線段中找出最外側(cè)的兩條, 分別取中點, 記為 A、 B。 由 A、 B兩點連一條直線。
(2) 在 Y 方向的掃描線段中找出最外側(cè)的兩條, 分別取中點, 記為 C、 D。 由 C、 D兩點連一條直線。
(3) 計算直線 AB 與直線 CD 的交點 O, 即為位置探測圖形中心點。
將 QR 碼符號的左上、 右上位置探測圖形的中心分別記為 A、 B。 連接 A、 B。 直線 AB 與水平線的夾角α 即為 QR 碼符號的旋轉(zhuǎn)角度。
對于該旋轉(zhuǎn)角度α , 求出其正弦值 sinα 與余弦值 cosα 即可。 具體計算公式如下:
位置探測圖形邊長的計算是基于無旋轉(zhuǎn)圖像的, 在無旋轉(zhuǎn)圖像中, 水平掃描線段的長度即為位置探測圖形的邊長。
水平掃描線段 AB 的長度即為位置探測圖形的邊長 X。
對于經(jīng)過旋轉(zhuǎn)的 QR 碼圖像, 先通過插值算法生成旋正的 QR 碼圖像, 然后按照如上所述的方法進
4 深度學(xué)習(xí)二維碼識別
基于 CNN 的二維碼檢測,網(wǎng)絡(luò)結(jié)構(gòu)如下
4.1 部分關(guān)鍵代碼
篇幅有限,學(xué)長在這只給出部分關(guān)鍵代碼
首先,定義一個 AlgoQrCode.h
?
#pragma once
? #include
? #include
? using namespace cv;
? using namespace std;
? class AlgoQRCode{private:Ptr<wechat_qrcode::WeChatQRCode> detector;public:bool initModel(string modelPath);string detectQRCode(string strPath);bool compression(string inputFileName, string outputFileName, int quality);void release();};?
該頭文件定義了一些方法,包含了加載模型、識別二維碼、釋放資源等方法,以及一個 detector 對象用于識別二維碼。
然后編寫對應(yīng)的源文件 AlgoQrCode.cpp
? bool AlgoQRCode::initModel(string modelPath) {
? string detect_prototxt = modelPath + "detect.prototxt";
? string detect_caffe_model = modelPath + "detect.caffemodel";
? string sr_prototxt = modelPath + "sr.prototxt";
? string sr_caffe_model = modelPath + "sr.caffemodel";
? try
? {
? detector = makePtr<wechat_qrcode::WeChatQRCode>(detect_prototxt, detect_caffe_model, sr_prototxt, sr_caffe_model);
? }
? catch (const std::exception& e)
? {
? cout << e.what() << endl;
? return false;
? }
? return true;}string AlgoQRCode::detectQRCode(string strPath){if (detector == NULL) {return "-1";}vector<Mat> vPoints;vector<cv::String> vStrDecoded;Mat imgInput = imread(strPath, IMREAD_GRAYSCALE);// vStrDecoded = detector->detectAndDecode(imgInput, vPoints);....}bool AlgoQRCode::compression(string inputFileName, string outputFileName, int quality) {Mat srcImage = imread(inputFileName);if (srcImage.data != NULL){vector<int>compression_params;compression_params.push_back(IMWRITE_JPEG_QUALITY);compression_params.push_back(quality); //圖像壓縮參數(shù),該參數(shù)取值范圍為0-100,數(shù)值越高,圖像質(zhì)量越高bool bRet = imwrite(outputFileName, srcImage, compression_params);return bRet;}return false;}void AlgoQRCode::release() {detector = NULL;}?
5 測試結(jié)果
學(xué)長這里放到樹莓派中,調(diào)用外部攝像頭進行識別,可以看到,效果還是非常不錯的
6 最后
🧿 更多資料, 項目分享:
https://gitee.com/dancheng-senior/postgraduate