概述:
Android支持很多种相机功能, 我们可以在自己的APP中控制它, 比如图片格式, 闪光模式, 焦点设置, 还有很多别的. 这里会列出相机的常用功能并简要地讨论如何使用它们. 大多数相机功能可以访问并且通过Camera.Parameters对象设置使用. 但是有一些重要的功能需要更加复杂的设置. 这些功能将在之后介绍. 包括: 测光和聚焦(Metering and focus areas), 人脸识别(Face detection),延时拍摄(Time lapse video).
Camera.Parameters:
下表是常用的相机功能, 按照引入的API级别排列.
功能 | 版本 | 描述 |
人脸识别(Face Detection) | 14 | 识别图片中的人脸, 并对他们聚焦, 测光, 和白平衡. |
测光区域(Metering Areas) | 14 | 指定图片中的一个或更多的区域用于计算白平衡. |
聚焦(Focus Areas) | 14 | 设置图片中的一个或更多的区域用来做焦点. |
白平衡锁定(White Balance Lock) | 14 | 启动或者停止自动白平衡调整. |
曝光锁定(Exposure Lock) | 14 | 启动或者停止自动曝光调整. |
视频快照(Video Snapshot) | 14 | 拍摄视频的时候截个图(帧抓取) |
延迟摄影 (Time Lapse Video) | 11 | 根据设置的延迟来录制帧. |
多相机拍摄(Multiple Cameras) | 9 | 为多于一个相机的设备提供支持. 包括前置和后置相机. |
对焦距离(Focus Distance) | 9 | 报告相机和焦点之间的距离. |
放大(Zoom) | 8 | 设置图像放大. |
曝光补偿(Exposure Compensation) | 8 | 增加或减少曝光等级. |
GPS数据(GPS Data) | 5 | 设置是否包括图片的地理位置. |
白平衡(White Balance) | 5 | 设置白平衡模式, 它会影响照片的颜色值. |
对焦模式(Focus Mode) | 5 | 设置相机对焦的模式, 比如自动, 固定, 微距或者无穷大. |
场景模式(Scene Mode) | 5 | 为特定类型的拍摄场景设置模式, 比如夜间, 海滩, 雪景或者烛光场景. |
JPEG质量(JPEG Quality) | 5 | 为JPEG图片设置压缩等级, 它可以增加或者减少输出的图片文件的质量和大小. |
闪光模式(Flash Mode) | 5 | 开启关闭闪光灯, 也可以使用自动模式. |
色彩效果(Color Effects) | 5 | 为拍摄的图片指定色彩效果, 比如黑白, 棕褐色色调或者底片. |
消除条纹(Anti-Banding) | 5 | 在JPEG压缩的时候降低条纹的对比度, 变为渐变色. |
图片格式(Picture Format) | 1 | 为图片指定文件格式. |
图片大小(Picture Size) | 1 | 为保存的图片指定像素尺寸. |
这些功能根据硬件差异和软件实现并不会在所有的设备上都可以正常运行. 所以需要检查功能的可用性.
检查功能的可用性:
使用Android设备上的相机功能时首先要明白的是, 并不是所有的相机功能都可以在所有的设备上支持. 此外, 有些支持特殊功能的设备可能会有不同的可选功能. 因此, 开发策略由APP想要支持的功能决定.
我们可以通过获取一个相机参数对象实例来检查相机功能的可用性. 下面的代码展示了如何获得一个Camera.Parameters对象并检查相机是否支持自动聚焦功能:
// get Camera parameters
Camera.Parameters params = mCamera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
// Autofocusmode is supported
}
我们可以对大部分的相机功能使用上面的方法. Camera.Parameters对象提供了getSupported…()方法, is…Supported()方法, getMax…()方法来确认一个功能是否被支持.
如果APP需要确定相机功能来实现某一功能, 我们可以将它们添加到manifest中. 当我们声明使用某一个功能时, 比如闪光和自动聚焦, Google Play会限制APP安装在那些不支持这些功能的设备上.
使用相机功能:
大多数相机功能可以被Camera.Parameters对象激活并控制. 想要获取这个对象, 首先要获取一个Camera对象实例, 调用getParameters()方法, 修改返回的参数对象, 并将它设置给相机对象, 栗子:
// get Camera parameters Camera.Parameters params = mCamera.getParameters(); // set the focus mode params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); // set Camera parameters mCamera.setParameters(params);
该套路几乎可以用于所有的相机功能, 大部分参数可以在获取了Camera对象后的任何时候修改. 参数的修改可以直接影响到用户在预览窗口看到的效果. 在软件侧, 参数修改可能要消耗几帧的时间才能生效.
重要: 有些相机功能不能被随意修改. 特别是修改相机预览窗口的方向和尺寸, 修改这些参数需要先停止预览, 然后再重启预览. 从Android4.0开始, 预览方向可以不需要重启修改.
测光和焦点区域:
在某些情况下拍摄自动对焦和测光可能不会产生预期的效果, 从Android4.0开始, 相机APP可以提供额外的控制, 它允许APP或者用户可以指定图片区域用来确定焦点或者亮度等级, 并传递这些值给硬件用于拍摄.
测光和聚焦区域工作起来跟其它的相机功能相似, 通过Camera.Parameters对象来控制. 下面的代码展示了为一个Camera实例设置两个测光区域:
// Create an instance of Camera mCamera = getCameraInstance(); // set Camera parameters Camera.Parameters params = mCamera.getParameters(); if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); Rect areaRect1 = new Rect(-100, -100, 100, 100); // specify an area in center of image meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60% Rect areaRect2 = new Rect(800, -1000, 1000, -800); // specify an area in upper right of image meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40% params.setMeteringAreas(meteringAreas); } mCamera.setParameters(params);
Camera对象包含两个数据参数: 一个Rect对象用来指定一个相机区域中的矩形区域和一个比重值, 它告诉相机该区域的重要级别, 应该给予什么样的测光或者聚焦.
Camera.Area对象中的矩形区域描述了一个2000x2000的单元格. 坐标-1000,-1000表示相机图片的左上角, 坐标1000, 1000表示右下角, 如下图:
红线表示在相机预览窗口中用Camera.Area指定的坐标系统. 蓝色的矩形表示333,333,667,667坐标指示的形状.
这个坐标系的边界总是对应于相机预览中可见的图像边界, 并不随着缩放级别而收缩或者扩展. 同样, 通过Camera.setDisplayOrientation()方法旋转图像预览系统也不会重新映射坐标系统.
人脸识别:
对于包含人物的图片, 面部通常都是图中最重要的部分, 应该被着重照顾, 当拍照的时候聚焦和白平衡都应该用于面部. Android4.0 framework提供了用于识别面部和采用面部识别技术图像设置的API.
注意, 当面部识别功能正在运行的时候, setWhiteBalance(String), setFocusAreas(List)和setMeteringAreas(List)方法不生效.
在相机APP中使用面部识别技术需要以下几个典型的步骤:
l 检查设备是否支持人脸识别.
l 创建人脸识别监听器.
l 添加人脸识别监听器到相机对象.
l 预览后启动人脸识别(在每个预览重启之后).
人脸识别功能并不是所有的设备都可以支持的, 我们可以用getMaxNumDetectedFaces()方法检查该功能是否可用. 一个使用该方法的栗子将会在下面的startFaceDetection()方法的栗子中展示.
为了得到通知和对人脸识别做出响应, 相机应用必须为人脸识别事件设置一个监听器. 想要完成这个功能, 必须创建一个监听器类, 该类需要实现Camera.FaceDetectionListener接口, 栗子:
class MyFaceDetectionListener implements Camera.FaceDetectionListener { @Override public void onFaceDetection(Face[] faces, Camera camera) { if (faces.length > 0){ Log.d("FaceDetection", "face detected: "+ faces.length + " Face 1 Location X: " + faces[0].rect.centerX() + "Y: " + faces[0].rect.centerY() ); } } }
创建该类之后, 需要将它设置给APP的Camera对象, 栗子:
mCamera.setFaceDetectionListener(new MyFaceDetectionListener());
APP必须每次相机预览启动的时候(或者重启)都要开启人脸识别功能. 创建一个方法用于启动人脸识别, 这样就可以每次要的时候调用它了, 它是这样的:
public void startFaceDetection(){ // Try starting Face Detection Camera.Parameters params = mCamera.getParameters(); // start face detection only *after* preview has started if (params.getMaxNumDetectedFaces() > 0){ // camera supports face detection, so can start it: mCamera.startFaceDetection(); } }
记得每次都要开启. . .如果我们使用”创建一个预览类”小节中的预览类, 那么需要添加startFaceDetection()方法到surfaceCreated()和surfaceChanged()方法中. 栗子:
public void surfaceCreated(SurfaceHolder holder) { try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // start face detection feature } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (mHolder.getSurface() == null){ // preview surface does not exist Log.d(TAG, "mHolder.getSurface() == null"); return; } try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: " + e.getMessage()); } try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); startFaceDetection(); // re-start face detection feature } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } }
注意: 记得在调用startPreview()方法之后调用这个方法. 不要尝试在activity的onCreate()方法中启动人脸识别, 因为此时预览不可用.
延时拍摄:
该功能允许用户每隔几秒或者几分钟创建视频剪辑或图片. 该功能使用MediaRecorder来拍摄. 想要使用MediaRecorder实现该功能, 必须配置recorder对象, 就好像录制一个普通的视频那样, 设置每秒捕获帧到一个较低的数目并使用一个时间间隔质量设置, 栗子:
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)); ... // Step 5.5: Set the video capture rate to a low number mMediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
这些设置必须作为MediaRecorder较大的配置程序的一部分. 一个完整的配置代码的栗子, 可以参考”配置MediaRecorder”. 一旦配置完成, 就好像启动普通视频那样启动视频录制即可.
总结:
自定义相机可以更加的充分的利用相机提供的功能, 详情可以参考最上面的表格. 大部分的相机功能使用的流程是: 获取Camera.Paramters参数, 设置该参数, 然后将其再设置回给Camera对象.
参考: https://developer.android.com/guide/topics/media/camera.html