您的位置:首页 > 移动开发 > Android开发

Opencv For Android: 如何显示摄像头预览

2015-11-09 22:07 603 查看
它是在 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 实现会很复杂,具体问题具体以后再分析,这里只是稍微提下
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: