我在三星Galaxy S7边缘设备上拍摄照片时遇到了不良行为。
在拍摄照片之前,我会同时等待对焦和曝光,但最后我与原生相机应用输出相比,有一种模糊的图像。
问题在缩放图像上尤其明显,但在未缩放时也存在。我也试图启用光学防抖,但问题并未解决。
以下是解释问题的链接样本图片。
以下是代码:
图片捕获方法步骤1:
public void capturePicture() {
CameraState state = getState();
if (state != IDLE && state != CLOSING && state != TAKE_PICTURE) {
boolean af = false;
boolean ae = false;
if (isAFEnabled()) {
af = true;
} else if (isAEEnabled()) {
ae = true;
}
if (!af && !ae) {
takePicture();
} else {
triggerFocusAndExposure(true);
}
}
return;
}
触发对焦和曝光的方法:
private void triggerFocusAndExposure(boolean picture) {
setState(WAIT_PRECAPTURE_PICTURE);
if (isAFEnabled()) {
previewBuilder.set(CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_START);
}
if (isAEEnabled()) {
previewBuilder.set(CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_START);
}
try {
cameraSession.capture(previewBuilder.build(), new SCameraCaptureSession.CaptureCallback() {
@Override public void onCaptureCompleted(SCameraCaptureSession session, SCaptureRequest request, STotalCaptureResult result) {
setState(PRECAPTURE_TRIGGERED_PICTURE);
}
}, backgroundHandler);
} catch (CameraAccessException e) {
return;
}
try {
previewBuilder.set(CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE);
previewBuilder.set(CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
cameraSession.setRepeatingRequest(previewBuilder.build(), mSessionCaptureCallback, backgroundHandler);
} catch (CameraAccessException e) {
}
}
等待焦点和曝光的方法:
private void waitPrecapture(STotalCaptureResult result, boolean picture) {
// Check if AF/AE triggered and/or finished
if ((!isAFTriggered(result) || isAfFinished(result)) && (!isAETriggered(result) || isAEFinished(result))) {
takePicture();
}
}
private boolean isAFTriggered(STotalCaptureResult result) {
Integer afMode = result.get(SCaptureResult.CONTROL_AF_MODE);
return afMode != CONTROL_AF_MODE_OFF &&
afMode != CONTROL_AF_MODE_EDOF;
}
private boolean isAfFinished(STotalCaptureResult result) {
int afState = result.get(SCaptureResult.CONTROL_AF_STATE);
return afState == CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CONTROL_AF_STATE_NOT_FOCUSED_LOCKED
|| afState == CONTROL_AF_STATE_PASSIVE_FOCUSED || afState == CONTROL_AF_STATE_PASSIVE_UNFOCUSED;
}
private boolean isAETriggered(STotalCaptureResult result) {
boolean aeMode = result.get(SCaptureResult.CONTROL_AE_MODE) != SCaptureResult.CONTROL_AE_MODE_OFF;
return aeMode && cameraCharacteristics.get(SCameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
!= SCameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
}
private boolean isAEFinished(STotalCaptureResult result) {
Integer aeState = result.get(SCaptureResult.CONTROL_AE_STATE);
return aeState == null || aeState == SCaptureResult.CONTROL_AE_STATE_CONVERGED || aeState == SCaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED
|| aeState == SCaptureResult.CONTROL_AE_STATE_LOCKED;
}
图片捕获方法步骤2:
public void takePicture(){
imageReader.setOnImageAvailableListener(reader -> {
Image image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
image.close();
singleSubscriber.onSuccess(bytes);
}, imageSavingHandler);
try {
cameraSession.capture(captureBuilder.build(), new SCameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(SCameraCaptureSession session, SCaptureRequest request, STotalCaptureResult result) {
if (getState() == CameraState.CLOSING) {
return;
}
cancelAF();
}
@Override
public void onCaptureStarted(SCameraCaptureSession session, SCaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
shutterCallback.call();
}
@Override public void onCaptureFailed(SCameraCaptureSession session, SCaptureRequest request, SCaptureFailure failure) {
singleSubscriber.onError(new RuntimeException("Error taking picture, onCaptureFailed"));
if (getState() == CameraState.CLOSING) {
return;
}
cancelAF();
}
}, backgroundHandler);
setState(CameraState.TAKE_PICTURE);
} catch (CameraAccessException e) {
singleSubscriber.onError(new RuntimeException("Error capturing image", e));
}
}
答案 0 :(得分:8)
我找到了解决办法。
captureBuilder
会自动设置CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY
和CaptureRequest.EDGE_MODE_HIGH_QUALITY
但在我的情况下,设备在处理这些选项时会遇到一些问题。设置CaptureRequest.NOISE_REDUCTION_MODE_FAST
和CaptureRequest.EDGE_MODE_FAST
可以解决问题。