对焦功能标准化流程
一、摘要
本篇文章围绕实际相机功能的对焦场景阐述如何开发好一个功能完善的相机对焦功能。
相关文章:
二、对焦功能流程
2.1 功能分类
2.1.1 对焦模式
对焦模式 |
---|
FOCUS_MODE_AUTO |
FOCUS_MODE_INFINITY |
FOCUS_MODE_MACRO |
FOCUS_MODE_FIXED |
FOCUS_MODE_EDOF |
FOCUS_MODE_CONTINUOUS_VIDEO |
FOCUS_MODE_CONTINUOUS_PICTURE |
具体细节可参考Camera1 Parameters参数详解(二)—— 3A算法 (对焦、曝光、白平衡)【二.AF】
2.1.2 对焦功能
- 连续对焦:用于相机移动预览画面,对应对焦模式为
continuous
- 单次对焦:touch focus,点击对焦
2.2 对焦工作流程
2.2.1 Part1: 【1、2、3】
- 进入相机首先设置模式为连续对焦,拍照和视频对应不同的连续对焦
2.2.2 Part2:【5、6、7】
- 单次对焦分为2种,一种为自己触发一次中心对焦。另外一种为根据onTouchEvent获取点击位置Touch Focus。
- 自己触发一次中心对焦即坐标点为(mPreviewUIWidth/2f,mPreviewUIHeight/2f),Touch Focus即(touchX, touchY)
- 判断AUTO模式,判断maxMeterAreaNum、maxFocusAreaNum等
- 具体代码可参考Camera1 对焦(二) 对焦区域计算的几种方式(Touch to Focus)
2.2.3 Part3:【8、9】
part2之后即锁定了对焦区域为Part2设置的rect。此时需要监听手机是否移动,如果不监听手机是否做移动就会出现对焦区域锁定在点击区域,移到别的场景就会出现不对焦的情况。
- 监听手机传感器,根据阀值判断手机是否移动相关距离
- 如果移动则切换到连续对焦
- 这里需要延后一定时间如3000ms后开始检测移动,否则当点击固定区域对焦后手抖就会立马失焦
2.3 相关代码
2.3.1 设置连续对焦模式代码:
private void setAutoFocus(Camera camera) {
if (camera is null) {
return;
}
try {
Camera.Parameters params = mCamera1Config.getCameraParameter(camera);
if (params == null) {
return;
}
List<String> modes = params.getSupportedFocusModes();
if (modes is null) {
return;
}
if (isVideo && modes.contains(FOCUS_MODE_CONTINUOUS_VIDEO)) {
params.setFocusMode(FOCUS_MODE_CONTINUOUS_VIDEO);
} else if (modes.contains(FOCUS_MODE_CONTINUOUS_PICTURE)) {
params.setFocusMode(FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (modes.contains(FOCUS_MODE_FIXED)) {
params.setFocusMode(FOCUS_MODE_FIXED);
} else if (modes.contains(FOCUS_MODE_INFINITY)) {
params.setFocusMode(FOCUS_MODE_INFINITY);
} else {
params.setFocusMode(modes.get(0));
}
camera.setParameters(params);
} catch (Exception e) {
...
}
}
2.3.2 touch Focus相关代码
传送门
=> Camera1 对焦(二) 对焦区域计算的几种方式(Touch to Focus)
2.3.3 监听传感器移动
public class PhoneMovementDetector implements SensorEventListener {
protected final String TAG = getClass().getSimpleName();
private SensorManager sensorManager;
private Sensor accelerometer;
private Listener listener;
private Semaphore lock = new Semaphore(1);
private static PhoneMovementDetector mInstance = new PhoneMovementDetector();
private void init() {
sensorManager = (SensorManager) AppContexts.sContext.getSystemService(Context.SENSOR_SERVICE);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
}
public PhoneMovementDetector start(Listener listener) {
this.listener = listener;
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
return this;
}
public PhoneMovementDetector stop() {
sensorManager.unregisterListener(this);
this.listener = null;
return this;
}
private long lastTime = 0;
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {
try {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
float diff = x * x + y * y + z * z;
listener.onMotionDetected(diff);
} catch (Exception e) {
} finally {
}
}
}
public interface Listener {
void onMotionDetected(float acceleration);
}
}
综上,Android Camera里对焦功能开发基于上述流程即可。