https://www.jianshu.com/p/76225ac72b56

android从5.0开始,废弃了原有的Camera接口,提供了全新的Camera2接口。Camera2接口为了给app提供更强大更低级的摄像头控制,将整个的摄像头框架及流程进行了修改。在使用Camera2时,发现手工对焦的实现逻辑与旧的Camera实现该逻辑有较大不同,本文就谈下如何使用Camera2进行手工对焦。

1. 操作摄像头进行对焦

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[] {new MeteringRectangle(rect, 1000)});
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, new MeteringRectangle[] {new MeteringRectangle(rect, 1000)}); mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO); mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START); mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START); mPreviewRequest = mPreviewRequestBuilder.build(); try { mCaptureSession.setRepeatingRequest(mPreviewRequest, mAfCaptureCallback, mBackgroundHandler); } catch (CameraAccessException e) { Log.e(TAG, "setRepeatingRequest failed, " + e.getMessage()); } 

主要步骤:

  1. 指定自动对焦和自动嚗光测量的区域,这个区域就是手指点击的图像区域。
  2. 指定自动对焦模式为 CONTROL_AF_MODE_AUTO 模式,非点击对焦的时候,模式应该为 CONTROL_AF_MODE_CONTINUOUS_PICTURE 或者 CONTROL_AF_MODE_CONTINUOUS_VIDEO
  3. 将对焦的状态修改为开始对焦
  4. 触发连续获取图像数据

2. 对焦完成恢复正常的预览模式

if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState|| CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);mPreviewRequest = mPreviewRequestBuilder.build();try {mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mBackgroundHandler);} catch (CameraAccessException e) { Log.e(TAG, "setRepeatingRequest failed, errMsg: " + e.getMessage()); } } 

点击对焦完成后,将对焦模式修改为 CONTROL_AF_MODE_CONTINUOUS_VIDEO

3. 计算自动对焦区域

CONTROL_AF_REGIONS 的参数是指定用来测量对焦的区域,摄像头设备使用这个区域来测量光度情况进行对焦,因此该区域坐标系基于摄像头成像区域的坐标系。那么app接收到的图像数据与成像区域的关系如何呢?

手机摄像头成像区域是固定的,因此系统对于app中需要采集不同分辨率的需求做法是:将成像区域按照需要的分辨率比例进行居中裁剪,然后缩放到对应的尺寸。

Camera2通过不同的接口,给应用层提供了这方面的信息:

  • SENSOR_INFO_PIXEL_ARRAY_SIZE 表示的是摄像头成像区域所使用的内存大小。
  • SENSOR_INFO_ACTIVE_ARRAY_SIZE 表示真正接收光线的区域,因此成像的区域是该参数指定的区域,当然该矩形区域的坐标系基于 SENSOR_INFO_PIXEL_ARRAY_SIZE
  • SCALER_CROP_REGION 表示最终的输出内容是基于 SENSOR_INFO_ACTIVE_ARRAY_SIZE 裁剪的部分,而该值指定裁剪的区域。

摄像头输出裁剪区域

如图:整个区域(2000 x 1500)是整个成像所使用的内存区域,蓝色部分(crop region)是输出内容是使用的裁剪区域(根据我的测试结果发现,crop region基本等于成像区域大小),绿色的和橘黄色的部分就是不同分辨率所使用的区域。

了解该裁剪流程之后,就可以知道如何计算对焦区域了:

  • 一般app拿到摄像头来的数据之后,会将摄像头进行合适的旋转,然后根据屏幕比例居中裁剪图像数据,再进行显示。所以我们先将屏幕上面点击区域的坐标转化为app收到的图像区域的坐标:
// 先取相对于view上面的坐标
double x = event.getX(), y = event.getY(), tmp;// 取出来的图像如果有旋转角度的话,则需要将宽高交换下
int realPreviewWidth = mPreviewSize.width, realPreviewHeight = mPreviewSize.height; if (90 == mDisplayRotate || 270 == mDisplayRotate) { realPreviewWidth = mPreviewSize.height; realPreviewHeight = mPreviewSize.width; } // 计算摄像头取出的图像相对于view放大了多少,以及有多少偏移 double imgScale = 1.0, verticalOffset = 0, horizontalOffset = 0; if (realPreviewHeight * viewWidth > realPreviewWidth * viewHeight) { imgScale = viewWidth * 1.0 / realPreviewWidth; verticalOffset = (realPreviewHeight - viewHeight / imgScale) / 2; } else { imgScale = viewHeight * 1.0 / realPreviewHeight; horizontalOffset = (realPreviewWidth - viewWidth / imgScale) / 2; } // 将点击的坐标转换为图像上的坐标 x = x / imgScale + horizontalOffset; y = y / imgScale + verticalOffset; if (90 == mDisplayRotate) { tmp = x; x = y; y = mPreviewSize.height - tmp; } else if (270 == mDisplayRotate) { tmp = x; x = mPreviewSize.width - y; y = tmp; } 
  • app取到的图像是按照裁剪区域(crop region)按照预览尺寸的比例进行居中裁剪的,所以需要计算app取到的图像相对于裁剪区域进行了多少缩放,以及有多少位移:
// 计算取到的图像相对于裁剪区域的缩放系数,以及位移
Rect cropRegion = mPreviewRequest.get(CaptureRequest.SCALER_CROP_REGION);
if (null == cropRegion) {Log.e(TAG, "can't get crop region"); cropRegion = mActiveArraySize; } int cropWidth = cropRegion.width(), cropHeight = cropRegion.height(); if (mPreviewSize.height * cropWidth > mPreviewSize.width * cropHeight) { imgScale = cropHeight * 1.0 / mPreviewSize.height; verticalOffset = 0; horizontalOffset = (cropWidth - imgScale * mPreviewSize.width) / 2; } else { imgScale = cropWidth * 1.0 / mPreviewSize.width; horizontalOffset = 0; verticalOffset = (cropHeight - imgScale * mPreviewSize.height) / 2; } 
  • 将点击区域相对于app取到的图像坐标,转化为相对于成像区域的坐标:
// 将点击区域相对于图像的坐标,转化为相对于成像区域的坐标
x = x * imgScale + horizontalOffset + cropRegion.left;
y = y * imgScale + verticalOffset + cropRegion.top;
  • 按照对焦区域为成像区域的0.1倍计算对焦的矩形:
double tapAreaRatio = 0.1;
Rect rect = new Rect();
rect.left = clamp((int) (x - tapAreaRatio / 2 * cropRegion.width()), 0, cropRegion.width()); rect.right = clamp((int) (x + tapAreaRatio / 2 * cropRegion.width()), 0, cropRegion.width()); rect.top = clamp((int) (y - tapAreaRatio / 2 * cropRegion.height()), 0, cropRegion.height()); rect.bottom = clamp((int) (y + tapAreaRatio / 2 * cropRegion.height()), 0, cropRegion.height()); 

4. 总结

Camera2相对于就的Camera api来说,使用复杂度提升不少,但是提供更多的操作空间。同时,由于从Android 5.0就开始提供Camera2的接口,而有些机器并不一定支持全部的Camera2特性,所以需要通过 android.info.supportedHardwareLevel 查询支持的程度:

  • LEGACY:app调用Camera2的接口时,由框架将其转调给Camera API1来实现对应的功能,因此不支持Camera2的某些特性,如:每帧控制。
  • FULL:设备支持所有的Camera2接口。
  • LIMITED:设备支持部分的Camera2接口。

demo地址在这,demo中并没有查询级别,如果demo跑得不正常时,可以检查下支持级别是否是FULL。

文中的理解来自于下面几篇文章,有任何问题,欢迎指教:

  1. http://source.android.com/devices/camera/camera3_crop_reprocess.html
  2. https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#SCALER_CROP_REGION
  3. https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SENSOR_INFO_ACTIVE_ARRAY_SIZE
  4. https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SENSOR_INFO_PIXEL_ARRAY_SIZE
Android音视频

转载于:https://www.cnblogs.com/jukan/p/9896358.html

Camera2点击对焦实现相关推荐

  1. Camera2实现预览及算法处理

    一.应用背景 小白公司业务为车辆安全驾驶检测等,需要开启相机将图像传递给算法进行处理以达到行车预警的功能.由于项目需求,需要将开启相机这一块由原来的Camera1.0更新为Camera2.0,以下是小 ...

  2. android 点击连续拍照,android自定义相机、连续(自动)聚焦、点击(触摸)聚焦、变焦、拍照后自定义裁剪、旋转...

    最近做了一个图片识别.以及搜索的小项目,其中有一个模块是拍照以及拍照后对图片进行剪切,开始用的系统的相机和裁剪,由于系统的相机和裁剪多出了一些不必要的步骤和启动慢等等带给用户的体验不好,故自己写了一个 ...

  3. android 判断照片清晰度_手机如何拍出更清晰的照片?带你走进变焦与对焦的世界...

    *本文来自花粉俱乐部@倾阳一点丹心在 大家在讨论手机的拍照功能时,可能经常听到变焦和对焦这两个专业术语,那么到底什么是变焦,什么又是对焦呢? 一.变焦(Zoom) 是指通过调整镜头的焦距f,以改变相机 ...

  4. 【Android Camera1】Camera1 对焦(一) UI坐标系和相机坐标系

    一.简介 本篇文章为对焦系列文章的第一篇:主要讲解UI坐标系和相机坐标系.后续其他相关文章如下: 相关文章: Camera1 对焦(二) 对焦区域计算的几种方式(Touch to Focus) Cam ...

  5. Android开发自定义相机,自定义拍照界面

    1.目的 :开发时产品需求自己定义拍照界面,拍照处理.如下图:自定义一个拍照界面 可以看到,底部拍照按钮,和相册选择.整个界面和系统相机不一样.这时我们就要自己去开发定义自己的相机处理. 2.实现思路 ...

  6. Android JetPack组件-CameraX初探

    CameraX 又是一个 Google 推出的 JetPack 组件 ,是一个新鲜玩意儿,故给大家分享下我在项目中的使用过程心得.. CameraX 是什么? Google 开发者文档 对 Camer ...

  7. iOS 视频录制流程解析

    这篇文章主要介绍在 iOS 中视频录制的主要流程结构,以及相关 api 的介绍. 参考:录音Demo. 在 iOS 系统中,录制视频有两种方式,一种是直接利用系统封装好的 UIImagePickerC ...

  8. android7.1.1彩蛋魅族,魅族PRO 6 Android 7.1.1尝鲜, 一功能很“原生”

    原标题:魅族PRO 6 Android 7.1.1尝鲜, 一功能很"原生" 上周魅族因为Android N的系统未稳定了将内测推迟,如今终于迎来了首批内测,笔者有幸也申请到了And ...

  9. android技术需求,支撑你各种安卓相机开发需求CameraView

    名称 CameraView 语言 Android 平台 GitHub 作者 natario1 日常开发工作中,我们偶尔会遇到照相或摄像的开发需求,一般我们是会直接使用系统的Camera类,然后基于这个 ...

最新文章

  1. 3月最新!ESI世界大学排名:371所内地高校上榜!
  2. 大数据环境下数据科学的知识体系
  3. 进程的创建-fork
  4. C++STL容器大全
  5. tensorflow学习笔记:tf.data.Dataset,from_tensor_slices(),shuffle(),batch()的用法
  6. netflix_Netflix Archaius用于物业管理–基础知识
  7. linux常用网络命令详解,linux网络命令详解(鸟哥)
  8. Springboot集成BeanValidation扩展一:错误提示信息加公共模板
  9. NB-IoT---(0) NB-IoT技术
  10. [转] js中的钩子机制(hook)
  11. 计算机网络成绩分析单,【计算机网络论文】计算机网络技术课程教考分离解析(共2033字)...
  12. Java爬虫Crawler
  13. 黑莓9530完美刷机教程
  14. java se 通用能力-判断推理专项练习(选择题)
  15. spring-jpa中mappedby的作用
  16. 安卓虚拟键盘_干货分享:推荐几款性能不错的安卓模拟器
  17. llvm安装方式_LLVM 安装教程(包安装)
  18. 【camera】手机相机系统
  19. 【源码部署】Kettle IDEA 源码部署
  20. Flowable6.8(6.x版本通用)整合集成达梦8数据库(DM8)详解,解决自动生成表时dmn相关表语法报错问题。

热门文章

  1. C、C++语言中参数的压栈顺序
  2. javascript自制函数图像生成器
  3. 从零开始搭建系统2.4——Jenkins安装及配置
  4. mybatis 传参是 liststring 的注意事项
  5. Servlet学习的两个案例之网站访问次数的统计
  6. [Android]Notification汇总
  7. 通过资源名称得到资源id
  8. 计算机网络学习笔记(25. Cookie技术)
  9. 怎么查询房贷批下来没?
  10. 工作工资不高,很普通的一个我