Camera2 API 是 Android 5.0 (Lollipop) 引入的新相机框架,取代了旧的 Camera API。它提供了更精细的控制能力,包括手动控制曝光时间、ISO、对焦等参数。
曝光时间是指相机传感器暴露在光线下的时间长度,通常以纳秒(ns)为单位。较长的曝光时间可以让更多光线进入,适合低光环境,但可能导致运动模糊;较短的曝光时间适合明亮环境或快速移动的物体。
要获取 Camera2 API 的当前曝光时间,需要通过 CameraCharacteristics 和 CaptureResult 来获取相关信息。
首先需要检查设备是否支持手动曝光控制:
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
boolean isManualExposureSupported = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES) != null
&& Arrays.asList(characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES))
.contains(CameraMetadata.CONTROL_AE_MODE_OFF);
在预览过程中,可以通过 CaptureResult 获取当前的曝光时间:
private CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
Long exposureTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
if (exposureTime != null) {
// 曝光时间以纳秒为单位
Log.d("Camera2API", "当前曝光时间: " + exposureTime + " ns");
// 转换为更常用的单位,如毫秒
double exposureTimeMs = exposureTime / 1_000_000.0;
Log.d("Camera2API", "当前曝光时间: " + exposureTimeMs + " ms");
}
}
};
以下是获取并显示当前曝光时间的完整示例:
public class Camera2Activity extends AppCompatActivity {
private CameraManager cameraManager;
private String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSession;
private TextureView textureView;
private TextView exposureTimeTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera2);
textureView = findViewById(R.id.textureView);
exposureTimeTextView = findViewById(R.id.exposureTimeTextView);
cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
}
private void openCamera() {
try {
cameraId = cameraManager.getCameraIdList()[0]; // 通常使用后置摄像头
// 检查手动曝光支持
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
boolean isManualExposureSupported = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES) != null
&& Arrays.asList(characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES))
.contains(CameraMetadata.CONTROL_AE_MODE_OFF);
if (!isManualExposureSupported) {
Log.w("Camera2API", "设备不支持手动曝光控制");
}
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
cameraManager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
cameraDevice.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};
private void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(640, 480); // 设置预览尺寸
Surface surface = new Surface(texture);
CaptureRequest.Builder captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
// 设置自动曝光模式
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
if (cameraDevice == null) {
return;
}
cameraCaptureSession = session;
try {
session.setRepeatingRequest(captureRequestBuilder.build(), captureCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Toast.makeText(Camera2Activity.this, "配置失败", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
Long exposureTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
if (exposureTime != null) {
double exposureTimeMs = exposureTime / 1_000_000.0;
runOnUiThread(() -> {
exposureTimeTextView.setText(String.format("曝光时间: %.3f ms", exposureTimeMs));
});
}
}
};
@Override
protected void onResume() {
super.onResume();
if (textureView.isAvailable()) {
openCamera();
} else {
textureView.setSurfaceTextureListener(textureListener);
}
}
@Override
protected void onPause() {
closeCamera();
super.onPause();
}
private void closeCamera() {
if (cameraCaptureSession != null) {
cameraCaptureSession.close();
cameraCaptureSession = null;
}
if (cameraDevice != null) {
cameraDevice.close();
cameraDevice = null;
}
}
private TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
openCamera();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
}
原因:
解决方案:
原因:
解决方案:
原因:
解决方案:
// 关闭自动曝光
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
// 设置手动曝光时间(单位:纳秒)
captureRequestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, desiredExposureTimeInNs);
没有搜到相关的文章