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());