Android CameraX如何实现广角/缩小



我试图使用CameraXapi为我的应用内相机实现广角选项,但遇到了一个问题-CameraControl.setZoomRatio允许在ZoomState.getMinZoomRatio()ZoomState.getMaxZoomRatio()之间设置缩放,在手机上我测试了minZoomRatio1.0f。同一款手机在系统摄像头中支持缩小到0.5f

当前片段我如何初始化相机:

private var camera: Camera? = null
private var imageCapture: ImageCapture? = null
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(binding.viewFinder.surfaceProvider)
}
imageCapture = ImageCapture.Builder()
.setFlashMode(ImageCapture.FLASH_MODE_AUTO)
.build()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
cameraProvider.unbindAll()
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)
viewModel.onCameraStarted()
} catch (exc: Exception) {
Timber.e(exc)
}
},
ContextCompat.getMainExecutor(this)
)
}

当前的缩放实现:

val scaleGestureDetector = ScaleGestureDetector(this,
object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
override fun onScale(detector: ScaleGestureDetector): Boolean {
val camera = camera ?: return false
val zoomState = camera.cameraInfo.zoomState.value ?: return false
val scale = zoomState.zoomRatio * detector.scaleFactor
val finalScale =
scale.coerceIn(MIN_ZOOM, MAX_ZOOM).coerceIn(zoomState.minZoomRatio, zoomState.maxZoomRatio)
camera.cameraControl.setZoomRatio(finalScale)
return true
}
})
binding.viewFinder.setOnTouchListener { view, event ->
view.performClick()
scaleGestureDetector.onTouchEvent(event)
return@setOnTouchListener true
}

我的问题是,是否可以使用CameraXapi使用广角相机(或实现0.5f变焦(,或者我是否必须使用Camera2重写整个实现。

正如问题下面的评论中所解释的,宽镜头相机(以及任何其他相机,例如,如果我们试图实现变焦x20,则为大变焦(是独立的相机,因此为了允许在普通相机和(例如(宽镜头相机之间切换,我们必须使用不同的相机选择器重新启动相机视图。我们如何重新启动它,取决于我们(例如,在特定的挤压后重新启动,或者通过切换相机的按钮重新启动(。

这是一个相机选择器,它可以根据startCameraData.ultraWide参数获得后置相机或宽镜头后置相机:

val cameraSelector = if (startCameraData.ultraWide) {
CameraSelector.Builder()
.addCameraFilter { cameraInfos ->
// filter back cameras with minimum sensor pixel size
val backCameras = cameraInfos.filterIsInstance<Camera2CameraInfoImpl>()
.filter {
val pixelWidth = it.cameraCharacteristicsCompat.get(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE)?.width ?: 0
it.lensFacing == CameraSelector.LENS_FACING_BACK && pixelWidth >= 2000 // arbitrary number resolved empirically
}  
// try to find wide lens camera, if not present, default to general backCameras
backCameras.minByOrNull {
val focalLengths = it.cameraCharacteristicsCompat.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)
focalLengths?.getOrNull(0) ?: 0f
}
?.let { listOf(it) } ?: backCameras
}
.build()
} else {
CameraSelector.DEFAULT_BACK_CAMERA
}

注意:Camera2 api可能无法根据手机访问某些相机,但有时也会访问,除非应用程序包被谷歌列入白名单。例如,Open Camera应用程序(net.sourceforge.opencamera(被列入白名单,并且可以访问所有相机。我通过将应用程序包更改为net.sourceforge.opencamera进行了测试,突然得到了6个摄像头ID,而不是3个。

最新更新