Android相机2 API - 实时显示处理后的帧

3
我正在尝试创建一个应用程序,实时处理相机图像并在屏幕上显示它们。我正在使用camera2 API。我已经创建了一个本地库,使用OpenCV处理这些图像。
到目前为止,我已经成功设置了一个ImageReader来接收YUV_420_888格式的图像,就像这样。
        mImageReader = ImageReader.newInstance(
                mPreviewSize.getWidth(),
                mPreviewSize.getHeight(),
                ImageFormat.YUV_420_888,
                4);
        mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mImageReaderHandler);

从那里,我能够获取图像平面(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();

在本地端,我能够从缓冲区获取数据指针,从数据创建一个cv::Mat并进行图像处理。现在下一步是展示处理后的输出,但我不确定如何展示处理后的图像。非常感谢任何帮助。

可能是实时处理Android相机帧的重复问题。 - ZdaR
2个回答

6

一般而言,您需要将处理过的图像数据发送到 Android 视图。

最高效的选项是获取一个 android.view.Surface 对象进行绘制 - 您可以通过 SurfaceView(通过 SurfaceHolder)或 TextureView(通过 SurfaceTexture)获取它。然后,您可以通过 JNI 将该 Surface 传递到本机代码,并在那里使用 NDK 方法:

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

一般来说,你应该坚持使用RGBA_8888作为最兼容的格式;在技术上,只有它和其他两种RGB变体得到了官方支持。因此,如果您处理的图像是YUV,则需要先转换为RGBA格式。
您还需要确保输出视图的宽高比与您设置的尺寸相匹配;默认情况下,Android的View会将这些内部缓冲区缩放到输出View的大小,可能会在此过程中拉伸它。
您也可以将格式设置为Android的内部YUV格式之一,但这并不保证能够正常工作!

0

我尝试过使用ANativeWindow方法,但是设置起来很麻烦,而且我没有成功地完成它。最终,我放弃了,并导入了OpenCV4Android库,该库通过在后台将相机数据转换为RGBA Mat来简化事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接