图像处理 花屏_滴滴开源的 AoE:工程实践中的图像处理
生活随笔
收集整理的這篇文章主要介紹了
图像处理 花屏_滴滴开源的 AoE:工程实践中的图像处理
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
近期,滴滴開源了AOE項目,很多人還是一臉懵逼,不太清楚AOE 到底是干什么的,所以今天我們再來聽聽官方工程師是怎么介紹的吧,不信你還是聽不懂:近期我們開發(fā)了一個銀行卡 OCR 項目。需求是用手機對著銀行卡拍攝以后,通過推理,可以識別出卡片上的卡號。工程開發(fā)過程中,我們發(fā)現(xiàn)手機拍攝以后的圖像,并不能滿足模型的輸入要求。以 Android 為例,從攝像頭獲取到的預(yù)覽圖像是帶 90 度旋轉(zhuǎn)的 NV21 格式的圖片,而我們的模型要求的輸入,只需要卡片區(qū)域這一塊的圖像,并且需要轉(zhuǎn)成固定尺寸的 BGR 格式。所以在圖像輸入到模型之前,我們需要對采集到的圖像做圖像處理,如下圖所示:在開發(fā)的過程中,我們對 YUV 圖像格式和 libyuv 進行了研究,也積累了一些經(jīng)驗。下文我們結(jié)合銀行卡 OCR 項目,講一講里面涉及到的一些基礎(chǔ)知識:
了解了YUV的圖像格式以后,我們就可以嘗試對圖片進行裁剪和旋轉(zhuǎn)了。我們的想法是先在圖片上裁剪出銀行卡的區(qū)域,再進行一次旋轉(zhuǎn)。
●編號757,輸入編號直達本文●輸入m獲取到文章目錄
- 什么是YUV格式
- 如何對YUV圖像進行裁剪
- 如何對YUV圖像進行旋轉(zhuǎn)
- 圖像處理中的Stride
- 如何進行縮放和格式轉(zhuǎn)換
- libyuv的使用
什么是YUV格式
YUV 是一種顏色編碼方法,YUV,分為三個分量:- “Y” 表示明亮度(Luminance或Luma),也就是灰度值;
- “U”和“V” 表示的則是色度(Chrominance或Chroma)。
- 主流的采樣方式有三種,YUV4:4:4,YUV4:2:2,YUV4:2:0。
- YUV420SP,先排列Y分量,UV分量交替排列,例如:NV12: YYYYYYYY UVUV 和 NV21: YYYYYYYY VUVU (上文中我們在安卓上采集到的圖像就是這種格式)。
- YUV420P,先排列U(或者V)分量,再排列V(或者U)分量。例如:I420: YYYYYYYY UU VV 和 YV12: YYYYYYYY VV UU。
如何對YUV圖像進行裁剪
YUV420SP 和 YUV420P 裁剪的過程類似,以 YUV420SP 為例,我們要裁剪圖中的這塊區(qū)域:在圖上看起來就非常明顯了,只要找到裁剪區(qū)域?qū)?yīng)的Y分量和UV分量,按行拷貝到目標(biāo)空間里就可以了。我們再來看一張圖,是否可以用上面的方法來裁剪圖中的這塊區(qū)域呢?答案是否定的,如果你按照上面說的方法來操作,最后你會發(fā)現(xiàn)你保存出來的圖,顏色基本是不對的,甚至?xí)袃?nèi)存錯誤。原因很簡單,仔細觀察一下,當(dāng) ClipLeft 或者 ClipTop 是奇數(shù)的時候,會導(dǎo)致拷貝的時候UV分量錯亂。如果把錯誤的圖像數(shù)據(jù)輸入到模型里面,肯定是得不到我們期望的結(jié)果的。所以我們在做裁剪的時候,需要規(guī)避掉奇數(shù)的場景,否則你會遇到意想不到的結(jié)果。如何對 YUV 圖像進行旋轉(zhuǎn)
對上文裁剪后的圖像做順時針90度旋轉(zhuǎn),相比裁剪,轉(zhuǎn)換要稍微復(fù)雜一些。基本方法是一樣的,拷貝對應(yīng)的 Y 分量和 UV 分量到目標(biāo)空間里。在了解了裁剪和旋轉(zhuǎn)的方法以后,我們發(fā)現(xiàn)在學(xué)習(xí)的過程中不可避免地遇到了 Stride 這個詞。那它在圖像中的作用是什么呢?圖像處理中的Stride
Stride?是非常重要的一個概念,Stride 指在內(nèi)存中每行像素所占的空間,它是一個大于等于圖像寬度的內(nèi)存對齊的長度。如下圖所示:回過頭來看我們上面說到的裁剪和旋轉(zhuǎn),是否有什么問題?以 Android 上的YV12為例,Google Doc 里是這樣描述的:YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed by (W/2) x (H/2) Cr and Cb planes.This format assumes? an even width? an even height? a horizontal stride multiple of 16 pixels? a vertical stride equal to the heighty_size = stride * heightc_stride = ALIGN(stride / 2, 16)c_size = c_stride * height / 2size = y_size + c_size * 2cr_offset = y_sizecb_offize = y_size + c_size
所以在不同的平臺和設(shè)備上,需要按照文檔和 stride 來進行計算。例如計算 Buffer 的大小,很多文章都是簡單的 “*3/2” ,仔細考慮一下,這其實是有問題的。如果不考慮 stride ,會有帶來什么后果?如果 “運氣” 足夠好,一切看起來很正常。“運氣”不夠好,你會發(fā)現(xiàn)很多奇怪的問題,例如花屏,綠條紋,內(nèi)存錯誤等等。這和我們平常工作中遇到的很多的奇怪問題一樣,實際上背后都是有深層次的原因的。經(jīng)過裁剪和旋轉(zhuǎn),我們只需要把圖像縮放成模型需要的尺寸,轉(zhuǎn)成模型需要的BGR格式就可以了。如何進行縮放和格式轉(zhuǎn)換
以縮放為例,有臨近插值,線性插值,立方插值,蘭索斯插值等算法。YUV 和 RGB 之間的轉(zhuǎn)換,轉(zhuǎn)換的公式也有很多種,例如量化和非量化。這些涉及到專業(yè)的知識,需要大量的時間去學(xué)習(xí)和理解。這么多的轉(zhuǎn)換,我們是否都要自己去實現(xiàn)?很多優(yōu)秀的開源項目已經(jīng)提供了完善的 API 給我們調(diào)用,例如 OpenCV,libyuv 等。我們需要做的是理解基本的原理,站在別人的肩膀上,做到心里有數(shù),這樣即使遇到問題,也能很快地定位解決。經(jīng)過調(diào)查和比較,我們選擇了 libyuv 來做圖像處理的庫。libyuv 是 Google 開源的實現(xiàn)各種 YUV 與 RGB 之間相互轉(zhuǎn)換、旋轉(zhuǎn)、縮放的庫。它是跨平臺的,可在 Windows、Linux、Mac、Android 等操作系統(tǒng),x86、x64、arm 架構(gòu)上進行編譯運行,支持 SSE、AVX、NEON等SIMD 指令加速。libyuv的使用
引入libyuv以后,我們只需要調(diào)用libyuv提供的相關(guān)API就可以了。在銀行卡OCR工程使用的過程中,我們主要遇到了2個問題:1,在Android開發(fā)的初期,我們發(fā)現(xiàn)識別率和我們的期望存在一定的差距。我們懷疑是模型的輸入數(shù)據(jù)有問題,通過排查發(fā)現(xiàn)是使用libyuv的時候,沒注意到它是little endian。例如這個方法:int BGRAToARGB(...),BGRA little endian,在內(nèi)存里順序?qū)嶋H是ARGB。所以在使用的時候需要弄清楚你的數(shù)據(jù)在內(nèi)存里是什么順序的,修改這個問題后識別率達到了我們的預(yù)期。2,在大部分機型上運行正常,但在部分機型上出現(xiàn)了 Native 層的內(nèi)存異常。通過多次定位,最后發(fā)現(xiàn)是 stride 和 buffersize 的計算錯誤引起的。由于 libyuv 是 C/C++ 實現(xiàn)的,使用的時候不是那么的便捷。為了提高開發(fā)效率,我們提取了一個 AoeVision 組件,對libyuv封裝了一層 JNI 接口,包括了一些基礎(chǔ)的轉(zhuǎn)換和一些 Sample,這樣使用起來更加簡單方便,AoeVision組件還在不斷開發(fā)和完善中。最后附上Github地址:https://github.com/didi/aoe。歡迎大家使用和提意見●編號757,輸入編號直達本文●輸入m獲取到文章目錄
總結(jié)
以上是生活随笔為你收集整理的图像处理 花屏_滴滴开源的 AoE:工程实践中的图像处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python bind_Python b
- 下一篇: springboot banner在线生