Android使用Camera2获取预览数据
一、Camera2简介Camera2是Google在Android 5.0后推出的一个全新的相机API,Camera2和Camera没有继承关系,是完全重新设计的,且Camera2支持的功能也更加丰富,但是提供了更丰富的功能的同时也增加了使用的难度。Google的官方Demo:https://github.com/googlesamp... 二、Camera2 VS Camera以下分别是使用Camera2和Camera打开相机进行预览并获取预览数据的流程图。 可以看到,和Camera相比,Camera2的调用明显复杂得多,但同时也提供了更强大的功能: 支持在非UI线程获取预览数据可以获取更多的预览帧对相机的控制更加完备支持更多格式的预览数据支持高速连拍但是具体能否使用还要看设备的厂商有无实现。 三、如何使用Camera2获取预览数据一般情况下,大多设备其实只支持ImageFormat.YUV_420_888和ImageFormat.JPEG格式的预览数据,而ImageFormat.JPEG是压缩格式,一般适用于拍照的场景,而不适合直接用于算法检测,因此我们一般取ImageFormat.YUV_420_888作为我们获取预览数据的格式,对于YUV不太了解的同学可以戳这里。 mImageReader = ImageReader.newInstance(mPreviewSize.getWidth(), mPreviewSize.getHeight(), ImageFormat.YUV_420_888, 2);mImageReader.setOnImageAvailableListener( new OnImageAvailableListenerImpl(), mBackgroundHandler);其中OnImageAvailableListenerImpl的实现如下 private class OnImageAvailableListenerImpl implements ImageReader.OnImageAvailableListener { private byte[] y; private byte[] u; private byte[] v; private ReentrantLock lock = new ReentrantLock(); @Override public void onImageAvailable(ImageReader reader) { Image image = reader.acquireNextImage(); // Y:U:V == 4:2:2 if (camera2Listener != null && image.getFormat() == ImageFormat.YUV_420_888) { Image.Plane[] planes = image.getPlanes(); // 加锁确保y、u、v来源于同一个Image lock.lock(); // 重复使用同一批byte数组,减少gc频率 if (y == null) { y = new byte[planes[0].getBuffer().limit() - planes[0].getBuffer().position()]; u = new byte[planes[1].getBuffer().limit() - planes[1].getBuffer().position()]; v = new byte[planes[2].getBuffer().limit() - planes[2].getBuffer().position()]; } if (image.getPlanes()[0].getBuffer().remaining() == y.length) { planes[0].getBuffer().get(y); planes[1].getBuffer().get(u); planes[2].getBuffer().get(v); camera2Listener.onPreview(y, u, v, mPreviewSize, planes[0].getRowStride()); } lock.unlock(); } image.close(); }}注意事项. 图像格式问题经过在多台设备上测试,明明设置的预览数据格式是ImageFormat.YUV_420_888(4个Y对应一组UV,即平均1个像素占1.5个byte,12位),但是拿到的数据却都是YUV_422格式(2个Y对应一组UV,即平均1个像素占2个byte,16位),且U和V的长度都少了一些(在Oneplus 5和Samsung Tab s3上长度都少了1),也就是: ...