国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
一款媲美微信二維碼的識(shí)別庫(kù),這個(gè)得知道啊

1、為什么要做這個(gè)庫(kù)?

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

有了這樣的『標(biāo)桿』存在,大家在潛意識(shí)里面也都有了標(biāo)準(zhǔn),你們的掃一掃為什么不好用?為什么要識(shí)別這么久?甚至我對(duì)準(zhǔn)了也識(shí)別不出來(lái)?擺在我們面前的是各種用戶的不滿,解決這些問(wèn)題就成了我們必須要面對(duì)的情形。

2、選型

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

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

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

3、相機(jī)的處理

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

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

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

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

1、格式轉(zhuǎn)換

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

YUV420

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

https://zh.wikipedia.org/wiki/YUV

YUV的組成

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

YUV->RGB

2、算法優(yōu)化

對(duì)于二維碼來(lái)說(shuō),它是一個(gè)個(gè)黑白的點(diǎn)組成的,其實(shí)并不需要多么色彩斑斕的裝飾,一張灰度圖或許是更好的選擇,一般的圖像處理,都是輪詢所有像素?cái)?shù)據(jù),對(duì)于一個(gè)或者一組數(shù)據(jù)進(jìn)行處理。一個(gè)YUV轉(zhuǎn)化為RGB的算法就是要拿出所有像素,然后各種轉(zhuǎn)換,這無(wú)疑是一種浪費(fèi)。一個(gè)更好的選擇是把原圖像直接轉(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、圖片裁剪

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

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

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

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

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、解析二維碼

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

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

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

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

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

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

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

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

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

3、放大優(yōu)化

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

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

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

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

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

/**

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

*

* @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、與微信的對(duì)比

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

6、OpenCV

識(shí)別距離

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

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

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

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

方案二:機(jī)器學(xué)習(xí),直接定位二維碼。

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

當(dāng)圖像即無(wú)法解析出數(shù)據(jù)也無(wú)法定位到二維碼時(shí),我們采用OpenCV去處理圖像。因?yàn)橹耙呀?jīng)進(jìn)行過(guò)灰度處理了,這里可以直接進(jìn)行Canny化,然后執(zhí)行findContours方法獲取輪廓信息,之后過(guò)濾輪廓信息,判斷點(diǎn)與點(diǎn)之間的距離,得到二維碼的位置信息。

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

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

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

的圖像過(guò)濾算法,作為一個(gè)圖像處理的門外漢真的學(xué)到很多)

canny化之后的圖像

定位二維碼輪廓,紅色框框是自動(dòng)生成的

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

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

7、成果

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

識(shí)別效果展示

8、待完善的功能

  1. aar過(guò)大,因?yàn)橛蠴penCV的加入,aar文件有7.7M。

  2. 擴(kuò)展性、可定制性不夠,這個(gè)可以慢慢加入。

  3. 有時(shí)候會(huì)放的太大,試試縮小功能。

注:不同手機(jī)識(shí)別效率其實(shí)不盡相同,攝像頭越好,識(shí)別效率越高。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
二維碼識(shí)別技術(shù)的原理和識(shí)別
二維最大熵閾值分割
三種笛卡爾坐標(biāo)到極坐標(biāo)轉(zhuǎn)換插值算法比較
【學(xué)術(shù)論文】圖像去模糊系統(tǒng)頻域優(yōu)化設(shè)計(jì)
數(shù)字圖像處理基本知識(shí)
圖像去霧算法(二)基于暗通道先驗(yàn)算法學(xué)習(xí)筆記
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服