小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

一款媲美微信二維碼的識別庫,這個得知道啊

 看見就非常 2020-05-14

1、為什么要做這個庫?

相信大家在平常的生活中,如果遇到掃碼的場景第一個想到的應(yīng)該就是微信了,可以說微信使用二維碼打開了移動互聯(lián)網(wǎng)的另一扇大門,并且在掃碼體驗上及其優(yōu)秀,本該有一定要求的掃碼過程,在經(jīng)過微信的優(yōu)化之后,讓用戶在使用時擁有了一種『隨意性』,像拍一張照片一樣簡單,像發(fā)一句消息隨意,像擺弄一件玩具一樣有趣。

有了這樣的『標桿』存在,大家在潛意識里面也都有了標準,你們的掃一掃為什么不好用?為什么要識別這么久?甚至我對準了也識別不出來?擺在我們面前的是各種用戶的不滿,解決這些問題就成了我們必須要面對的情形。

2、選型

二維碼處理,繞不開的就是ZXing和ZBar了,ZXing作為老牌的識別庫已經(jīng)'孵化'出了包括js、Python、C++、PHP等各個語言的lib,同時Android版本也一直在更新,但是ZBar作為C的處理者,上次的更新已經(jīng)是7年前了。

為了讓二維碼的識別盡量的快,并且對圖像處理有更多的可能性,考量之后我們選用了更具活力的zxing-cpp,選用了它來作為我們的底層處理庫。

https://github.com/nu-book/zxing-cpp

3、相機的處理

原始圖像的獲取至關(guān)重要,倘若這一步走不好,其他的處理再好也于事無補,對于從來沒有接觸這一領(lǐng)域的自己來說,踏遍Android相機的坑不知要花多少時間,好在已經(jīng)有優(yōu)秀的開源庫,這里特別感謝BGAQRCode-Android的開源庫,操縱攝像頭的一些重要功能,比如自動對焦、觸摸對焦、放大縮小等都已經(jīng)具備,自己也只是在其之上做了一些小改進,比如GroupView的改進、加入傳感器對焦、線程池處理等等。有了這些之后,我們就可以開始處理數(shù)據(jù)了。

https://github.com/bingoogolapple/BGAQRCode-Android

4、相機數(shù)據(jù)處理

Android的相機獲取到的數(shù)據(jù)并非我們平常認為的RGB數(shù)據(jù),而是視頻采集中的經(jīng)常使用的NV21格式即YUV,所以在獲取到這些數(shù)據(jù)之后是無法直接使用的。

1、格式轉(zhuǎn)換

要轉(zhuǎn)格式首先我們先要了解NV21在內(nèi)存中是什么樣子的。

YUV420

不同于我們平常的圖片格式,比如png的圖片,圖片由一個一個像素點構(gòu)成,400 * 800的圖片就有320000個像素,每一個像素對應(yīng)一個ARGB,即4個字節(jié),分別表示(透明度,紅色色值,綠色色值,藍色色值),就是我們平常見到的(0,255,255,255)一個像素的內(nèi)存是連在一起的,但是YUV不同于我們『認知』上的格式,這3個數(shù)值分別代表的是(明亮度,色度,濃度),一個很有意思的知識是:YUV的發(fā)明是由于彩色電視與黑白電視的過渡時期。

https://zh./wiki/YUV

YUV的組成

有了一個大概的了解之后,我們就可以把攝像頭的數(shù)據(jù)轉(zhuǎn)化為我們需要的數(shù)據(jù),其實只要根據(jù)公式來推倒就可以了,但是了解原理能讓我們更好的理解。

YUV->RGB

2、算法優(yōu)化

對于二維碼來說,它是一個個黑白的點組成的,其實并不需要多么色彩斑斕的裝飾,一張灰度圖或許是更好的選擇,一般的圖像處理,都是輪詢所有像素數(shù)據(jù),對于一個或者一組數(shù)據(jù)進行處理。一個YUV轉(zhuǎn)化為RGB的算法就是要拿出所有像素,然后各種轉(zhuǎn)換,這無疑是一種浪費。一個更好的選擇是把原圖像直接轉(zhuǎn)化為灰度圖。

for( inti = top; i < height + top; ++i) {

srcIndex += left;

for( intj = left; j < left+ width; ++j, ++desIndex, ++srcIndex) {

p = data[srcIndex] & 0xFF;

pixels[desIndex] = 0xff000000| p << 16| p << 8| p;

}

srcIndex += margin;

}

3、圖片裁剪

我們知道,通常二維碼識別的界面都有一個『框』,這個框并不是可有可無的,它不僅能告訴用戶我們正在掃描,二維碼應(yīng)該放在這里面,更能在我們處理時成倍的提高處理效率,在測試的過程中,裁剪和沒有經(jīng)過裁剪的圖片處理一般要相差4-5倍的時間。

一張600 * 600的圖片識別要50-80ms;而一張完整照片,比如1920 * 1080的圖片,通常要經(jīng)過200ms以上的時間處理,如果所有的圖片都不經(jīng)過截取,那么想要提升整體的識別效率是很困難的。

圖片裁剪是一個非常必要的操作,加上我們上面的灰度轉(zhuǎn)換,兩個操作合二為一,得到灰度圖的同時也裁剪了圖像。經(jīng)過簡單的處理之后,這個圖像的“質(zhì)量”是很高的。

截取后的圖像只有原圖像的1/5,更利于我們?nèi)ヌ幚頂?shù)據(jù),至此我們的圖像已經(jīng)準備好了。

void ImageUtil::convertNV21ToGrayAndScale( intleft, inttop, intwidth, intheight, introwWidth,

constjbyte *data, int*pixels) {

intp;

intdesIndex = 0;

intbottom = top + height;

intright= left+ width;

intsrcIndex = top * rowWidth;

intmarginRight = rowWidth - right;

for( inti = top; i < bottom; ++i) {

srcIndex += left;

for( intj = left; j < right; ++j, ++desIndex, ++srcIndex) {

p = data[srcIndex] & 0xFF;

pixels[desIndex] = 0xff000000u | p << 16u | p << 8u | p;

}

srcIndex += marginRight;

}

}

1、解析二維碼

有了充足的準備,二維碼的識別已經(jīng)是水到渠成的事情了,根據(jù)轉(zhuǎn)化好的數(shù)據(jù),生成HybridBinarizer對象,通過MultiFormatReader即可解析。

2、識別流程優(yōu)化

在一些Demo中,二維碼處理流程通常是使用setOneShotPreviewCallback作為相機數(shù)據(jù)的處理,即一幀畫面處理完再處理下一幀(兩幀不一定是相連的),這樣的處理會造成兩個問題.

首先:相機獲取的畫面不一定是完全對焦好的,一般我們拿出手機都有一個對焦的動作,中間可能只有50%的畫面是可用的,這種情況下可能會丟失清晰的圖像而處理了模糊的圖像;

其次這種串行的處理也是對機能的浪費,現(xiàn)在的手機處理連續(xù)的圖像是綽綽有余的;

最后,這樣的處理流程是不受我們控制的,只能來一張?zhí)幚硪粡垺?/p>

在流程改進中我使用了setPreviewCallback的回調(diào),并統(tǒng)一加入線程池處理。這里我可以控制一秒之內(nèi)處理多少幀圖像,在測試中是300ms處理一幀(不同機型處理的速度不盡相同,為了避免線程池隊列過長,選擇了較低的處理速度,后期可以根據(jù)機型來動態(tài)設(shè)置處理間隔),為了加速處理,這4幀是識別框內(nèi)的數(shù)據(jù)。

同時,為了能快速識別簡單的二維碼,每4幀處理完之后加入一幀全屏處理,這一幀可以作為識別圖像明亮度的主幀,也可以在二維碼超出識別框時,繼續(xù)識別數(shù)據(jù)。有了這個改動,就可以做到點擊掃一掃,抬手就能得到結(jié)果。

但是這個掃碼的距離實在不能讓人滿意,我們常用的掃一掃通常都會有一個放大的操作,而這個操作是掃碼優(yōu)化中也是非常關(guān)鍵的一步。

3、放大優(yōu)化

想要進一步的優(yōu)化我們就得更進一步的研究二維碼了,二維碼的生成細節(jié)和原理和二維碼(QR code)基本結(jié)構(gòu)及生成原理有詳細的解釋,這里我們發(fā)現(xiàn)左上、左下、右上三個位置探測圖形,在二維碼的解碼過程中,其實是分幾個步驟的,首先就是要定位這個二維碼確認其位置,然后才能取出里面的數(shù)據(jù),而這個定位的點就是這三個。

  • 二維碼的生成細節(jié)和原理 https:///articles/10590.html

  • 二維碼(QR code)基本結(jié)構(gòu)及生成原理 https://blog.csdn.net/u012611878/article/details/53167009

在距離二維碼較遠時,可能無法解析出完整的數(shù)據(jù),但是卻能定位這個二維碼,通過定位點的信息,我們可以進行放大的操作,從而獲取到更加精確的圖像數(shù)據(jù),也更有利于我們解析。

二維碼結(jié)構(gòu)

/**

* 沒有查詢到二維碼結(jié)果,但是能基本能定位到二維碼,根據(jù)返回的數(shù)據(jù)集,檢驗是否要放大

*

* @param result 二維碼定位信息

*/

voidtryZoom(BarcodeReader.Result result){

intlen = 0;

float[] points = result.getPoints;

if(points.length > 3) {

floatpoint1X = points[ 0];

floatpoint1Y = points[ 1];

floatpoint2X = points[ 2];

floatpoint2Y = points[ 3];

floatxLen = Math. abs(point1X - point2X);

floatyLen = Math. abs(point1Y - point2Y);

len = ( int) Math. sqrt(xLen * xLen + yLen * yLen);

}

handleAutoZoom(len);

}

4、與微信的對比

微信的掃一掃可以說是秒級的處理,特別是在iOS的設(shè)備上,更不可思議的是它好像沒有距離的限制。經(jīng)過我們的優(yōu)化之后,我們的二維碼可以在50cm內(nèi)解析出來,但是與微信相差的還是太遠,我們需要更好的處理圖像數(shù)據(jù),來定位二維碼。

6、OpenCV

識別距離

距離 是一個非常關(guān)鍵的制約條件,通常在30cm-40cm內(nèi)是一定可以識別出來的,但是超過這個距離獲取到的圖像就會比較模糊,如果攝像頭的分辨率不高識別率也會下降,如果超過這個閾值,識別算法就只能定位數(shù)據(jù)而無法解析數(shù)據(jù),比如上圖中的B點,這里我們加入自動放大就可以解決,但是超過這個距離呢?

我們就需要手機移動了。如果有一種方案,可以像在B點時一樣,雖然無法獲取到數(shù)據(jù)但是可以得到二維碼的位置、大小呢?要做到這個,OpenCV是一個不二之選。

說到圖像處理,我們大致有兩套方案,

方案一:處理圖像數(shù)據(jù),獲取圖像輪廓,算法檢測二維碼位置。

方案二:機器學習,直接定位二維碼。

兩者其實都是可行的,只是在難易度方面的差異,我們首先嘗試了機器學習的方案,奈何自己學的還比較淺,收集到的樣本數(shù)據(jù)也不夠,訓練出來的模型也不太理想,比如一個沒有二維碼的畫面會檢查出好幾個,又比如有的時候又要離的特別近才能識別出來,這又違背了我們的本意。所以我選擇了方案一,雖然聽起來沒那么高大上了,但是在實際的測試中也完全能達到預(yù)期水平。

當圖像即無法解析出數(shù)據(jù)也無法定位到二維碼時,我們采用OpenCV去處理圖像。因為之前已經(jīng)進行過灰度處理了,這里可以直接進行Canny化,然后執(zhí)行findContours方法獲取輪廓信息,之后過濾輪廓信息,判斷點與點之間的距離,得到二維碼的位置信息。

(以上的過程看似簡單,其實進行了很多嘗試,包括二值化,毛邊去除、調(diào)節(jié)亮度、對比度處理,直接獲取點信息等等,這里感謝

https://blog.csdn.net/jia20003/article/details/77348170

和https://blog.csdn.net/zwx1995zwx/article/details/79171979

的圖像過濾算法,作為一個圖像處理的門外漢真的學到很多)

canny化之后的圖像

定位二維碼輪廓,紅色框框是自動生成的

拿到這些信息之后,我們就可以遵循在B點時的處理邏輯,直接放大圖像獲取數(shù)據(jù)。

你可能會想為什么不直接截取圖像,這樣就不用費時費力再進行一輪識別,其實這里也想到過,但是得到的數(shù)據(jù)精度丟失實在太多,我嘗試用微信去識別截取得到的二維碼,微信也無法檢測出來,這樣的處理對于簡單的二維碼或許可行,但是對于稍微復雜的二維碼或者我們所要解決的問題來說是遠遠不夠的.

7、成果

在加入OpenCV之后,我們的識別距離擴大了一倍,得到的效果比預(yù)期的還要好。

識別效果展示

8、待完善的功能

  1. aar過大,因為有OpenCV的加入,aar文件有7.7M。

  2. 擴展性、可定制性不夠,這個可以慢慢加入。

  3. 有時候會放的太大,試試縮小功能。

注:不同手機識別效率其實不盡相同,攝像頭越好,識別效率越高。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多