Opencv For Android: 如何顯示攝像頭預覽
阿新 • • 發佈:2019-02-01
它是在 CameraBridgeBase 這個類裡有一個 方法,
deliverAndDrawFrame(CvCameraViewFrame ),
在這個函式裡面,
它將CvCameraViewListener2 的onCameraFrame 返回的Mat 轉換為 bitmap ,
然後通過canvas畫在 surfaceView 持有holder的 surface上。
注意,onCameraFrame是我們要具體去實現的介面, 而且也是我們處理影象主要戰場
而我們也可以通過繼承 deliverAndDrawFrame 這個方法來 通過opengl 載入bitmap紋理,顯示影象到 opengl es繫結的surface上,。
深入一點, deliverAndDrawFrame 的引數 CvCameraViewFrame 怎麼來的?
如果玩過 Android 攝像頭的人都知道, 在initializeCamera 就是 開啟攝像頭和設定攝像頭的地方,
顯示攝像頭也有兩種方式:
1 通過 setPreviewDisplay(SurfaceHolder holder)
這種,一般與 SurfaceView搭配, 通過SurfaceView.getHolder()
2 通過 setPreviewTexture(SurfaceTexture surfaceTexture)
這種,一般與 OpenGL的 Surface搭配,根據 我的 另一篇部落格,
SurfaceView通過 Holder 可以得到Surface,而在Native層,通過ANativeWindow_fromSurface來獲得本地的window視窗,
然後,通過於該window獲取EGLDisplay連線,進而建立EGLSurface及EGLContext,
這樣就與Opengl關聯起來
而SurfaceTexture 是綁定了一個Texture, 因此,攝像頭通過 EGLSurface將,資料寫到Surface上,即這個Texture的buffer裡面,
Opengl 通過其draw方法,顯示出影象預覽來。
Camera的 PreviewCallback介面 :
PreviewCallback在 攝像頭預覽顯示每一幀到Surface上時,會通過Copy一份,通過介面
public void onPreviewFrame(byte[] frame)來獲得
其中, frame就是我們獲取的影象資料, 在記憶體中按位元組連續存放。獲取的預覽影象格式是yuv。
OpenCV 的mat矩陣:
Mat類能夠接收 byte[]陣列,
在initializeCamera的 方法裡面, 建立了兩個Mat矩陣,
mFrameChain[0], mFrameChain[1]
這兩個Mat矩陣的目的是, 交替存放 PreviewCallback回掉回來的byte[] yuv資料。
CvCameraViewFrame:
是一個 Interface,裡面提供了 轉rgba, 和 gray的介面, 在繼承的實現的子類裡,JavaCameraFrame 接受了三個引數: Mat, width, height 其中, Mat接受, mFrameChain[0]或者mFrameChain[1] 而通過 JavaCameraFrame的 rgba, 和 gray可以將yuv 轉換為rgb或者灰度影象。 與 我們實現演算法的戰場 onCameraFrame的關係: 上一步轉換過來的 rgb或者灰度影象 傳給 onCameraFrame,onCameraFrame處理後 給deiverAndDrawFrame 顯示 如果用opengl ,如何實現,效能有哪些提高的猜想: 在獲取資料方面: opengl es: 通過SurfaceTexture拿到 texture紋理 opencv: 通過 onPreviewCallback 拿到 byte[] 以上, gl是 16ms以內, onPreviewCallback需要30ms以上 在演算法處理上: 都在native層實現 opengl: 在shader可以並行處理,每一點畫素,就像PC端cuda一樣。如果處理 opencv: Mat矩陣 需要兩個for迴圈 但是演算法上,opencv 大大優於 opengl的實現 opengl 實現會很複雜,具體問題具體以後再分析,這裡只是稍微提下
是一個 Interface,裡面提供了 轉rgba, 和 gray的介面, 在繼承的實現的子類裡,JavaCameraFrame 接受了三個引數: Mat, width, height 其中, Mat接受, mFrameChain[0]或者mFrameChain[1] 而通過 JavaCameraFrame的 rgba, 和 gray可以將yuv 轉換為rgb或者灰度影象。 與 我們實現演算法的戰場 onCameraFrame的關係: 上一步轉換過來的 rgb或者灰度影象 傳給 onCameraFrame,onCameraFrame處理後 給deiverAndDrawFrame 顯示 如果用opengl ,如何實現,效能有哪些提高的猜想: 在獲取資料方面: opengl es: 通過SurfaceTexture拿到 texture紋理 opencv: 通過 onPreviewCallback 拿到 byte[] 以上, gl是 16ms以內, onPreviewCallback需要30ms以上 在演算法處理上: 都在native層實現 opengl: 在shader可以並行處理,每一點畫素,就像PC端cuda一樣。如果處理 opencv: Mat矩陣 需要兩個for迴圈 但是演算法上,opencv 大大優於 opengl的實現 opengl 實現會很複雜,具體問題具體以後再分析,這裡只是稍微提下