android - 如何在手动设置所有设置(包括闪光灯)的情况下拍摄照片,而不会丢失包含完整闪光灯的图像?
问题描述
我使用最新的 Camera2Basic 示例程序作为我的试验源:
https://github.com/android/camera-samples.git
基本上,我在 takePhoto() 函数中调用 capture() 函数之前配置了 CaptureRequest,如下所示:
private fun prepareCaptureRequest(captureRequest: CaptureRequest.Builder) {
//set all needed camera settings here
captureRequest.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF)
captureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
//captureRequest.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
//captureRequest.set(CaptureRequest.CONTROL_AWB_LOCK, true);
captureRequest.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF);
captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
//captureRequest.set(CaptureRequest.CONTROL_AE_LOCK, true);
//captureRequest.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL);
//captureRequest.set(CaptureRequest.NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_FAST);
//flash
if (mState == CaptureState.PRECAPTURE){
//captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
captureRequest.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF)
}
if (mState == CaptureState.TAKEPICTURE) {
//captureRequest.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE)
//captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
captureRequest.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE)
}
val iso = 100
captureRequest.set(CaptureRequest.SENSOR_SENSITIVITY, iso)
val fractionOfASecond = 750.toLong()
captureRequest.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 1000.toLong() * 1000.toLong() * 1000.toLong() / fractionOfASecond)
//val exposureTime = 133333.toLong()
//captureRequest.set(CaptureRequest.SENSOR_EXPOSURE_TIME, exposureTime)
//val characteristics = cameraManager.getCameraCharacteristics(cameraId)
//val configs: StreamConfigurationMap? = characteristics[CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP]
//val frameDuration = 33333333.toLong()
//captureRequest.set(CaptureRequest.SENSOR_FRAME_DURATION, frameDuration)
val focusDistanceCm = 20.0.toFloat() //20cm
captureRequest.set(CaptureRequest.LENS_FOCUS_DISTANCE, 100.0f / focusDistanceCm)
//captureRequest.set(CaptureRequest.COLOR_CORRECTION_MODE, CameraMetadata.COLOR_CORRECTION_MODE_FAST)
captureRequest.set(CaptureRequest.COLOR_CORRECTION_MODE, CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX)
val colorTemp = 8000.toFloat();
val rggb = colorTemperature(colorTemp)
//captureRequest.set(CaptureRequest.COLOR_CORRECTION_TRANSFORM, colorTransform);
captureRequest.set(CaptureRequest.COLOR_CORRECTION_GAINS, rggb);
}
但返回的图片绝不是闪光灯最亮的图片。这是在 Google Pixel 2 设备上。因为我只拍了一张照片,所以我也不确定如何检查一些 CaptureResult 状态以找到正确的照片,因为只有一张照片。我已经在这里查看了类似问题的其他解决方案,但它们要么从未真正解决,要么在捕获预览期间以某种方式拍摄了我不想要的照片。
其他奇怪的观察是,在不同的设备上拍摄图像(也不总是在正确的时刻),但是我设置的手动值在图像的 JPEG 元数据中没有观察到。
如果需要,我可以将我的 git fork 放在 github 上。
解决方案
长曝光时间与闪光灯相结合似乎是基本问题,当结果不是那么好时,这意味着您的预设时间不是那么好。您必须根据闪光灯的时间优化曝光时间的持续时间(只需检查一些照片的 EXIF 以获取示例值)。您可以使用 an 来测量亮度ImageAnalysis.Analyzer
(这已从示例应用程序中删除,但旧版本仍有示例)。我已经尝试过使用默认的摩托罗拉相机应用程序;那里的照片似乎也是在闪光后不久拍摄的,当时亮度已经衰减(为了避免耀眼的亮光)。那是CaptureState.PRECAPTURE
,您关闭闪光灯的位置。在两个阶段闪烁是相当默认的,这可能会产生更好的结果。
如果你想让它耀眼夺目(即使这通常是不希望的),你也可以先打开手电筒,图像,再次关闭手电筒(我使用类似的东西,但仅用于条形码扫描) . 这至少可以防止任何曝光/闪光时间问题。
当 EXIF 中未表示更改的值时,您需要使用ExifInterface
, 来更新它们(有一个更新方向的示例,但可以更新任何值)。
推荐阅读
- python - 寻找有关此“For-Loop”如何工作的说明
- swift - 如何在 Xcode 中添加可由 Swift 包管理器运行的可执行文件?
- arrays - 如何使用 mongoldb 仅将键值放入数组中?
- python - Pandas - 显示一列中值的百分比,按另一列分组
- javascript - 如何防止 HTML 表单输出被样式化?
- javascript - 使用 MediaRecorder 录制音频 webm 时没有元数据
- spring-batch - 运行 Job 时如何将运行时参数传递给 Itemreader
- facebook - Facebook 报告工具
- json - .NET Core - 如何上传 JSON 文件?
- vue.js - Framework7 路由保护