当前位置: 首页 > news >正文

【用androidx.camera拍摄景深合成照片】

用androidx.camera拍摄景深合成照片

  • 用androidx.camera拍摄景深合成照片
      • 项目概述
      • 系统结构
      • 相机控制基础
      • 核心实现方法
      • 技术栈

用androidx.camera拍摄景深合成照片

androidx.camera的不断完善,使得原来复杂繁琐的安卓相机开发容易了许多。很多传统相机上有称之为景深包围的拍照功能,一次拍摄完成多张不同焦距的照片,后期用软件把多张照片合成为一张大景深或全景深照片,这种拍摄方式在安卓系统中也可以实现。

项目概述

DeepCamera 是一个基于 Android 平台的相机应用项目,采用 Kotlin 语言和 Jetpack Compose 框架开发,集成 CameraX 库实现相机功能。模块app用CameraControl+Camera2CameraControl实现对相机的控制。
一次拍摄可以得到多张不同焦距的照片,后期可以用软件(例如photoshop)合成一张大景深照片。

系统结构

整体结构如下:

DeepCamera/app/  
├── theme/					#主题
├── CameraScreen			#相机预览和拍照界面
├── FocusDistanceInfo		#相机焦距信息
├── FocusItem				#焦距项
├── MainActivity			#主界面
├── MainSurface				#相机页面	
├── SettingsSurface			#焦距设置页面
├── ShutterSound			#快门声效类
└── Util         			#静态子程序类  

核心组件包括:

  • UI 层:使用 Jetpack Compose 构建响应式界面
  • 相机控制层:基于 CameraX 实现相机硬件交互
  • 数据层:处理图片存储与系统媒体库交互

相机控制基础

androidX用抽象类UseCase(用例)管理相机的应用。UseCase目前只有ImageAnalysis, ImageCapture, Preview, VideoCapture四种子类,对应四种应用:图像分析、拍照、预览、拍视频。在程序中需要把UseCase绑定到CameraProvider,以实现对相机应用场景的控制。本程序只用到UseCase的两种应用场景:ImageCapture和Preview。

androidX对于相机的控制有三种途径

  1. CameraController
    CameraController是androidx.camera.view中的抽象类,它的实现是LifecycleCameraController,这是一个高级控制器,在单个类中提供了大多数 CameraX 核心功能。它负责相机初始化,创建并配置用例,并在准备就绪时将它们绑定到生命周期所有者。它还会监听设备运动传感器,并为UseCase用例设置目标旋转角度。
  2. CameraControl
    CameraControl是androidx.camera.core中的接口,它提供各种异步操作,如变焦、对焦和测光,这些操作会影响当前绑定到该相机的所有UseCase用例的输出。CameraControl 的每种方法都会返回一个 ListenableFuture,应用程序可以用它来检查异步结果。
  3. Camera2CameraControl
    Camera2CameraControl是androidx.camera.camera2.interop中的不可重写类,它提供与 android.hardware.camera2 API 的互操作能力,可以实现CameraControl所不能提供的相机底层操作,例如手动设定焦距。

本程序使用CameraControl+Camera2CameraControl实现对相机的控制,没有使用CameraController。
获取CameraControl和Camera2CameraControl的步骤如下:

val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
// 初始化CameraProvider的监听器
val cameraProviderFuture = remember { ProcessCameraProvider.getInstance(context) }
// 初始化CameraProvider
var cameraProvider by remember { mutableStateOf<ProcessCameraProvider?>(null) }
// 初始化PreviewView
val previewView = remember {PreviewView(context).apply {implementationMode = PreviewView.ImplementationMode.PERFORMANCE}
}
// 初始化相机
var camera by remember { mutableStateOf<Camera?>(null) }
// 创建拍照用例
val imageCapture = remember { Util.getImageCapture() }
// 创建预览用例
val preview = remember { Util.getPreview() }
// 使用previewView的SurfaceProvider来配置预览用例
preview.setSurfaceProvider(previewView.surfaceProvider)
// 监听CameraProvider的变化,从监听器中获取CameraProvider实例
cameraProvider = cameraProviderFuture.get()
//定义后摄像头的选择器
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
// 解除既有绑定
cameraProvider.unbindAll()
// 绑定新的用例
camera = cameraProvider.bindToLifecycle(lifecycleOwner,cameraSelector, imageCapture, preview)
// 取得cameraControl
val cameraControl = camera!!.cameraControl
// 取得camera2CameraControl
val camera2CameraControl = Camera2CameraControl.from(cameraControl)

核心实现方法

  1. 获取Preview
fun getPreview(): Preview {// 定义ResolutionStrategyval resolutionStrategy = ResolutionStrategy(Size(1920, 1080), FALLBACK_RULE_CLOSEST_LOWER)// 定义AspectRatioStrategyval aspectRatioStrategy =AspectRatioStrategy(AspectRatio.RATIO_16_9, AspectRatioStrategy.FALLBACK_RULE_AUTO)// 定义ResolutionSelectorval resolutionSelector =ResolutionSelector.Builder().setAspectRatioStrategy(aspectRatioStrategy).setResolutionStrategy(resolutionStrategy).build()return Preview.Builder().setResolutionSelector(resolutionSelector).build()}
  1. 获取ImageCapture
fun getImageCapture(): ImageCapture {// 定义ResolutionStrategyval resolutionStrategy = ResolutionStrategy.HIGHEST_AVAILABLE_STRATEGY// 定义AspectRatioStrategyval aspectRatioStrategy =AspectRatioStrategy(AspectRatio.RATIO_16_9, AspectRatioStrategy.FALLBACK_RULE_AUTO)// 定义ResolutionSelectorval resolutionSelector =ResolutionSelector.Builder().setAspectRatioStrategy(aspectRatioStrategy).setResolutionStrategy(resolutionStrategy).build()return ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY).setResolutionSelector(resolutionSelector).build()}
  1. 获取ImageCapture的输出文件选项
private fun getOutputFileOptions(context: Context): ImageCapture.OutputFileOptions {val contentValues = ContentValues().apply {val simpleDateFormat = SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.getDefault())val currentDateTime = simpleDateFormat.format(Date())put(MediaStore.MediaColumns.DISPLAY_NAME, "${currentDateTime}.jpg")put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)}return ImageCapture.OutputFileOptions.Builder(context.contentResolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build()}
  1. 设置缩放比例
fun setZoomRatio(cameraControl: CameraControl, zoomRatio: Float?): ListenableFuture<Void?> {val clampedZoomRatio = zoomRatio?.coerceIn(0f, 1f) ?: 0freturn cameraControl.setLinearZoom(clampedZoomRatio)}
  1. 设置焦距
private fun setFocusDistance(cameraControl: CameraControl, focusDistance: Float): ListenableFuture<Void?> {val camera2CameraControl = Camera2CameraControl.from(cameraControl)val captureRequestOptions = CaptureRequestOptions.Builder().setCaptureRequestOption(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF).setCaptureRequestOption(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance).build()return camera2CameraControl.setCaptureRequestOptions(captureRequestOptions)}
  1. 获取相机的对焦信息
fun getFocusDistanceInfo(context: Context): FocusDistanceInfo {val cameraManager =context.getSystemService(Context.CAMERA_SERVICE) as android.hardware.camera2.CameraManagerval cameraId = cameraManager.cameraIdList.firstOrNull {val characteristics = cameraManager.getCameraCharacteristics(it)characteristics.get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_BACK}if (cameraId == null) {Log.e("getMinFocusDistance", "No back camera found")return FocusDistanceInfo(0f, 0f, "no-camera-found")}val characteristic = cameraManager.getCameraCharacteristics(cameraId)// 检查是否支持手动对焦val afAvailability = characteristic.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES)if (afAvailability == null || !afAvailability.contains(CameraMetadata.CONTROL_AF_MODE_OFF)) {Log.e("getMinFocusDistance", "Camera does not support manual focus")return FocusDistanceInfo(0f, 0f, "non-focus-support")}// 获取镜头是否校准val focusDistanceCalibration =when (characteristic.get(CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION)) {CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED -> "uncalibrated"CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED -> "calibrated"CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE -> "approximate"else -> "unknown"}Log.i("getMinFocusDistance", "isLensCalibrated: $focusDistanceCalibration")// 获取焦点范围val minFocusDistance = characteristic.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) ?: 0fLog.i("getMinFocusDistance", "minFocusDistance: $minFocusDistance")// 获取超焦距val hyperFocalDistance = characteristic.get(CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE) ?: 0fLog.i("getMinFocusDistance", "hyperFocalDistance: $hyperFocalDistance")return FocusDistanceInfo(minFocusDistance, hyperFocalDistance, focusDistanceCalibration)}

技术栈

  • 开发语言:Kotlin
  • UI 框架:Jetpack Compose
  • 相机库:CameraX
  • 架构组件:Lifecycle、Navigation
  • 生命周期处理:Composable Effect
  • 图片存储:MediaStore

源代码

http://www.dtcms.com/a/414534.html

相关文章:

  • linux安装google chrome 谷歌浏览器
  • 从零起步学习Redis || 第二章:Cache Aside Pattern(旁路缓存模式)以及优化策略
  • 两性做受技巧视频网站喊别人做的网站不肯给代码
  • ESP32-S3入门第八天:往期知识回顾与实战练习
  • Claude Code 实战指南(三):AI辅助开发工作流 Spec Workflow MCP教程
  • 红帽认证含金量怎么样?适合哪些人?
  • 宣传的网站开发需要多少钱步骤的英文
  • 选择一款拖拽式界面的vscode扩展程序制作Python界面
  • Android开发-屏幕变更事件
  • 十大咨询公司排行榜aso优化师主要是干嘛的
  • LeetCode第1346题 - 检查整数及其两倍数是否存在
  • 【Leetcode hot 100】207.课程表
  • 搜索引擎高级搜索技巧
  • 2.3 物理层设备 (答案见原书 P48)
  • 华为OBS obsutil使用
  • 租购同权七年之痒:政策善意如何变现?
  • 【Linux操作系统】基础开发工具
  • 老年ai模拟恋爱抖音快手微信小程序看广告流量主开源
  • 知名的网站制作公司需要多少钱企业宣传网站模板下载
  • 深圳横岗做网站的网站品牌形象设计怎么做
  • 社区网站推广方案百度百家号注册
  • 编程竞赛高频考点
  • Linux 程序使用 STDOUT 打印日志导致程序“假死”?一次线上 Bug 的深度排查与解决
  • (一)routeros命令笔记:开局篇
  • 网站推广模式一份完整的项目计划书
  • 基于STM32设计的智能安全头盔_299
  • ​VR应急安全学习机,提升应对自然灾害时自救互救的应急技能
  • app网站建设公司竞彩网站建设
  • pytorch基本运算-torch.normal()函数输出多维数据时,如何绘制正态分布函数图
  • OpenCV2-图像基本操作-阈值与平滑处理-形态学-梯度运算