Android camera2 API-实时显示处理过的帧

Mat*_*nik 3 c++ android opencv native camera2

我正在尝试创建一个实时处理相机图像并将其显示在屏幕上的应用程序。我正在使用camera2 API。我创建了一个本地库来使用OpenCV处理图像。

到目前为止,我已经设法设置了一个ImageReader来接收类似YUV_420_888格式的图像。

        mImageReader = ImageReader.newInstance(
                mPreviewSize.getWidth(),
                mPreviewSize.getHeight(),
                ImageFormat.YUV_420_888,
                4);
        mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mImageReaderHandler);
Run Code Online (Sandbox Code Playgroud)

从那里,我可以获取图像平面(Y,U和V),获取它们的ByteBuffer对象,并将它们传递给我的本机函数。这发生在mOnImageAvailableListener

        Image image = reader.acquireLatestImage();

        Image.Plane[] planes = image.getPlanes();
        Image.Plane YPlane = planes[0];
        Image.Plane UPlane = planes[1];
        Image.Plane VPlane = planes[2];

        ByteBuffer YPlaneBuffer = YPlane.getBuffer();
        ByteBuffer UPlaneBuffer = UPlane.getBuffer();
        ByteBuffer VPlaneBuffer = VPlane.getBuffer();

        myNativeMethod(YPlaneBuffer, UPlaneBuffer, VPlaneBuffer, w, h);

        image.close();
Run Code Online (Sandbox Code Playgroud)

在本机端,我能够从缓冲区中获取数据指针,cv::Mat从数据中创建a 并执行图像处理。

现在,下一步将是显示经过处理的输出,但是我不确定如何显示经过处理的图像。任何帮助将不胜感激。

Edd*_*ala 5

一般来说,您需要将处理后的图像数据发送到Android视图。

性能最高的选项是获取要绘制的android.view.Surface对象-您可以从SurfaceView(通过SurfaceHolder)或TextureView(通过SurfaceTexture)中获得一个。然后,您可以将该Surface通过JNI传递到您的本机代码,然后在其中使用NDK方法:

使用setBuffersGeometry()配置输出大小,然后使用lock()获取ANativeWindow_Buffer。将图像数据写入ANativeWindow_Buffer.bits,然后使用unlockAndPost()发送缓冲区。

通常,您应该坚持使用RGBA_8888作为最兼容的格式。从技术上讲,仅正式支持它和另外两个RGB变体。因此,如果处理后的图像位于YUV中,则需要先将其转换为RGBA。

您还需要确保输出视图的长宽比与您设置的尺寸匹配。默认情况下,Android的View只会将这些内部缓冲区缩放到输出View的大小,可能会在此过程中对其进行拉伸。

您也可以将格式设置为Android内部的YUV格式之一,但这不能保证正常工作!