雙SurfaceView實現手機攝像頭預覽、監聽每一幀做處理繪製浮層效果(Demo畫了一個矩形上去)

應用場景

當時用手機攝像頭做實時預覽時、需要對視頻中的圖像做人臉檢測、繪製一些效果到人臉上等。。。

實現思路

1.自定義 CameraView extends SurfaceView 做攝像頭預覽。
2.自定義 FloatingLayerView extends SurfaceView 做上層圖標繪製。
3.自定義 DoubleSurfaceView extends FrameLayout 整合上兩個View、開啓相機、監聽幀數據。

關鍵點:

因爲是要使用兩個SurfaceView重疊在一起實現最終效果、所以處於上層的SurfaceView必須是背景透明的。
使用下面設置來實現:

setZOrderOnTop(true);// 設置層級處於頂層
getHolder().setFormat(PixelFormat.TRANSPARENT);// 設置背景透明

另外一個做攝像頭預覽的CameraView 不需要做設置。

技術點:

開啓攝像頭技術需要使用到的API

靜態方法
- Camera.getNumberOfCameras(); // 獲取攝像頭數量
- Camera.getCameraInfo(camIdx, cameraInfo); // 獲取對應ID的攝像頭信息
- Camera.open(camIdx); // 開啓對應ID的攝像頭
- Camera.CameraInfo.CAMERA_FACING_BACK // 後攝像頭
- Camera.CameraInfo.CAMERA_FACING_FRONT // 前攝像頭

非靜態
- mCamera.setDisplayOrientation(result); // 設置攝像頭旋轉角度
- mCamera.getParameters(); // 獲取當前攝像頭參數信息

示例:

// 根據展示區域設置攝像頭預覽寬高
Camera.Parameters params = mCamera.getParameters();
params.setPreviewSize(width, height);
// 開啓前置攝像頭
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
    Camera.getCameraInfo(camIdx, cameraInfo);
    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        try {
            camera = Camera.open(camIdx);
            break;
        } catch (RuntimeException e) {

        }
    }
}
    // int rotation = activity.getWindowManager ().getDefaultDisplay ().getRotation ();
    // 根據屏幕旋轉方向--旋轉攝像頭
    public void setCameraDisplayOrientation(int rotation, int cameraId, Camera camera) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int degrees = 0;
        switch (rotation) { // 根據屏幕旋轉方向記錄需要旋轉的角度
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { // 前置攝像頭計算方式
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {// 後置攝像頭計算方式
            // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

SurfaceView預覽攝像頭

獲取實時的數據幀

// 設置監聽(開啓預覽前設置)
mCamera.setPreviewCallback(new Camera.PreviewCallback(){
    @Override
    public void onPreviewFrame(byte[] bytes, Camera camera) {
        Log.i(TAG, "onPreviewFrame =  " + bytes.length);
        // 此處獲取每一幀的數據 bytes
    }
});
mCamera.setPreviewDisplay(surfaceView.getHolder());// 開啓實現預覽

在預覽圖像上繪製浮層

獲取到每一幀的數據、做對應處理(例如:人臉檢測)、此處不要直接在onPreviewFrame()回調中處理,換一個線程

浮層也是使用SurfaceView

只需要設置兩個屬性就可以了

setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSPARENT);
完整Demo代碼:https://download.csdn.net/download/xuanzhiqiang01/10567542
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章