相机

调用系统相机

添加权限

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Android 6.0 以上版本,还需处理动态权限

public class PhotoTools {

    public static final int REQUEST_CODE_TAKE_PICTURE = 10001;

    public static Uri takePicture(Activity activity,File file){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        Uri imgUri = null;

        // 7.0以上版本,必须使用FileProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            String authority = activity.getPackageName()+".fileprovider";
            imgUri = FileProvider.getUriForFile(activity, authority, file);
        } else {
            imgUri = Uri.fromFile(file);
        }
        // 设置拍照后保存的路径
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
        // 设置图片保存的格式
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        activity.startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE);

        return imgUri;
    }
}

拍照

File dir = new File(Environment.getExternalStorageDirectory(),"Pictures");
if (!dir.exists()) dir.mkdir();
File image = new File(dir,System.currentTimeMillis()+".jpg");
if (!image.exists()){
    try {
        image.createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Log.d("PhotoTools",image.getAbsolutePath());
PhotoTools.takePicture(MainActivity.this,image);

拍照是否成功

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PhotoTools.REQUEST_CODE_TAKE_PICTURE) {
        Log.d("PhotoTools","onActivityResult "+resultCode);
        if (resultCode == RESULT_OK) {
            Toast.makeText(this, "照片已保存", Toast.LENGTH_LONG).show();
        }
    }
}

关于系统相机的调用,具体可查看官方文档 拍照

注意,在API 24以上版本,不能直接使用file://型的URI,需使用FileProvider机制,具体参见 设置文件共享

FileProvider 配置文件filepaths.xml的标签:

标签 对应路径
<files-path> context.getFilesDir()
<cache-path> context.getCacheDir()
<external-path> Environment.getExternalStorageDirectory()
<external-files-path> context.getExternalFilesDir()
<external-cache-path> context.getExternalCacheDir()
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external-path" path="Pictures"/>
</paths>

上例中配置的路径,即为Environment.getExternalStorageDirectory()+"/Pictures"

调用相机API

  • CameraManager:主要用于管理系统摄像头

  • CameraDevice:用于代表一个摄像头。摄像头功能可被分为limit 和full 两个级别,当摄像头处于limited 级别时候,此时Camera2和早期的Camera功能相差不多。

    其主要承担的任务:

    • 通过CameraDevice.StateCallback监听摄像头的状态(主要包括onOpenedonClosedonDisconnectedonErro四种状态)
    • 通过方法createCaptureSession方法创建会话
  • CameraCharacteristics:描述CameraDevice属性的对象,内部携带大量的相机信息,包含摄像头的正反等

  • CaptureRequest:代表一次捕获请求,包含传感器,镜头,闪光灯等。

  • CaptureRequest.Builder:用于CaptureRequest对象的构造。

  • CameraCaptureSession:请求抓取相机图像帧的会话,主要会建立起一个通道。一个CameraDevice一次只能开启一个会话。 源端是摄像头,另一端是可以是Preview,也可以是ImageReader。需要注意,创建会话是一项耗时的异步操作,可能需要几百毫秒

  • ImageReader:用于从相机打开的通道中读取需要的格式的原始图像数据,可以设置多个ImageReader。

2020071308045442

预览示例:

public class CameraActivity extends Activity implements EasyPermissions.PermissionCallbacks{

    private CameraManager mCameraManager;
    private String mCameraId;
    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    private Handler mHandler;

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSurfaceView = findViewById(R.id.preview_view);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                initCamera();
            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder holder) {

            }
        });

        try {
            mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
            /**
             * 查询本机的摄像头情况,此操作无需权限
             */

            //遍历设备支持摄像头ID ,比如前置,后置等
            String[] cameraIdList = mCameraManager.getCameraIdList();
            for (String cameraId : cameraIdList) {
                Log.d("CameraActivity", "cameraId:" + cameraId);
                CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
                //拿到摄像头的朝向:前置,后置,或者外部的
                Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);

                if (facing != null) {
                        //后置摄像头
                    if (facing == CameraCharacteristics.LENS_FACING_BACK) {
                        mCameraId = cameraId;
                    } else if (facing == CameraCharacteristics.LENS_FACING_FRONT) {
                        //前置摄像头
                    }
                }

                //是否支持 Camera2 的高级特性
                Integer level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
                /**
                 * 不支持 Camera2 的特性
                 */
                if (level == null || level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
                    Toast.makeText(this, "该手机不支持Camera2的高级特性", Toast.LENGTH_SHORT).show();
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void initCamera() {
        HandlerThread handlerThread = new HandlerThread("Camera2");
        handlerThread.start();
        mHandler = new Handler(handlerThread.getLooper());
        openCamera();
    }

    @SuppressLint("MissingPermission")
    private void openCamera() {
        try {
            if (EasyPermissions.hasPermissions(CameraActivity.this, Manifest.permission.CAMERA)) {
                Log.d("CameraActivity", "hasPermissions:permission.CAMERA");
                mCameraManager.openCamera(mCameraId, new CameraDeviceCallback(), null);
            } else {
                EasyPermissions.requestPermissions(CameraActivity.this, "该测试需要相机权限", 1, Manifest.permission.CAMERA);
            }
        } catch (CameraAccessException e) {
            Log.e("CameraActivity", "open camera failed." + e.getMessage());
        }
    }

    private void createCameraCaptureSession(CameraDevice device) throws CameraAccessException {
        final CaptureRequest.Builder requestBuilder =
                device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        // 添加surface容器,用于预览显示
        requestBuilder.addTarget(mSurfaceHolder.getSurface());

        device.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface()),
                new CameraCaptureSession.StateCallback() {
                    // 会话开始处理捕获请求
                    @Override
                    public void onConfigured(CameraCaptureSession session) {
                        try {
                            //设置自动聚焦
                            requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                            //设置自动曝光
                            requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                            // 请求不断重复捕获图像,以此来实现预览
                            session.setRepeatingRequest(requestBuilder.build(), null, mHandler);
                        } catch (CameraAccessException e) {
                            Log.e("CameraActivity", "set preview builder failed." + e.getMessage());
                        }
                    }

                    @Override
                    public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                        Toast.makeText(CameraActivity.this, "配置失败", Toast.LENGTH_SHORT).show();
                    }
                }, mHandler);
    }

    class CameraDeviceCallback extends CameraDevice.StateCallback{

        //此时摄像头已打开,可以预览了
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            try {
                createCameraCaptureSession(camera);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        // 摄像头关闭
        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            camera.close();
        }

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            camera.close();
        }
    }

    // 动态权限处理。这里调用第三方库EasyPermissions来处理
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    // 授权成功
    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
        openCamera();
    }

    // 授权失败
    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
        /**
       * 若是在权限弹窗中,用户选择拒绝权限。并且勾选了'不在提示'
       * 这时候,需要跳转到设置界面去,让用户手动开启权限
       */
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            new AppSettingsDialog.Builder(this).build().show();
        }
    }
}

相机预览的基本步骤:

  1. 获取相机设备信息(CameraManager
  2. 创建用于预览的显示区域(SurfaceViewTextureView
  3. 打开相机(openCamera,6.0以上版本需检查动态权限)
  4. 创建Capture会话(createCaptureSession
  5. 创建CaptureRequest,并设置条件
  6. 开始预览(setRepeatingRequest
  7. 关闭相机

增加拍照处理的逻辑

// 拍照
private void takePicture() {
    if (mCameraDevice == null) return;
    // 创建拍照需要的CaptureRequest
    final CaptureRequest.Builder captureBuilder;
    try {
        captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        // 将imageReader的surface作为CaptureRequest.Builder的目标
        captureBuilder.addTarget(mImageReader.getSurface());
        // 自动聚焦、曝光
        captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
        captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

        // 根据设备方向计算设置照片的方向
        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getDisplayRotation());
        // 先停止预览
        mCameraCaptureSession.stopRepeating();

        //拍照
        CaptureRequest request = captureBuilder.build();
        mCameraCaptureSession.capture(request, null, mHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private int getDisplayRotation(){
    // 获取手机方向
    int rotation = getWindowManager().getDefaultDisplay().getRotation();
    switch (rotation){
        case Surface.ROTATION_0:
            rotation = 0;
            break;
        case Surface.ROTATION_90:
            rotation = 90;
            break;
        case Surface.ROTATION_180:
            rotation = 180;
            break;
        case Surface.ROTATION_270:
            rotation = 270;
            break;
    }
    return (mSensorOrientation - rotation + 360) % 360;
}

// 保存照片
private void saveImage(File file){
    FileOutputStream fos = null;
    Image image = null;
    try {
        fos = new FileOutputStream(file);
        //获取捕获的照片数据
        image = mImageReader.acquireLatestImage();
        //拿到所有的 Plane 数组
        Image.Plane[] planes = image.getPlanes();
        //由于是 JPEG ,数组只有一个元素
        ByteBuffer buffer = planes[0].getBuffer();
        byte[] data = new byte[buffer.remaining()];
        buffer.get(data);
        Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
        bitmap.compress(Bitmap.CompressFormat.JPEG,100,fos);
        fos.flush();
    }catch (Exception e){
        Log.e("CameraActivity", ""+e.toString());
    }finally {
        if (fos != null){
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (image != null) {
            image.close();
        }
    }
}

修改之前预览的代码

initCamera方法中增加ImageReader的创建

private void initCamera() {
    mHandlerThread = new HandlerThread("Camera2");
    mHandlerThread.start();
    mHandler = new Handler(mHandlerThread.getLooper());
    mImageReader = ImageReader.newInstance(mSurfaceView.getWidth(), mSurfaceView.getHeight(),
                                           ImageFormat.JPEG, 2);
    // 当有图像数据生成时,回调OnImageAvailableListener的onImageAvailable方法
    mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {

        @Override
        public void onImageAvailable(ImageReader reader) {
            File file = new File(Environment.getExternalStorageDirectory(), "take.jpg");
            Log.d("CameraActivity", file.getAbsolutePath());
            saveImage(file);
        }
    }, mHandler);
    openCamera();
}

此外需注意,在createCameraCaptureSession方法中,增加mImageReader.getSurface()

device.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(),mImageReader.getSurface()),

在查询摄像头信息时,增加摄像头方向的查询代码

mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

拍照时,有一个问题需要特别注意,即设置照片的方向。当我们使用 TextureView 或者 SurfaceView 进行画面预览时,系统会根据设备自然方向、摄像头方向和显示方向自动矫正预览画面的方向,但该矫正规则只适用于显示方向和和设备自然方向一致的情况。而当我们拍照时,则需要手动去处理照片方向的问题。

1519399-0b800d9d95f0e5bd

9551499-8660a7db6b17bff8

由于手机摄像头的方向和手机自然方向是不同的,通常相差90度,因此我们拍出的照片就需要进行旋转矫正。总结规律,我们可以归纳出一个计算公式

后置摄像头:

矫正角度 = (摄像头方向 - 手机方向 + 360) % 360

前置摄像头:

矫正角度 = (360 - (摄像头方向 + 手机方向) % 360) % 360

我们在拍照时停止了预览,可以设置监听器,在完成后重新开启预览

mCameraCaptureSession.capture(request, new CameraCaptureSession.CaptureCallback() {
                    @Override
                    public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                        super.onCaptureCompleted(session, request, result);
                        try {
                            //拍完之后,继续预览
                            CaptureRequest.Builder request1 = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                            request1.addTarget(mSurfaceHolder.getSurface());
                            mCameraCaptureSession.setRepeatingRequest(request1.build(),null,mHandler);
                        } catch (CameraAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }, mHandler);

最后,还有一个问题需要来探讨一下,即预览、拍照的最佳尺寸选择。

当摄像头获取的图像宽高比与预览区域的宽高比不一致时,画面会变形

1519399-42e60cb3981eda6d

解决这种变形问题,无外乎两种方式,一种是让预览区域的TextureView的宽高比和摄像头采集的画面宽高比保持一致,这就要重新调整TextureView的宽高,调用TextureViewsetDefaultBufferSize方法设置;另一种则是修改画面绘制在 TextureView 上的方式,类似于剪裁,调用TextureViewsetTransform()。(注意,SurfaceView没有这些方法,只能通过布局调整它的宽高)

摄像头采集的画面会包含多组宽高尺寸,这里我们先选出最佳尺寸

// 获取预览最佳尺寸
// 注意surface的宽高和获取的Size的宽高是反过来的
private Size getBestPreviewSize(CameraCharacteristics characteristics,int surfaceWidth, int surfaceHeight) {
    Size bestSize = null;
    // 获取摄像头支持的所有输出尺寸
    StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
    Size[] sizeArray = map.getOutputSizes(SurfaceHolder.class);
    for (Size size : sizeArray) {
        Log.d("CameraActivity", "Size: " + size.getWidth()+" - "+size.getHeight());
        // 寻找宽高比相等的尺寸
        if ((size.getWidth() * surfaceWidth/surfaceHeight) == size.getHeight()) {
            bestSize = size;
            break;
        }
    }

    if (bestSize == null){
        // 寻找宽高差值最小的尺寸
        int diffs = Integer.MAX_VALUE;
        for (Size s : sizeArray) {
            int newDiffs = Math.abs(s.getHeight() - surfaceWidth) + Math.abs(s.getWidth() - surfaceHeight);
            if (newDiffs <= diffs) {
                bestSize = s;
                diffs = newDiffs;
            }
        }
    }
    return bestSize;
}

// 然后调用setDefaultBufferSize,设置上述方法返回的Size
// Size bestSize = getBestPreviewSize()
 textureView.setDefaultBufferSize(bestSize.getWidth(), bestSize.getHeight());

关于拍照的尺寸,我们可以选择最大分辨率,以获取最佳质量

// 设置图片尺寸,选择最大的分辨率即可
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] sizes = map.getOutputSizes(ImageFormat.JPEG);
// 自定义一个比较器,选出sizes数组的最大值
Size largest = Collections.max(Arrays.asList(sizes),new CompareSizesByArea());
//设置ImageReader
mImageReader = ImageReader.newInstance(largest.getWidth(),largest.getHeight(),
                                       ImageFormat.JPEG,1);

class CompareSizesByArea implements Comparator<Size> {
    @Override
    public int compare(Size lhs, Size rhs) {
        // 比较Size对象的大小,这里以面积大小来比较
        return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
    }
}

相机相关参数

  • createCaptureRequest:该方法需要传入一个模版类型,六种类型如下
    • TEMPLATE_PREVIEW : 配置预览的模板
    • TEMPLATE_STILL_CAPTURE: 用于拍照的模板,图像质量优先于帧速率
    • TEMPLATE_RECORD : 用于视频录制的模板
    • TEMPLATE_VIDEO_SNAPSHOT: 用于视频录制时截图的模板
    • TEMPLATE_ZERO_SHUTTER_LAG : 用于零快门延迟的请求。(在不影响预览帧率的情况下最大化图像质量)
    • TEMPLATE_MANUAL : 手动配置参数的模板,请求中所有的自动控制都是禁用的(自动曝光,自动白平衡、自动焦点)
  • CameraCharacteristics.get():获取相机的各种参数
  • CaptureRequest.Builder.set():设置指定的参数

CameraCharacteristics 常用的Key值属性:

  • CameraCharacteristics.LENS_FACING : 获取摄像头方向。前置摄像头(LENS_FACING_FRONT)、后置摄像头(LENS_FACING_BACK)或外置摄像头(LENS_FACING_EXTERNAL
  • CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL: 获取当前设备支持的相机特性
  • CameraCharacteristics.SENSOR_ORIENTATION: 获取摄像头方向
  • CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP: 获取 StreamConfigurationMap,它是管理摄像头支持的所有输出格式和尺寸
  • CameraCharacteristics.FLASH_INFO_AVAILABLE: 是否支持闪光灯
  • CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT: 同时检测到人脸的数量
  • CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES: 相机支持的人脸检测模式

CaptureRequest 常用设置的属性字段

  • 自动对焦 requestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTUR)
  • 闪光灯 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
  • 拍照时对照片进行旋转 requestBuilder.set(CaptureRequest.JPEG_ORIENTATION, mCameraSensorOrientation)
  • 人脸检测模式 requestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE,CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_SIMPLE)

这里还需要注意,CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL属性用于查询硬件层面支持的Camera2功能的等级,主要分为五个等级:

  • INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY

    向后兼容模式, 基本没有额外功能,相当于Camera API接口

  • INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED

    除了基本的功能, 还支持一些额外的高级功能, 这些高级功能是LEVEL_FULL的子集

  • INFO_SUPPORTED_HARDWARE_LEVEL_FULL

    支持对每一帧数据进行控制,还支持高速率的图片拍摄

  • INFO_SUPPORTED_HARDWARE_LEVEL_3

    支持YUV后处理和Raw格式图片拍摄, 还支持额外的输出流配置

  • INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL

    API28中加入,对应的是外接摄像头,功能类似LIMITED等级

支持的功能多少排序为:LEGACY < LIMITED < FULL < LEVEL_3

更多属性,可查看官方文档 CameraCharacteristics 或者查看以下附录内容

相机API的使用,可参考Google的2个Java写的Demo工程

附录:

CameraCharacteristics 属性

返回值 字段名 解释
int[] COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES 异常校正模式
int[] CONTROL_AE_AVAILABLE_ANTIBANDING_MODES 自动曝光反带模式列表
int[] CONTROL_AE_AVAILABLE_MODES 在自动曝光模式列表
Range CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES 帧速率范围表
Rational CONTROL_AE_COMPENSATION_STEP 最小的一步,可以改变曝光补偿。
int[] CONTROL_AF_AVAILABLE_MODES 自动对焦(AF)列表
int[] CONTROL_AVAILABLE_EFFECTS 色彩效果列表
int[] CONTROL_AVAILABLE_MODES 控制模式列表
int[] CONTROL_AVAILABLE_SCENE_MODES 场景列表模式
int[] CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES 视频稳定模式列表
int[] CONTROL_AWB_AVAILABLE_MODES 白平衡模式列表
Boolean CONTROL_AWB_LOCK_AVAILABLE 相机设备支持MANUAL_POST_PROCESSING或BURST_CAPTURE则为true
Integer CONTROL_MAX_REGIONS_AE 自动曝光(AE)例程可使用的最大计量区域数。
Integer CONTROL_MAX_REGIONS_AF 自动对焦(AF)例程可使用的最大计量区域数。
Integer CONTROL_MAX_REGIONS_AWB 自动白平衡(AWB)例程可使用的最大计量区域数。
Range CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE 范围的增加
Boolean DEPTH_DEPTH_IS_EXCLUSIVE 表示捕获请求是否可以同时针对DEPTH16/depthpointcloud输出,以及正常的颜色输出(例如yuv420888、JPEG或RAW)。
int[] EDGE_AVAILABLE_EDGE_MODES 边缘增强模式列表
Boolean FLASH_INFO_AVAILABLE 相机是否有闪光灯单元
int[] HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES 热像素校正模式列表
Integer INFO_SUPPORTED_HARDWARE_LEVEL 相机设备功能的整体分类
Size[] JPEG_AVAILABLE_THUMBNAIL_SIZES JPEG缩略图的列表
Integer LENS_FACING 摄像机相对于设备屏幕的方向
float[] LENS_INFO_AVAILABLE_APERTURES 孔径尺寸值表
float[] LENS_INFO_AVAILABLE_FILTER_DENSITIES 中性密度滤波器值表
float[] LENS_INFO_AVAILABLE_FOCAL_LENGTHS 焦距列表
int[] LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION 光学图像稳定(OIS)模式列表
Integer LENS_INFO_FOCUS_DISTANCE_CALIBRATION 镜头聚焦距离校准质量。
Float LENS_INFO_HYPERFOCAL_DISTANCE 这个镜头的超焦距。
Float LENS_INFO_MINIMUM_FOCUS_DISTANCE 在镜头前的最短距离,可以把焦点集中在镜头的最前面。
float[] LENS_INTRINSIC_CALIBRATION 该相机设备的固有校正参数。
float[] LENS_POSE_ROTATION 传感器坐标系统的方向。
float[] LENS_POSE_TRANSLATION 照相机光学中心的位置。
float[] LENS_RADIAL_DISTORTION 修正了该相机装置的径向和切向透镜畸变的校正系数。
int[] NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES 噪声抑制方式表
Integer REPROCESS_MAX_CAPTURE_STALL 通过重新处理捕获请求引入的最大摄相机捕获管道(在帧数单元中)。
int[] REQUEST_AVAILABLE_CAPABILITIES 这个相机设备所宣传的功能是完全支持的。
Integer REQUEST_MAX_NUM_INPUT_STREAMS 任何类型的输入流的最大数量,可以同时被摄像机设备配置和使用。
Integer REQUEST_MAX_NUM_OUTPUT_PROC 不同类型的输出流的最大数量,可以同时配置和使用一个摄像机设备来处理任何处理的(但不是停滞的)格式。
Integer REQUEST_MAX_NUM_OUTPUT_PROC_STALLING 可以对任意处理(和停止)格式的摄像机设备同时配置和使用的不同类型的输出流的最大数量。
Integer REQUEST_MAX_NUM_OUTPUT_RAW 不同类型的输出流的最大数量,可以同时配置和使用任何原始格式的摄像机设备。
Integer REQUEST_PARTIAL_RESULT_COUNT 定义一个结果将由多少子组件组成。
Byte REQUEST_PIPELINE_MAX_DEPTH 指定一个框架必须经历的最大管道阶段的数量,当它暴露在框架下的时候。
Float SCALER_AVAILABLE_MAX_DIGITAL_ZOOM 活动区域宽度和作物区域宽度、活动区高度和作物区高度之间的最大比率,
Integer SCALER_CROPPING_TYPE 这个相机设备所支持的裁剪类型。
StreamConfigurationMap SCALER_STREAM_CONFIGURATION_MAP 这个相机设备支持的可用的流配置;还包括最小帧持续时间和每个格式/大小组合的停顿时间。
int[] SENSOR_AVAILABLE_TEST_PATTERN_MODES 传感器测试模式模式列表
BlackLevelPattern SENSOR_BLACK_LEVEL_PATTERN 每一种颜色过滤装置(CFA)马赛克通道都有固定的黑色电平。
ColorSpaceTransform SENSOR_CALIBRATION_TRANSFORM1 每个设备的校准转换矩阵,从参考传感器的色彩空间映射到实际的设备传感器的色彩空间。
ColorSpaceTransform SENSOR_CALIBRATION_TRANSFORM2 每个设备的校准转换矩阵,从参考传感器的色彩空间映射到实际的设备传感器的色彩空间(这是原始缓冲区数据的色彩空间)。
ColorSpaceTransform SENSOR_COLOR_TRANSFORM1 一个矩阵,它将颜色值从CIE XYZ颜色空间转换为参考传感器颜色空间。
ColorSpaceTransform SENSOR_COLOR_TRANSFORM2 一个矩阵,它将颜色值从CIE XYZ颜色空间转换为参考传感器颜色空间。
ColorSpaceTransform SENSOR_FORWARD_MATRIX1 一个矩阵,它将白色平衡摄像机的颜色从参考传感器的色彩空间转换为带有D50白色点的CIE XYZ颜色空间。
ColorSpaceTransform SENSOR_FORWARD_MATRIX2 一个矩阵,它将白色平衡摄像机的颜色从参考传感器的色彩空间转换为带有D50白色点的CIE XYZ颜色空间。
Size SENSOR_INFO_PIXEL_ARRAY_SIZE 全像素数组的尺寸,可能包括黑色校准像素
Rect SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE 在应用任何几何畸变校正之前,图像传感器的区域与活动的像素相对应。
Range SENSOR_INFO_SENSITIVITY_RANGE 敏感的范围
Integer SENSOR_INFO_TIMESTAMP_SOURCE 传感器捕获的时间基准源开始时间戳。
Integer SENSOR_INFO_WHITE_LEVEL 传感器的最大原始值输出。
Integer SENSOR_MAX_ANALOG_SENSITIVITY 最大灵敏度是通过模拟增益实现的。
Integer SENSOR_OPTICAL_BLACK_REGIONS 显示传感器光学屏蔽黑色像素区域的分离矩形的列表。
Rect[] SENSOR_OPTICAL_BLACK_REGIONS 显示传感器光学屏蔽黑色像素区域的分离矩形的列表。
Integer SENSOR_ORIENTATION 顺时针方向的角度,在设备屏幕上,输出图像需要旋转以保持在本机定位上。
Integer SENSOR_REFERENCE_ILLUMINANT1 标准参考光源用作场景光源
Byte SENSOR_REFERENCE_ILLUMINANT2
int[] SHADING_AVAILABLE_MODES 透镜阴影模式列表
int[] STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES 人脸检测方式
boolean[] STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES 热像素映射输出模式列表
int[] STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES 镜头阴影贴图输出模式列表
Integer STATISTICS_INFO_MAX_FACE_COUNT 同时可检测到的人脸的最大数量。
Integer SYNC_MAX_LATENCY 提交请求后(不同于之前的)的最大帧数被提交,并且在结果的状态变为同步之前。
int[] TONEMAP_AVAILABLE_TONE_MAP_MODES tonemapping列表模式
Integer TONEMAP_MAX_CURVE_POINTS

CaptureRequest 和 CaptureResult 属性

返回值 字段名 解释
Boolean BLACK_LEVEL_LOCK 黑等级的补偿是否被锁定在当前的值上,或者是自由的变化。
Integer COLOR_CORRECTION_ABERRATION_MODE 色差
RggbChannelVector COLOR_CORRECTION_GAINS 获得白平衡Bayer的raw color频道
Integer COLOR_CORRECTION_MODE 模式控制选择如何将图像数据从传感器的本机颜色转换为线性sRGB颜色。
ColorSpaceTransform COLOR_CORRECTION_TRANSFORM 一种颜色变换矩阵,用于从传感器RGB颜色空间转换为输出线性sRGB色彩空间
Integer CONTROL_AE_ANTIBANDING_MODE 相机设备的自动曝光算法的反带补偿的理想设置。
Integer CONTROL_AE_EXPOSURE_COMPENSATION 调整自动曝光(AE)目标图像亮度。
Integer CONTROL_AE_LOCK 是否自动曝光(AE)目前被锁定在最新的计算值上。
Integer CONTROL_AE_MODE 相机设备的自动曝光程序所需的模式。
Integer CONTROL_AE_PRECAPTURE_TRIGGER 当它处理这个请求时,摄像机设备是否会触发一个预捕获的测量序列。
MeteringRectangle[] CONTROL_AE_REGIONS 用于自动曝光调整的计量区域表。
Boolean CONTROL_AWB_LOCK 自动白平衡(AWB)是否被锁定在最新的计算值上。
Integer CONTROL_AWB_MODE 自动白平衡(AWB)是否正在设置颜色转换字段,以及它的照明目标是什么。
MeteringRectangle[] CONTROL_AWB_REGIONS 用于自动平衡光源估计的计量区域的列表。
Integer CONTROL_CAPTURE_INTENT 信息到相机设备3A(自动曝光,自动对焦,自动平衡)例程,以帮助相机设备决定最优的3A策略。
Integer CONTROL_EFFECT_MODE 一种特殊的颜色效果。
Boolean CONTROL_ENABLE_ZSL 允许相机设备为android.control.captureIntent == STILL_CAPTURE 的请求启用零树/延迟模式
Integer CONTROL_MODE 3A的整体模式(自动曝光,自动平衡,自动对焦)控制例程。
Integer CONTROL_POST_RAW_SENSITIVITY_BOOST 在获取原始传感器数据后,应用于输出图像的额外灵敏度增加。
Integer CONTROL_SCENE_MODE 控制哪个场景模式当前是活跃的。
Integer CONTROL_VIDEO_STABILIZATION_MODE 视频稳定是否活跃。
Integer EDGE_MODE 边缘增强的操作模式。
Integer FLASH_MODE 闪存模式
Integer HOT_PIXEL_MODE 热像素校正的操作模式。
Location JPEG_GPS_LOCATION 在生成图像GPS元数据时使用的位置对象。
Integer JPEG_ORIENTATION 一个JPEG图像的朝向。
Byte JPEG_QUALITY 最终JPEG图像的压缩质量
Size JPEG_THUMBNAIL_SIZE 嵌入的JPEG缩略图的解析。
Float LENS_APERTURE 所需的镜头光圈大小,作为透镜焦距与有效孔径的比值。
Float LENS_FILTER_DENSITY 镜头中性密度滤光片(s)所需的设置。
Float LENS_FOCAL_LENGTH 想要的镜头焦距;用于光学变焦。
Float LENS_FOCUS_DISTANCE 从镜头的最前表面测量到最尖锐焦点的距离。
Integer LENS_OPTICAL_STABILIZATION_MODE 设置相机设备在拍摄图像时是否使用光学图像稳定(OIS)。
Integer NOISE_REDUCTION_MODE 降噪算法的操作模式。
Float REPROCESS_EFFECTIVE_EXPOSURE_FACTOR 在进行再加工前,应用处理的应用程序处理的暴露时间增加了。
Rect SCALER_CROP_REGION 传感器所需要的区域来读取这个捕获(拍某个形状的设置)
Long SENSOR_EXPOSURE_TIME 持续每一个像素都暴露在光中。
Long SENSOR_FRAME_DURATION 从帧曝光开始到下一个帧曝光的持续时间
Integer SENSOR_SENSITIVITY 处理前的传感器数据的增益。
int[] SENSOR_TEST_PATTERN_DATA 当android.sensor.testPatternMode是 SOLID_COLOR,一个pixel[R, G_even, G_odd, B]提供测试模式的像素
Integer SENSOR_TEST_PATTERN_MODE 当启用时,传感器会发送一个测试模式,而不是从摄像机中进行真实的曝光。
Integer SHADING_MODE 镜头阴影校正的质量应用于图像数据。
Integer STATISTICS_FACE_DETECT_MODE 人脸检测装置的工作模式
Boolean STATISTICS_HOT_PIXEL_MAP_MODE 热像素映射生成的操作模式。
Integer STATISTICS_LENS_SHADING_MAP_MODE 摄像机设备是否会输出结果元数据中的镜头着色图。
TonemapCurve TONEMAP_CURVE 当android.tonemap.mode 是CONTRAST_CURVE时,使用音调/对比度/伽玛曲线
Float ONEMAP_GAMMA android.tonemap.mode 是GAMMA_VALUE时,使用Tonemapping曲线。tonemap曲线将定义如下公式:OUT=pow(在1.0/gamma中)输入的像素值被缩放到范围0.0,1.0,pow是能量函数,而伽玛是这个键所指定的伽马值。
Integer TONEMAP_MODE 高级全球对比/γ/ tonemapping控制。
Integer TONEMAP_PRESET_CURVE android.tonemap.mode 是 PRESET_CURVE时,使用Tonemapping曲线。tonemap曲线将由指定的标准定义。

公众号“编程之路从0到1”

20190301102949549

Copyright © Arcticfox 2021 all right reserved,powered by Gitbook文档修订于: 2022-05-01 12:20:20

results matching ""

    No results matching ""