Android Camera2 获取预览数据

一、Camera2简介

Camera2是Google在Android 5.0后推出的一个全新的相机API,Camera2和Camera没有继承关系,是完全重新设计的,且Camera2支持的功能也更加丰富,但是提供了更丰富的功能的同时也增加了使用的难度。Google的官方Demo:

https://github.com/googlesamples/android-Camera2Basic

二、Camera2预览流程

Camera2 API使用流程如下

三、使用Camera2获取预览数据

1.获取预览数据

一般情况下,大多设备其实只支持ImageFormat.YUV_420_888ImageFormat.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) {
            runOnSubThread(new Runnable() {
                @Override
                public void run() {
                    Image image = reader.acquireNextImage();
                    // Y:U:V == 4:2:2
                    if (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);
							//2.处理数据
                            byte[] nv21 = new byte[planes[0].getRowStride() * mPreviewSize.getHeight() * 3 / 2];
                            yuv422ToYuv420sp(y, u, v, nv21, planes[0].getRowStride(), mPreviewSize.getHeight());
                        }
                        lock.unlock();
                    }
                    image.close();
                }
            });
        }
    }
2.将YUV_420_888的数据转化成nv21
复制代码
	/**
     * 将Y:U:V == 4:2:2的数据转换为nv21
     *
     * @param y      Y 数据
     * @param u      U 数据
     * @param v      V 数据
     * @param nv21   生成的nv21,需要预先分配内存
     * @param stride 步长
     * @param height 图像高度
     */
    public void yuv422ToYuv420sp(byte[] y, byte[] u, byte[] v, byte[] nv21, int stride, int height) {
        System.arraycopy(y, 0, nv21, 0, y.length);
        // 注意,若length值为 y.length * 3 / 2 会有数组越界的风险,需使用真实数据长度计算
        int length = y.length + u.length / 2 + v.length / 2;
        int uIndex = 0, vIndex = 0;
        for (int i = stride * height; i < length; i += 2) {
            nv21[i] = v[vIndex];
            nv21[i + 1] = u[uIndex];
            vIndex += 2;
            uIndex += 2;
        }
        List<FacePreviewInfo> facePreviewInfos = HrHelper.getInstance().onPreviewFrame(nv21, true);
        HrHelper.getInstance().clearLeftFace(facePreviewInfos);
    }

四、参考

进击的丸子

Android Camera2入门系列2 - ImageReader获得预览数据

相关推荐
我命由我1234513 小时前
Android 开发 - 一些画板第三方库(DrawBoard、FingerPaintView、PaletteLib)
android·java·java-ee·android studio·安卓·android-studio·android runtime
程序员的世界你不懂13 小时前
【Flask】测试平台开发,工具模块开发 第二十二篇
android·python·flask
Digitally16 小时前
如何在安卓手机/平板上找到下载文件?
android·智能手机·电脑
硬件学长森哥19 小时前
Android影像基础--cameraAPI2核心流程
android·计算机视觉
前行的小黑炭1 天前
Android 协程的使用:结合一个环境噪音检查功能的例子来玩玩
android·java·kotlin
阿华的代码王国1 天前
【Android】内外部存储的读写
android·内外存储的读写
inmK11 天前
蓝奏云官方版不好用?蓝云最后一版实测:轻量化 + 不限速(避更新坑) 蓝云、蓝奏云第三方安卓版、蓝云最后一版、蓝奏云无广告管理工具、安卓网盘轻量化 APP
android·工具·网盘工具
giaoho1 天前
Android 热点开发的相关api总结
android
咖啡の猫1 天前
Android开发-常用布局
android·gitee
程序员老刘1 天前
Google突然“变脸“,2026年要给全球开发者上“紧箍咒“?
android·flutter·客户端