Camera2开发:CameraDevice类

2023-12-22 08:18
文章标签 开发 camera2 cameradevice

本文主要是介绍Camera2开发:CameraDevice类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



0x00 说明

该文章为本人个人学习的总结,如果遗漏或错误欢迎在评论区批评指出or补充。如对您有帮助可以细看之,如希望直接查看本人的学习资料来源,可直接跳到 0x05 相关资料 一节查看。

0x01 概览

CameraDevice是连接在安卓设备上的单个相机的抽象表示, CameraDevice 支持在高帧率下对捕获的图像进行细粒度控制和后期处理.

在Camera2 API中,一个相机设备可能支持的硬件等级有以下几种(按每个等级所支持的功能来排序):

LEVEL_3> FULL > LIMIT > LEGACY

按照 Google文档 的说法,一般手机的相机可能会支持 FULL 或 LIMIT ,当一个设备支持到 LIMIT ,此时尽管 Camera2 API 具有更整洁和高效的接口,然而其只暴露出和旧的Camera API 功能相当的API,与使用旧的API无异。

而支持到 FULL 等级的设备,则提供了比旧的 Camera API 大大改进的功能,比如支持 30fps全高清连拍,支持帧之间的手动设置,支持RAW格式的图片拍摄,快门零延迟以及视频速拍等特性。 只有在支持 FULL 级别的设备上才能完全发挥 Camera2的特性。然而经过实测中发现,目前市面上大多安卓手机都只支持到最低级别 LEGACY (估计是为了兼容android L 以下的系统?)......也就是说在这样的手机上使用Camera API和Camera2 API并没有太大区别,甚至Camera API的发挥可能还要好一些。不过,尽管如此,还是推荐使用 Camera2 API ,毕竟旧的 Camera API 已经被打上 deprecated 标签,指不定在未来哪个android的版本中Camera API就被移除了。相机设备所支持的硬件等级是由硬件厂商决定的,可以通过以下 CameraCharacteristics 类获取机子上的相机所支持的硬件等级参数:

CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
int hardwareLevel=characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);

其中 manager 为 CameraManager 实例,关于 CameraManager 在上篇文章 Camera2开发(1) --CameraManager类 中有介绍。 hardwareLevel==1 为 FULL , hardwareLevel==2 为 LEGACY , hardwareLevel==0 为 LIMIT , hardwareLevel==3 为 LEVEL_3 。

0x02 内部类

StateCallback

该类用于接收相机的连接状态的更新。这些状态包括一系列的通知如 相机启动结束(此时允许调用 CameraDevice.createCaptureSession(List, CameraCaptureSession.StateCallback, Handler) 创建一个捕获会话), 相机断开连接或关闭 以及相机 出现异常错误 等。

在调用 CameraDevice.openCamera(String,CameraDevice.StateCallback,Handler)方法打开相机时必须传入一个 CameraDevice.StateCallback 实例,以用于接收相机状态的更新和后续的处理。

典型的 CameraDevice.StateCallback 的声明和使用如下:

private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback()
{@Overridepublic void onOpened(@NonNull CameraDevice camera){//当相机打开成功之后会回调此方法//一般在此进行获取一个全局的CameraDevice实例,开启相机预览等操作mCameraDevice = camera;//获取CameraDevice实例createCameraPreviewSession();//创建相机预览会话} @Overridepublic void onDisconnected(@NonNull CameraDevice camera){//相机设备失去连接(不能继续使用)时回调此方法,同时当打开相机失败时也会调用此方法而不会调用onOpened()//可在此关闭相机,清除CameraDevice引用camera.close();mCameraDevice = null;}@Overridepublic void onError(@NonNull CameraDevice camera, int error){//相机发生错误时调用此方法camera.close();mCameraDevice = null;}@Overridepublic void onClosed(CameraDevice camera){//相机完全关闭时回调此方法super.onClosed(camera);}
};

其中 onError(@NonNull CameraDevice camera, int error) 中的 error 参数代表出错的代码,可参考 Google文档上的错误代码说明。

0x03 常量

int TEMPLATE_MANUAL

Constant Value: 6 (0x00000006)

用于创建一个 直接控制相机拍照参数 的 CaptureRequest 请求。使用该模板创建的请求,相机的所有自动控制都会被禁用(例如自动曝光,自动白平衡,自动对焦等),并将后期处理参数设置成预览质量。手动控制的参数(曝光,感光度等)将被设置成合理的默认值,用户需要根据自己想要的预期效果来调整这些参数。

兼容性: TEMPLATE_MANUAL 在支持 MANUAL_SENSOR 功能的设备上可用。

int TEMPLATE_PREVIEW

Constant Value: 1 (0x00000001)

用于创建一个 相机预览 请求。通常情况下,设置了该模板的预览画面,相机会优先保证预览的帧率。该模板适用于相机画面预览,通常将该模板结合 setRepeatingRequest(CaptureRequest, CameraCaptureSession.CaptureCallback, Handler) 创建一个预览请求。

兼容性: TEMPLATE_PREVIEW 在所有相机设备上均适用。

int TEMPLATE_RECORD

Constant Value: 3 (0x00000003)

用于创建 录制视频 的请求。使用该模板创建的请求将使用标准帧率,并且后期处理效果的质量将被设置成录像级别。

兼容性: TEMPLATE_RECORD 可在所有的相机设备上使用.。

int TEMPLATE_STILL_CAPTURE

Constant Value: 2 (0x00000002)

用于创建一个 拍照 请求。使用该模板创建的请求会优先保证图像的质量,以获得最好的拍照效果。

兼容性:可在所有的相机设备上使用。

int TEMPLATE_VIDEO_SNAPSHOT

Constant Value: 4 (0x00000004)

用于创建 录像时拍照 请求。使用该模板创建的请求可以最大化地保证照片的质量同时不会破坏正在录制的视频质量。该模板创建的请求通常与 CameraCaptureSession.capture(CaptureRequest request, CameraCaptureSession.CaptureCallback callback, Handler handler) 结合使用,其中这里的 request 必须是基于 TEMPLATE_RECORD 模板创建。

兼容性:硬件支持级别高于 LEGACY 的所有相机设备可用。

int TEMPLATE_ZERO_SHUTTER_LAG

Constant Value: 5 (0x00000005)

用于创建 零延迟拍照 请求。使用该模板创建的请求将最大化地保证图片质量并且不会损失预览图像的帧率。此时自动对焦/自动白平衡和自动曝光都应处于 auto 模式。

兼容性:该模板仅在支持 PRIVATE_PEPROCESSING 或 YUV_PEPROCESSING 特性的相机设备上适用。

0x04 常用的方法

close()

尽可能快地关闭当前相机设备的连接。

调用该方法之后,所有调用处于激活状态的 session 和 CameraDevice 其方法的操作都将抛出一个 IllegalStateException 异常。当相机完全关闭后, CameraDevice.StateCallback.onClosed(CameraDevice) 方法会被调用,此时相机就绪以等待下一次被打开。

createCaptureRequest(int templateType)

创建一个用于构建capture request的CaptureRequest.Builder实例,并用templateType模板初始化该实例。

该设置会为当前指定的 CameraDevice 适配最佳的选项,因此创建的 CaptureRequest 不建议重用到其他的 CameraDevice 以免出错。

参数说明:
  • templateType:参考 0x03 常量 一节。

createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)

通过提供给相机设备的目标输出surface集合创建一个新的相机捕获会话(CameraCaptureSession)实例。

当前活动的 capture session 决定了相机的每一个 capture request 的输出 surface (每个 capture request 的输出 surface 都是 outputs 的一个子集)。比如当我需要将捕获数据输出到预览 surface ,则需要将预览 surface 添加到 outputs 作为createCaptureSession 的参数。

在实际使用中可根据不同的用例和输出目标来构建 surface 用于接收相机输出的图像数据,这里只列出拍照功能可能用到的几个,有关录像的以后再补充:

  • 绘制到一个SurfaceView:

    使用 SurfaceView 来显示预览画面时,应在 SurfaceView 的 Surface 创建成功后先通过 SurfaceHolder 设置其大小,再获取 Surface 实例,如果不设置,则相机会自动为其设置一个小于且最接近 1080p 的可用预览尺寸:

SurfaceView mSurfaceView = (SurfaceView)findViewById(R.id.surfaceview);
SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//获取所有可用的预览尺寸
Size[] sizes=map.getOutputSizes(SurfaceHolder.class);
Size mPreviewSize=sizes[bestSizeIndex];
//设置surface尺寸
mSurfaceHolder.setFixedSize(mPreviewSize.getWidth(),mPreviewSize.getHeight());
//获取预览的surface
Surface surface=mSurfaceHolder.getSurface();
  • 通过SurfaceTexture来访问OpenGL texture:

    使用 TextureView 来显示预览,要确保手机的硬件加速开启才能进行。

    在创建 Surface 之前,需要先设置 SurfaceTexture 的大小,如果不设置,则相机会自动为其设置一个小于且最接近 1080p 的可用预览尺寸:

//获取SurfaceTexture
SurfaceTexture texture = mTextureView.getSurfaceTexture();
//获取所有可用预览尺寸
Size[] sizes=map.getOutputSizes(SurfactTexture.class);
Size mPreviewSize=sizes[bestSizeIndex];
//设置SurfaceTexture大小
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
//获取预览的surface
Surface surface = new Surface(texture);
  • 结合MediaCodec进行录像: 待补充
  • 结合MediaRecorder进行录像: 待补充
  • 结合android.renderscript进行高效的YUV处理: 待补充
  • 在程序中访问RAW格式或未压缩的YUV或者压缩的JPEG格式的图像数据: 
    可创建一个 ImageReader 对象,通过 ImageReader 的 Surface 来接收相机图像并保存图像数据:
//************************
//**1.创建ImageReader对象**
//************************
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//获取指定格式的所有支持尺寸
Size[] sizes=map.getOutputSizes(ImageFormat.JPEG);
//计算期望的最佳尺寸,至于怎么计算则看具体需求。如果该ImageReader的大小没有在程序中设置,
//则当前相机设备将自动为该ImageReader设置一个支持的小于1080p的尺寸。
Size largestSize = Collections.max(Arrays.asList(sizes), new CompareSizesByArea());
//创建ImageReader
ImageReader mImageReader = ImageReader.newInstance(largestSize.getWidth(), largestSize.getHeight(), ImageFormat.JPEG,/*maxImages*/2);//...其他操作/** 
* 摘自Google Sample:Camera2Basic
* Compares two {@code Size}s based on their areas. 
*/
static class CompareSizesByArea implements Comparator<Size>{@Overridepublic int compare(Size lhs, Size rhs){//We cast here to ensure the multiplications won't overflowreturn Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());}
}//...其他操作//************************
//**2.设置ImageReader.OnImageAvailableListener监听**
//************************
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener()
{@Overridepublic void onImageAvailable(ImageReader reader){//在这里调用(reader.acquireNextImage()获取图像数据mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));}
};//...其他操作mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);//************************
//**3.随后可通过ImageReader.getSurface()方法获取Surface**
//************************
Surface surface=mImageReader.getSurface();
参数说明:
  • outputs 
    所有可用于捕获相机输出数据的 surface 集合。
  • callback 
    CameraCaptureSession.StateCallback实例,调用 CameraDevice.createCaptureSession 后会回调 callback 中相应的方法,可在该回调中处理创建 session 成功或失败之后的进一步操作。
  • handler 
    指定处理该操作的 handler

getId()

获取当前相机设备的id


来自http://www.qingpingshan.com/rjbc/az/




这篇关于Camera2开发:CameraDevice类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/523225

相关文章

Python通过模块化开发优化代码的技巧分享

《Python通过模块化开发优化代码的技巧分享》模块化开发就是把代码拆成一个个“零件”,该封装封装,该拆分拆分,下面小编就来和大家简单聊聊python如何用模块化开发进行代码优化吧... 目录什么是模块化开发如何拆分代码改进版:拆分成模块让模块更强大:使用 __init__.py你一定会遇到的问题模www.

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并

基于Python开发PDF转PNG的可视化工具

《基于Python开发PDF转PNG的可视化工具》在数字文档处理领域,PDF到图像格式的转换是常见需求,本文介绍如何利用Python的PyMuPDF库和Tkinter框架开发一个带图形界面的PDF转P... 目录一、引言二、功能特性三、技术架构1. 技术栈组成2. 系统架构javascript设计3.效果图

基于Python开发PDF转Doc格式小程序

《基于Python开发PDF转Doc格式小程序》这篇文章主要为大家详细介绍了如何基于Python开发PDF转Doc格式小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用python实现PDF转Doc格式小程序以下是一个使用Python实现PDF转DOC格式的GUI程序,采用T