Android camera2相机手动对焦MF实现
时间: 2023-10-03 11:08:10 浏览: 127
实 Android Camera2 相机的手动对焦(Manual Focus),需要进行以下步骤:
1. 获取 CameraDevice 对象,并打开相机。
2. 创建 CameraCaptureSession 对象,并设置预览 Surface。
3. 创建 CaptureRequest.Builder 对象,并设置相机参数(如曝光、ISO等)。
4. 设置手动对焦模式:
- 获取相机支持的手动对焦模式列表。
- 选择最合适的手动对焦模式。
- 设置手动对焦模式到 CaptureRequest.Builder 对象中。
5. 监听相机状态变化,并在相机状态变为 CameraDevice.STATE_ACTIVE 时进行手动对焦操作。
6. 创建 CaptureRequest 对象,并将其提交给 CameraCaptureSession 进行拍照或预览。
以下是示例代码:
```java
private void setupCamera() {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
String cameraId = null;
try {
// 获取相机列表中的第一个相机
cameraId = cameraManager.getCameraIdList()[0];
} catch (CameraAccessException e) {
e.printStackTrace();
}
try {
// 打开相机
cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera;
createCaptureSession();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
camera.close();
mCameraDevice = null;
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
camera.close();
mCameraDevice = null;
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCaptureSession() {
try {
// 创建预览 Surface
SurfaceTexture texture = mTextureView.getSurfaceTexture();
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface surface = new Surface(texture);
// 创建 CameraCaptureSession
mCameraDevice.createCaptureSession(Collections.singletonList(surface),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
mCaptureSession = session;
try {
// 创建 CaptureRequest.Builder
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
// 设置手动对焦模式
int[] afModes = mCameraCharacteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
if (afModes != null && afModes.length > 0) {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
if (Arrays.asList(afModes).contains(CaptureRequest.CONTROL_AF_MODE_MANUAL)) {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_MANUAL);
}
}
// 监听相机状态变化
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
mCaptureSession = session;
updatePreview();
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Toast.makeText(MainActivity.this, "配置相机失败", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Toast.makeText(MainActivity.this, "配置相机失败", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
try {
// 创建 CaptureRequest 对象
CaptureRequest previewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(previewRequest, null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
// 手动对焦
private void manualFocus(float x, float y) {
try {
// 计算对焦区域
Rect rect = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
int areaSize = 200;
int right = rect.right;
int bottom = rect.bottom;
int centerX = (int) (x / (float) mTextureView.getWidth() * right);
int centerY = (int) (y / (float) mTextureView.getHeight() * bottom);
int left = centerX - areaSize;
int top = centerY - areaSize;
right = centerX + areaSize;
bottom = centerY + areaSize;
left = Math.max(left, rect.left);
top = Math.max(top, rect.top);
right = Math.min(right, rect.right);
bottom = Math.min(bottom, rect.bottom);
Rect touchArea = new Rect(left, top, right, bottom);
// 计算对焦区域的权重
MeteringRectangle[] areas = new MeteringRectangle[1];
areas[0] = new MeteringRectangle(touchArea, 1000);
// 设置手动对焦区域和权重
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, areas);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, areas);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
// 更新 CaptureRequest
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
```
在 Activity 中实现 onTouchEvent 方法,实现手动对焦:
```java
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
manualFocus(event.getX(), event.getY());
return true;
}
return super.onTouchEvent(event);
}
```
以上是一个简单的手动对焦实现,需要注意的是不同手机的相机支持的手动对焦模式可能不同,需要根据具体情况进行调整。
阅读全文