Android Camera2之 手动点击区域对焦

引言

最近做一套基于Camera2 API的相机应用,发现有关Camera2 手动点击区域对焦的文章少之又少,无奈痛苦研究了一天手动区域对焦,终于达到理想效果。

展示一下效果:


screen.gif

有关Camera2 API的基本使用请自行Google,本文基于研究Camera2点击对焦实现基础之上,如有不足,欢迎指出。

手动对焦基本原理

我们都应该知道,手机改变焦距是通过分析摄像头拍摄二维图,并经过算法根据对焦区域来测量光度情况进行对焦。因此,Camera2中也提供了该对焦方式的API,我们只需提供基于Camera2所需的对焦区域(Rect)即可。

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

SENSOR_INFO_PIXEL_ARRAY_SIZE表示的是摄像头成像区域所使用的内存大小。

SENSOR_INFO_ACTIVE_ARRAY_SIZE表示真正接收光线的区域,因此成像的区域是该参数指定的区域,当然该矩形区域的坐标系基于SENSOR_INFO_PIXEL_ARRAY_SIZE

SCALER_CROP_REGION表示最终的输出内容是基于SENSOR_INFO_ACTIVE_ARRAY_SIZE裁剪的部分,而该值指定裁剪的区域。

image

上图灰色区域可以理解为通过 CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE拿到的区域,这个区域就是我们摄像头拍摄照片的最大分辨率(比如我的三星s8,最大分辨率为4032*3024)。

蓝色区域是通过CaptureRequest.SCALER_CROP_REGION 拿到的部分该部分经测试与*SENSOR_INFO_PIXEL_ARRAY_SIZE *拿到的区域大小是一样的。

橘黄色区域和绿色区域分别代表我们的应用界面裁剪区域。橘黄色一般为竖屏,绿色一般为横屏。这个两个部分的大小其实就是我们在设定相机预览界面时的大小,这个可以根据需要来设定。但这个区域显示在手机屏幕的时候是等比缩放的。所以我们在处理手指的点击区域时,我们需要根据预览界面相对于相机取景最大分辨率进行调整触摸坐标位置。

开始对焦

原理介绍完了,开始切入正题

首先我们需要知道,手动对焦是通过CaptureRequest.Builder的CONTROL_AF_REGIONS(控制对焦区域)和CONTROL_AE_REGIONS(控制曝光区域)来控制的。上代码(Kotlin):

mPreViewBuilder.apply{
    set(CaptureRequest.CONTROL_AF_REGIONS, arrayOf(MeteringRectangle(rect, 1000)))

    set(CaptureRequest.CONTROL_AE_REGIONS, arrayOf(MeteringRectangle(rect, 1000)))

    set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO)

    set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START)

    set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START)
}

可以见得手动对焦关键在于如何获取上述代码中的rect变量。也就是相对于整个相机最大分辨率,手指的点击区域。继续上代码(在这里我们暂只考虑竖屏情况,横屏情况参考注释):

  /**
  * 获取点击区域
  * @param x:手指触摸点x坐标
  * @param y: 手指触摸点y坐标 
  */
 private fun getFocusRect( x: Int, y: Int): Rect {
    val screenW = FontDisplayUtil.getScreenWidth()//获取屏幕长度
    val screenH = FontDisplayUtil.getScreenHeight()//获取屏幕宽度
    
    //因为获取的SCALER_CROP_REGION是宽大于高的,也就是默认横屏模式,竖屏模式需要对调width和height
    var realPreviewWidth = mPreviewSize.height 
    var realPreviewHeight = mPreviewSize.width
    
    //根据预览像素与拍照最大像素的比例,调整手指点击的对焦区域的位置
    val focusX = realPreviewWidth.toFloat() / screenW * x
    val focusY = realPreviewHeight.toFloat() / screenH * y
    LogUtil.i("focusX=$focusX,focusY=$focusY")
    
    //获取SCALER_CROP_REGION,也就是拍照最大像素的Rect
    val totalPicSize = mPreViewBuilder!!.get(CaptureRequest.SCALER_CROP_REGION)
    LogUtil.i("camera pic area size=$totalShowSize")

    //计算出摄像头剪裁区域偏移量
    val cutDx = (totalPicSize.height() - mPreviewSize.height) / 2
    LogUtil.i("cutDx=$cutDx")

    //我们默认使用10dp的大小,也就是默认的对焦区域长宽是10dp,这个数值可以根据需要调节
    val width = FontDisplayUtil.dip2px(10f)
    val height = FontDisplayUtil.dip2px(10f)
    
    //返回最终对焦区域Rect
    return Rect(focusY.toInt(), focusX.toInt() + cutDx, (focusY + height).toInt(), (focusX + cutDx + width).toInt())
}

其中cutDx变量是屏幕比例相对于摄像头剪裁区域的偏移量。因为在我的项目中屏幕是固定竖屏的,也就是说我的屏幕高度与SCALER_CROP_REGION获取的最大高度时相等的,所以只需要考虑宽度的调整。可以参考下图整理一下思路...


示例

至此,点击对焦的大部分工作均已完成。不要忘了在设置完mPreViewBuilder的手动对焦模式之后,使用setRepeatingRequest方法来实现画面的连贯加载。

本文参考:https://www.jianshu.com/p/76225ac72b56
如有不足,欢迎指出,谢谢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容