这是2017年,我终于开始从Camera1切换到Camera2.在Camera1中,我非常依赖于setPreviewCallbackWithBuffer()执行实时帧处理,但是在Camera2中,它的工作速度要慢得多,几乎无法使用.
相比之下,在Moto G3上Camera1可以很容易地产生30-40 FPS而在Camera2上我的速度不能超过10-15 FPS.
这就是我的创作方式 ImageReader
imageReader = ImageReader
.newInstance(
previewSize.width, // size is around 1280x720
previewSize.height,
ImageFormat.YUV_420_888, // note, it is not JPEG
2 // max number of images, does not really affect performance
);
imageReader.setOnImageAvailableListener(
callback,
CameraThread.getInstance().createHandler()
);
Run Code Online (Sandbox Code Playgroud)
回调本身可以完成最小的工作:
Image image = reader.acquireNextImage();
image.close();
Run Code Online (Sandbox Code Playgroud)
我已经检查了类似的答案,比如这个.然而他们的问题是他们使用的是JPEG图像格式而不是YUV_420_888.
如何实现类似于Camera1的性能?
我在我的git repo中使用了/sf/answers/2810650321/中ImageUtil提供的类:https://github.com/ahasbini/cameraview/tree/camera_preview_imp(注意实现在分支中)到实现帧预览回调.一个被设置为预览在帧格式将被转换成使用类,并将其发送给帧的回调.演示应用程序每50帧将回调帧保存到文件中.所有保存的帧图像都会失真,类似于以下内容:camera_preview_impImageReaderImageFormat.YUV_420_888ImageFormat.JPEGImageUtil
如果我通过执行以下更改而改为ImageReader使用:ImageFormat.JPEGCamera2
mPreviewImageReader = ImageReader.newInstance(previewSize.getWidth(),
previewSize.getHeight(), ImageFormat.JPEG, /* maxImages */ 2);
mCamera.createCaptureSession(Arrays.asList(surface, mPreviewImageReader.getSurface()),
mSessionCallback, null);
Run Code Online (Sandbox Code Playgroud)
图像正常运行而没有任何失真,但帧速率显着下降,视图开始滞后.因此,我认为ImageUtil班级没有正确转换.
通过 camera2 API,我们接收到格式为YUV_420_888的 Image 对象。然后我们使用以下函数转换为NV21:
private static byte[] YUV_420_888toNV21(Image image) {
byte[] nv21;
ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
nv21 = new byte[ySize + uSize + vSize];
//U and V are swapped
yBuffer.get(nv21, 0, ySize);
vBuffer.get(nv21, ySize, vSize);
uBuffer.get(nv21, ySize + vSize, uSize);
return nv21;
}
Run Code Online (Sandbox Code Playgroud)
虽然此函数与 配合良好cameraCaptureSessions.setRepeatingRequest,但在调用 时,我们会在进一步处理(在 JNI 端)中遇到分段错误cameraCaptureSessions.capture。两者都通过 ImageReader 请求 YUV_420_888 …
我正在从事 AR 项目,我需要捕获当前帧并将其保存到图库。我可以使用 AR 核心中的 Frame 类获取图像,但图像格式为 YUV_420_888。我已经尝试了很多解决方案来将其转换为位图,但无法解决。