Camera2 人脸识别
需要使用的API介绍
因为Camera2提供的功能更加强大,所以使用比Camera1会复杂许多.需要调用的API和回调也更多.这里简单介绍一下这些API的对应功能.好初步认识Camera2.
CameraManager
摄像头管理类:
主要有4个功能:
- 获取摄像头的ID
- 获取摄像头的特征信息(比如摄像头前后位置信息和支持的分辨率信息等等)
- 打开指定id的摄像头
- 打开和关闭闪光灯
CameraDevice
摄像头设备类:
主要功能有3个
- 创建获取数据请求类CaptureRequest.Builder(或者叫捕获请求),下面会介绍这个类
- 创建获取数据会话(创建预览或者拍照的会话通道)
- 关闭摄像头
CameraDevice.StateCallback
摄像头状态接口回调类:
主要是负责回调摄像头的开启/断开/异常/销毁.我们使用CameraManager打开指定id的摄像头时需要添加这个回调.
CameraCaptureSession.StateCallback
获取数据会话的状态接口回调类:
我们创建相机预览图像/拍照/录像都需要这个回调类,来告诉我们获取数据会话的通道状态是配置成功或者配置失败.它还负责给我们回调一个重要的CameraCaptureSession提供给我们操作,这个CameraCaptureSession类我下面会介绍
CameraCaptureSession.CaptureCallback
获取数据会话的数据接口回调类:
负责回调获取数据的生命周期(比如开始/进行中/完成/失败等等),如果你并不需要对生命周期里做操作,所以有时候没有啥作用.但是它也是必需创建的一个回调接口类,是在创建预览图像/拍照/录像的时候添加进去,但是拍照或者录像的数据都不在这个回调接口里出来(一开始很容易误解,以为拍照数据会从这里返回).除了回调获取数据的生命周期,还可以在回调方法里获取拍照或者录制过程的的一些参数信息,比如图片的Size/分辨率等等.
CaptureRequest.Builder
获取数据请求配置类:
很重要,也是我们频繁操作的一个配置类.由CameraDevice类创建.主要负责
- 设置返回数据的surface(显示预览View比如TextureView的surface 或者 照片ImageReader的surface)
- 配置预览/拍照/录制的拍照参数,比如自动对焦/自动曝光/拍照自动闪光/设置HZ值/颜色校正等等你能在系统相机上看到的功能.
数据配置完成后交给CameraCaptureSession会话类,让CameraCaptureSession操作提供我们需要的数据,例如图像预览或者拍照/录制视频
CameraCaptureSession
获取数据会话类:
很重要,是我们频繁操作的一个数据会话类,比如创建预览/停止预览/拍照/录像都要它来操作,它由CameraCaptureSession.StateCallback这个接口回调方法里回调提供给我们.
ImageReader
图片读取类:
不属于Camera2Api的类,但是是拍照功能重要的类,照片的数据流由它缓存,然后我们提取保存到本地成为图片文件或者显示在ImageView里
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);//
3.预览更新和不更新也会影响黑色和白色
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE,
CameraMetadata.FLASH_MODE_SINGLE);
1。开启闪光灯,mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE,
CameraMetadata.FLASH_MODE_SINGLE);
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);//自动闪光灯
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);//
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);//
有预览,但是黑
不注释:有些没有预览,会白
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
CONTROL_AE_MODE_ON_ALWAYS_FLASH | 同上,只是相机设备还控制闪光灯,拍照时总是闪光 | |
int | CONTROL_AE_MODE_ON_AUTO_FLASH | 同上,只是相机设备控制闪光灯在低光条件下开启 |
mCaptureRequestBuilder.set(CaptureRequest.FLASH_MODE,
CaptureRequest.FLASH_MODE_TORCH);
为了解释上面的示意图,假设我们想要同时拍摄两张不同尺寸的图片,并且在拍摄的过程中闪光灯必须亮起来。整个拍摄流程如下:
- 创建一个用于从 Pipeline 获取图片的 CaptureRequest。
- 修改 CaptureRequest 的闪光灯配置,让闪光灯在拍照过程中亮起来。
- 创建两个不同尺寸的 Surface 用于接收图片数据,并且将它们添加到 CaptureRequest 中。
- 发送配置好的 CaptureRequest 到 Pipeline 中等待它返回拍照结果。
Capture
Capture 从执行方式上又被细分为【单次模式】、【多次模式】和【重复模式】三种,我们来一一解释下:
- 单次模式(One-shot):指的是只执行一次的 Capture 操作,例如设置闪光灯模式、对焦模式和拍一张照片等。多个一次性模式的 Capture 会进入队列按顺序执行。
- 多次模式(Burst):指的是连续多次执行指定的 Capture 操作,该模式和多次执行单次模式的最大区别是连续多次 Capture 期间不允许插入其他任何 Capture 操作,例如连续拍摄 100 张照片,在拍摄这 100 张照片期间任何新的 Capture 请求都会排队等待,直到拍完 100 张照片。多组多次模式的 Capture 会进入队列按顺序执行。
- 重复模式(Repeating):指的是不断重复执行指定的 Capture 操作,当有其他模式的 Capture 提交时会暂停该模式,转而执行其他被模式的 Capture,当其他模式的 Capture 执行完毕后又会自动恢复继续执行该模式的 Capture,例如显示预览画面就是不断 Capture 获取每一帧画面。该模式的 Capture 是全局唯一的,也就是新提交的重复模式 Capture 会覆盖旧的重复模式 Capture。
相机的所有操作和参数配置最终都是服务于图像捕获,例如对焦是为了让某一个区域的图像更加清晰,调节曝光补偿是为了调节图像的亮度。因此,在 Camera2 里面所有的相机操作和参数配置都被抽象成 Capture(捕获)
9 CaptureRequest
CaptureRequest 是向 CameraCaptureSession 提交 Capture 请求时的信息载体,其内部包括了本次 Capture 的参数配置和接收图像数据的 Surface。CaptureRequest 可以配置的信息非常多,包括图像格式、图像分辨率、传感器控制、闪光灯控制、3A 控制等等,可以说绝大部分的相机参数都是通过 CaptureRequest 配置的。值得注意的是每一个 CaptureRequest 表示一帧画面的操作,这意味着你可以精确控制每一帧的 Capture 操作。
在暗环境下拍照的时候,如果能够适当延长曝光时间,就可以让图像画面的亮度得到提高。在 Camera2 上,你可以在规定的曝光时长范围内配置拍照的曝光时间,从而实现拍摄长曝光图片,你甚至可以延长每一帧预览画面的曝光时间让整个预览画面在暗环境下也能保证一定的亮度。而在 Camera1 上你只能 YY 一下。
解决方案:
使用android.hardware.camera2打造新的自定义相机
创建一个新的相机预览的参数设置
//获取ISO范围
Range<Integer> range1 = characteristics.get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
//获取快门范围
Range<Long> range2 = characteristics.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
//获取帧间隔范围
Long max3 = characteristics.get(CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION);
int max1 = range1.getUpper();//华为P9最大值为3500
int min1 = range1.getLower();//华为P9最小值为100
Long max2 = range2.getUpper()/10 ;//华为P9最大值1s
Long min2 = range2.getLower()/200 ;//华为p9最小值100ns
int iso = ((Progress[0] * (max1 - min1)) / 100 + min1);
Long exposure = ((Progress[1] * (max2 - min2)) / 100 + min2);
Long frame = max3 / 1000;
//以下分别为ISO,快门,帧间隔
mPreviewBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, iso);
mPreviewBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, exposure);
mPreviewBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, frame);
//设置自动曝光帧率范围previewBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,getRange());