具有OpenCV面部检测的OpenGL字节缓冲区

时间:2015-10-27 12:59:16

标签: android opencv opengl-es glsurfaceview

我正在尝试使用OpenCV和OpenGL在脸上叠加贴纸。

我在onDrawFrame中获取了ByteBuffer:

@Override
    public void onDrawFrame(GL10 unused) {
        if (VERBOSE) {
            Log.d(TAG, "onDrawFrame tex=" + mTextureId);
        }

        mSurfaceTexture.updateTexImage();
        mSurfaceTexture.getTransformMatrix(mSTMatrix);

        byteBuffer.rewind();
        GLES20.glReadPixels(0, 0, mWidth, mHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuffer);
        mat.put(0, 0, byteBuffer.array());

        if (mCascadeClassifier != null) {
            mFaces.empty();
            mCascadeClassifier.detectMultiScale(mat, mFaces);
            Log.d(TAG, "No. of faces detected : " + mFaces.toArray().length);
        }

        drawFrame(mTextureId, mSTMatrix);
}

我的mat对象初始化为相机预览宽度和高度:

mat = new Mat(height, width, CvType.CV_8UC3);

日志返回0面部检测。我有两个问题:

  1. 我在这里使用OpenCV进行面部检测时缺少什么?
  2. 另外,如何提高视频帧渲染的性能/效率并进行实时人脸检测?因为 glReadPixels 需要时间来执行并减慢渲染速度。

1 个答案:

答案 0 :(得分:2)

在您渲染任何内容之前,您正在GLES帧缓冲区上调用drawFrame()。如果您希望回读SurfaceTexture渲染,则需要在glReadPixels()之后执行此操作。您可能需要考虑将屏幕外的纹理渲染为pbuffer EGLSurface,然后从中回读。

有几种不同的方法可以从相机获取像素数据:

  1. 使用Camera byte [] API。通常涉及软件副本,因此往往很慢。
  2. 将输出发送到ImageReader。这使您可以立即访问原始YUV数据。
  3. 将输出发送到SurfaceTexture,渲染纹理,使用 <local:UC Test="{Binding SelectedString, Mode=OneWay}"/> 读取RGB数据(我相信您正在尝试这样做)。这通常非常快,但在某些设备和Android版本上,它可能会很慢。