ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

三方相机人脸测光失效?touch AE抢占face AE的排查与修复

三方相机人脸测光失效?touch AE抢占face AE的排查与修复 三方相机的项目上一次让我盯了整整一周的问题就出在自动曝光策略上。客户反馈很直接预览画面里人脸亮度不对人脸框明明是有的但测光完全不理人脸额头过曝、背景正常。第一反应是face AE算法故障可一帧帧拉日志看下来算法根本没挂是AE策略压根没进人脸优先的档位。真正的元凶是三方相机在初始化阶段自动触发了一次touch AE把测光区域锁死在了屏幕某个点上face AE再强也抢不回来。这个case很有代表性我在几个不同方案商的平台上都见过类似现象值得把排查链路完整写出来。如果你也在搞Camera HAL层、三方相机兼容、或者正在被各种“AE行为异常”的bug单追着跑这篇应该能帮你少走不少弯路。1. 现场问题与现象拆解看似“人脸测光失效”其实另有玄机先还原一下问题出现时的完整画面很多时候我们太急着看代码反而忽略了现象本身能给出的信息。这次的问题描述来自三方相机App的兼容性测试报告复现机型是搭载高通平台的设备系统侧使用Camera HAL3架构。1.1 三方相机上复现出的三层异常现象我把测试报告里的异常现象翻来覆去看了几遍归纳下来是三层第一层人脸区域亮度异常。正对光源时人脸过曝高光部分直接溢出背对光源时人脸又黑成剪影。但背景的曝光是正常的天空、墙壁、桌面都处在合理曝光区间内说明整个系统的曝光能力没有坏只是测光目标选错了。第二层触控区域曝光异常敏感。用手指点击画面任意位置画面亮度会立刻跟随点击位置的亮度剧烈变化而且在点击之后整个画面的曝光策略就“粘”在了那个点上。松手后不会平滑过渡回自动模式人脸框还在但对亮度控制没有任何话语权。第三层部分三方App表现稳定部分必现。同一个设备系统相机App测试一切正常人脸测光、对焦、美颜都跟手换某个三方相机App后问题必现。这就基本把怀疑范围从底层驱动故障收窄到了三方App与HAL层策略交互的问题上。1.2 为什么第一反应要往“AE策略被抢占”方向想遇到这类问题如果只盯着“face AE失败”这几个字去找算法bug大概率会白忙一场。我的判断逻辑是这样的人脸检测框能正常出框说明人脸检测模块、ISP的人脸信息上报链路是通的。既然人脸信息能送达AE算法模块那“算法拿不到人脸”这个假设不成立。剩下的可能性是“算法拿到了人脸但同时拿到了更优先的touch信息”策略上touch AE压过了face AE。这个推断在三方相机的特殊背景下尤其合理。系统相机App通常有完整的人脸优先策略会主动把face AE相关的region正确传给HAL而三方相机App的API调用习惯千奇百怪很多App会在初始化或预览启动阶段自动设置焦点区域和测光区域相当于在用户没有任何感知的情况下替用户执行了一次“点击屏幕”的操作。1.3 先排除最基础的三类干扰项在进入深层排查之前我建议先把下面三件事做掉别嫌基础三分之一的“face AE失败”其实是这三类问题伪装的一是检查三方相机App的预览分辨率是否触发了我方sensor的binning重新配置。部分sensor在切分辨率时会重新下发曝光参数如果三方App在这时读到了旧参数并作为手动曝光基准看起来就很像AE不跟脸。区分方法很简单打开log看sensor的exposure time有没有随着画面亮度变化。二是确认拉流通道是否真的走了三方App自己设置的manual exposure。不少三方App支持手动曝光滑杆如果App在前台恢复时没有正确重置manual flagHAL会一直停留在manual AE模式跟touch、face都没关系。查一下metadata里的android.control.aeMode如果是OFF或者手动模式那压根不是策略抢占问题。三是人脸检测库是否在三方App进程内被降级。部分三方App会自带人脸检测算法并且把检测结果缓存后重新注入给PreviewCallback。如果注入的face信息格式不对或者滞后HAL层AE看到的人脸框是过期位置测光自然不准。三类干扰项确认排除之后我终于能安心进入主战场touch AE与face AE的优先级博弈。2. AE策略的博弈规则touch AE为什么能“碾”过face AE要理解这个bug的本质得先跳出“AE是个算法”这个思维把AE当作“一堆测光区域在抢话语权”的博弈过程。我在排查时习惯画一张抽象的权重图把所有测光输入源画成一块块带权重的区域看最终谁占领了AE算法的决策中心。2.1 曝光算法眼里没有“人脸”只有权重图先搞清楚AE算法的输入。从HAL3角度上层App会通过CaptureRequest携带若干与测光相关的metadata核心是android.control.aeRegions它是一个由坐标区域和权重组成的列表。ISP的3A统计模块会按这些区域的坐标去统计亮度、对比度等数据然后喂给AE算法去计算目标曝光时间、增益、光圈。人脸信息理论上也是一样的HAL层拿到人脸检测结果后会把人脸框转换成一组aeRegions叠加高权重告诉AE算法“这边亮度最重要”。所以算法眼里根本没有“人脸”这个概念只有一块矩形区域以及一个权重值。这就能解释为什么touch AE能赢如果三方App在touch发生时给了HAL一个区块权重极端的aeRegion比如权重值拉到最高而HAL自身的人脸检测权重是中等水平那么在AE算法的加权统计里touch区域对最终亮度的贡献占比会远超人脸区域算法计算出的目标亮度当然优先满足touch区域的亮度水平。2.2 touch region与face region的合并优先级每家平台的3A库对touch region与face region合并都有自己的策略但行业里比较常见的做法是两类一种是touch优先覆盖。用户手动点击屏幕被视为最高优先级交互一旦系统收到touch event对应的AE region立即以该region作为主要测光依据人脸region暂时降级或被移出计算。这种设计的出发点是“交互优先”用户都指了就不能忽略用户意图。但问题也出在这如果是一次误触或程序自动模拟的touch用户自己都不知道自己“指定”了哪里。另一种是area加权融合。touch region、face region、自动全局region同时参与统计权重不同。如果face权重足够高且face出现在touch区域附近算法会自动倾向人脸测光。这种设计对算法要求高很多平台默认并不开启或者只在特定AE策略档位才启用。这次出问题的平台明显属于第一种touch一旦被激活face AE就彻底出局。而三方App唤醒touch的方式又太隐蔽才酿成了这个bug。2.3 三方相机“自动触发touch”的两条典型路径排查过程中我发现三方App触发touch AE的路径有两条都很隐蔽路径一是App在启动预览时默认建立焦点和测光点。很多三方相机App为了体现“专业感”会在预览初始化时往CaptureRequest里塞一个默认的aeRegions和afRegions一般是屏幕中心点带一个半径region data的权重也会填满。对App来说这是“默认对焦中心”但对HAL来说这就是一次标准的touch AE触发AE策略切换到touch优先模式从此face AE被架空了。路径二是App在预览线程里周期性地检测人脸一旦检测失败就自动重置“焦点回到画面中心”。这个逻辑本身是App内部做对焦辅助用的本意是“找不到脸就对焦画面中心”但实现时直接把aeRegions也一起重置了。等于App每隔几帧就给HAL发一次touch AE的regionface AE的权重再怎么拉也没戏。这两条路径我称之为“程序化touch”区别于“用户意图touch”。它最大的坏处是UI上用户看不到任何手指点击痕迹系统相机测试又一切正常只有三方相机的自动逻辑在背后悄悄改变测光策略。3. 从回归测试到复现稳定触发touch AE的操作序列排查这种问题最忌讳的是一边试着复现一边抓log操作节奏和抓log时机对不上很容易漏掉关键信息。我在这个case里花了半天时间设计了一套稳定复现流程分享出来你可以直接拿去用。3.1 最小复现路径预览启动后立刻点击画面测试发现这个问题有一个非常稳定的触发操作序列第一步冷启动三方相机App进入预览界面。此时不要做任何操作先观察3-5秒记录人脸亮度是否正常。在这个阶段部分三方App已经会在启动时发送默认aeRegion所以即使什么都不做问题也可能已经出现。第二步如果第一步未触发用手在屏幕任意位置单击一下模拟用户正常的对焦操作。点击后观察画面亮度变化正常情况下画面会有一个短暂的曝光收敛过程然后稳定下来。第三步点击后等待至少10秒期间让人脸在画面中缓慢移动观察人脸区域亮度是否发生变化。如果人脸亮度和画面亮度只跟随点击点亮度变化不跟随人脸移动基本就锁定是touch AE锁区问题。第四步退出App重进再连续快速多次点击屏幕不同位置。这一步是为了模拟三方App内部“焦点重置”逻辑验证“粘滞”程度。这个序列在bug触发率高的版本上基本两步就必现不用走完全部流程。3.2 抓取关键日志的准备工作复现之前日志抓取要提前配置好等复现再开log基本来不及。我在这个场景下准备了三类日志源第一类是HAL层3A日志。不同平台开关有差异高通平台一般开CamxOverride或camxoverridesettings.txt里的log开关重点关不掉信息层级把3A状态机的切换和AE region的变更打出来。我一般把OverrideLogLevel调到1再单独开logCamx3ALog相关选项。第二类是metadata关键项的dump。用系统工具周期性打印每帧CaptureResult里的android.control.aeRegions、android.control.afRegions、android.statistics.faceIds、android.control.aeState一帧一帧看这些字段的交替变化能非常清晰地还原出策略演进过程。第三类是App侧的调用轨迹。这一步在三方App没有源码的情况下有点难但如果是自家三方App或者能拿到合作方联调权限建议在App的CameraDevice相关调用点打trace记录每次createCaptureRequest、setRepeatingRequest时的参数尤其要盯aeRegions有没有被打包进去。3.3 日志里判定“touch AE已生效”的四个特征点抓到日志后怎么一眼认定touch AE已经接管我总结了一套判断特征对上两条基本就可以锤实特征一aeRegions的值出现了一个非全幅的集中区域且该区域坐标对应屏幕中心或最近一次点击位置权重数值明显高于周边。自动模式下的aeRegions通常是全幅覆盖(0,0,width,height)出现这种小方块就意味着有外部触达。特征二aeState状态机在IDLE、SEARCHING、CONVERGED之间循环变化但收敛后的曝光参数长期围绕touch区域亮度波动。如果人脸亮度信息和曝光参数走势出现背离比如人脸的Y值统计在涨但曝光时间没有相应下降说明算法根本没采纳人脸统计。特征三faceIds虽然一直有检测到人脸但hAL层的faceAeMode或对应的aeRegions更新频率突然降低。很多平台会做人脸追焦优先策略如果人脸框坐标一直在变化但aeRegions纹丝不动大概率人脸测光路径已被截断。特征四在touch发生的前后两帧CaptureResult里有明显的一次aeRegions跳变然后该region持续存在数十帧没有被替换。这就是“程序化touch”粘滞期的直接证据。我这次定位就是靠特征一和特征四锁定的App在启动预览时确实发送了一个默认aeRegion并作为重复请求持续持有一直没释放。4. 排查链路全记录从HAL日志一路追到三方应用API调用有了稳定复现方法和日志抓手排查就是按图索骥。这个case的排查链路我当时走了整整一轮从怀疑HAL策略bug到定位App逻辑问题中间有不少弯路拆开说更有参考价值。4.1 第一次定位确认AE状态机卡在touch模式复现问题后我首先把HAL的3A状态机日志拉出来一帧帧对照。结果非常直观在App进入预览的第一百帧左右aeState开始持续处于CONVERGED状态aeRegions固定在一个大约占全画面五分之一面积的中心区域随后无论人脸在画面内如何移动该region都没有任何位移。这个现象可以排除平台侧的人脸检测链路问题——因为在我把手指从屏幕上移开、没有做任何新touch操作的情况下region居然还能保持几十帧不动。这说明它已经处于一个被持续应用的状态很可能来自repeating request里的持续参数。此时我对问题根因的判断是HAL侧AE策略在处理“重复请求携带的touch region”时没有区分用户主动touch和App自动设置的region错误地把App的默认设置当成了用户在触摸屏幕。我当时甚至一度怀疑是否要给HAL加补丁让它在Face AE优先级下忽略某些touch region。但继续深挖下去发现HAL只是忠实地执行了上层指令真正越界的是上层。4.2 缩小嫌疑范围区分HAL侧主动触发与APP侧被动触发为了厘清责任边界我做了两组对比实验实验一用系统相机App开启预览手动点击屏幕看aeRegions是否同样固定不动。结果系统相机的touch region在点击后持续几帧会随人脸移动重新调整而且一旦检测到人脸touch region会被替换成face region。这说明平台HAL本身具备touch到face的切换能力。实验二回到三方相机App在预览启动后用adb命令手动清除预览线程的touch状态观察aeRegions是否恢复。这一步在App不做改动时很难直接做但我换了个思路通过CameraDevice的测试接口向同一通道发送空aeRegions的重置请求结果参考帧恢复正常人脸测光立即恢复。这进一步证明问题不在HAL的算法能力上而在于HAL收到的是来自App的持续touch指令。到这里嫌疑重心已经从HAL转移到三方App的API调用序列上。4.3 最终确认搜寻APP层调用栈找touch AE发明者要彻底证实就要拿到App层的调用证据。我和合作方App团队联调在他们的调试版本里加了一行关键日志每次构建CaptureRequest时打印aeRegions的来源标记。整个调用栈很快暴露了问题App在PreviewCallback里维护了一个FocusAreaManager单例该对象在onPreviewOrientationChanged和onSurfaceTextureAvailable两个回调里都会执行focusToCenter()函数。这个函数会把默认对焦区域设置到画面中心同时顺手把aeRegions也设成了同样区域。更致命的是这个focusToCenter()不仅在用户行为时调用在App检测到人脸丢失时也会自动调用。App的逻辑本来是“人脸丢了对焦回到中心避免拉风箱”但由于AE区域跟着AF区域一起重置了HAL层面瞬间就出现了一个权重极高的中心touch region。后续即使人脸重新出现在画面中App也没有再执行一次“人脸优先的aeRegion替换”逻辑。所以整个链路是App在某个时刻因为人脸丢失自动调用了focusToCenter触发了touch AE此后face AE策略被HAL搁置。用户从头到尾没有触碰屏幕却完美复现了touch AE霸屏的现场。5. 根因确认与双端修复方案根因清晰后修复方案反而要谨慎设计。这个问题横跨App层和HAL层单改一端可以解决表象但双端一起改才能避免同类问题换个马甲再回来。5.1 根因一句话总结三方相机App在自动对焦辅助逻辑中没有区分AF region和AE region的语义人脸丢失时把对焦区域和测光区域一起重置到画面中心导致HAL层AE策略误判为用户touch AE压制了face AE的测光权重。5.2 App侧修复初始化阶段去掉默认focus/touch设置App侧的修复核心是剥夺自动逻辑里对AE region的“误设”能力。具体来说有三个改动点第一focusToCenter()函数只管AF region不再设置aeRegions。AE region交给AI算法或系统自动策略去填App不要主动代劳。第二onPreviewOrientationChanged回调里把原来的“重置对焦测光”改成“重置对焦AF 通知HAL保持AE自动模式”。操作方式是重新发一个空白aeRegions请求全幅、权重均匀分布让AE算法恢复到自动统计全画面的模式再叠加HAL的face AE权重。第三人脸丢失后的自动对焦补偿逻辑收敛到AF的search模式即可不做任何AE干预。如果有人脸丢失后画面确实会过曝或欠曝那是AE自动收敛的临时过程可以在UI层等待1-2秒再判断不用App强制干预。App侧的代码逻辑改成下面这样是我实际验证有效的一种写法private void focusToCenter() { // 只构建AF region不携带AE region MeteringRectangle[] afRegion {new MeteringRectangle( centerX - size, centerY - size, size * 2, size * 2, MeteringRectangle.METERING_WEIGHT_MAX )}; CaptureRequest.Builder builder session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); builder.set(CaptureRequest.CONTROL_AF_REGIONS, afRegion); // AE REGIONS 交给系统自动策略不在此处设置 builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); repeatingRequest builder.build(); session.setRepeatingRequest(repeatingRequest, callback, handler); }注意这里一定要把CONTROL_AE_MODE明确设成CONTROL_AE_MODE_ON而不是依赖默认值。部分平台如果上次手动模式残留光重置region不够得连模式一起重置。5.3 HAL侧兜底对touch region与face region的合并策略做保护App侧修了HAL侧也不能只当甩手掌柜。三方App生态太杂总会有App不按正确姿势调用API。作为平台侧合理的兜底策略是允许上层设置touch region但只能在user interaction的上下文中生效而不是对每一帧repeating request无条件生效。业界有一个可行的兜底方案是在HAL的AE策略里引入“touch region生命期”的概念。我在这类平台上的实践做法是将repeating request里携带的aeRegion标记为“软Touch”记录首次出现的帧号。如果在后续N帧中我推荐取30帧即大约0.5秒没有检测到新的负面事件比如touch region坐标没变、权重大小没变HAL自动把aeRegion降权恢复face AE优先。如果检测到face region与touch region有重叠区域且face region置信度较高则直接采用face region作为主测光区。这个方案的实现难度主要在HAL层需要维护一小段状态机属于中等改动量。但在三方相机兼容性测试里它能兜住大部分“App误设aeRegion”的坑性价比不错。伪码逻辑大致如下// 在AE策略更新中为每帧的touch region计算优先级 int AeStrategy::getRegionPriority(camx::ChiRegion touch, camx::ChiRegion face) { if (face.valid hasTouchRegionLastFrames(30)) { // 若touch region长时间未变化认为它是程序设定而非用户交互 if (isTouchRegionStatic(touch)) { if (isRegionOverlapping(touch, face)) { return FACE_REGION_PRIORITY; } return TOUCH_REGION_DEGRADED_PRIORITY; } // 若是新近变化的touch用户交互痕迹明显保持touch优先 return TOUCH_REGION_ACTIVE_PRIORITY; } if (face.valid) { return FACE_REGION_PRIORITY; } return AUTO_REGION_PRIORITY; }HAL侧兜底的意义在于就算App没改恶意或误设的aeRegion也会在几十帧后自动失去优先级face AE能自动恢复。对于做平台的团队这层兜底建议早做。5.4 修复后的验证矩阵修复完别急着提测要跑一轮完整的验证矩阵至少覆盖这些场景系统相机App人脸测光回归确保HAL侧改动没有影响系统相机的正常touch-face切换体验。三方相机App正常点击屏幕用户主动touch应该仍然生效AE快速响应点击位置亮度变化这是产品功能底线不能因为兜底策略把用户主动touch废掉。三方相机App人脸丢失后自动恢复场景模拟人脸出画再入画观察aeRegion是否能在500ms内切换回人脸区域。连续点击屏幕人脸移动混合场景验证HAL状态机不会在用户快速交互时误判为“程序化touch”。弱光、逆光等极端光场确保降权后的touch region不会让画面出现整体亮度震荡。我跑完这组矩阵大约用了两天主要是连续点击人脸移动混合场景里发现一个针对“用户快速滑动手指”的误判用户滑动时touch region坐标持续变化我的静态判断逻辑会把它识别为活跃touch没问题但如果用户点完立刻把手移开屏幕且App没有再发新region老的region会被当成静态touch。解决办法是在App侧修复的基础上HAL的静态判定阈值调到30帧这个case基本稳定通过。6. 这类face AE问题的通用排查模板与踩坑经验写完这个case的完整链路我把一些可以复用的排查经验抽出来做成模板直接贴在这儿。以后再遇到“face AE失败”“测光不跟脸”“曝光异常”这类bug单从上往下对着查能省很多时间。6.1 排查Checklist可以直接抄先别碰代码先看现象人脸框是否能正常显示Touch画面时曝光是否即时响应换系统相机App是否复现拉HAL的3A log重点对以下几帧预览启动帧、touch发生帧、touch结束帧、人脸状态变化帧。dump至少100帧的aeRegions faceIds观察region是否长期固定是否与touch坐标强相关。查App调用链App是否在PreviewCallback里重置过AE/AF区域是否在焦点丢失时修改了aeRegion是否在某个回调里反复发送“repeating request带aeRegion”跑到第4步还没定位把问题分层是HAL策略bug、App逻辑bug、还是三者之间的交互时序冲突修完必须跑混合交互矩阵不要只测单一场景。6.2 几个容易误判的细节有几个判断细节我踩过坑单独说一下细节一App设置了aeRegion不代表一定touch优先。部分平台会把aeRegions拆成多段App设置的region可以是很低的权重跟全幅region并存。所以别看到aeRegion非空就急着定性要去看权重值和区域面积占比评估它对AE算法的实际影响力。细节二face AE不是只有人脸检测到就一定会启用。不少平台的人脸测光策略需要满足两个条件才真正进入face优先一是faceId连续N帧稳定二是人脸框的面积占比超过某阈值。三方App如果把人脸框强行缩放得很小HAL会认为人脸太小不值得优先测光。这个流程和touch AE的冲突其实可以共存人脸框太小本身就不该触发face优先此时touch优先是正确的行为。排查时先区分“该不该face优先”和“能不能face优先”。细节三三方App的背景虚化模式最容易把AE策略搞乱。很多三方相机App开启人像虚化时会从afMode切换到AF_MODE_OFF并且将aeMode切到MANUAL同时设置一组人工定义的曝光参数。这种模式下主控权根本不在HAL的AE策略手里face AE自然失效。查问题前先看aeMode是不是被App锁死在manual或者external mode别在错误的分支里浪费几小时。6.3 与外接相机/网络相机联合调试时的特殊注意顺着热搜词里外接相机的方向多说一嘴。如果你用的三方相机不是手机内置摄像头而是通过USB或者网络协议接入的外接相机这类问题还会多一层特殊坑这些外接相机的固件往往内置了一套自己的AE逻辑它自己会做人脸检测和曝光控制不care你做不做face AE。所以排查外接相机的“touch AE导致face AE失败”要分两部分看如果人脸测光逻辑跑在外接相机的内置DSP里App层设置的所有aeRegions都只是“建议值”最终曝光由相机固件决定。此时真正要查的是外接相机的配置比如NDI类网络摄像机需要确认它自己的曝光策略是否处于全自动、是否允许外部触发点测光、点测光后是否会自动恢复。这类场景下HAL层的日志不一定能看到真正的AE决策反而要看摄像头固件的设置项和它有导出的事件日志。如果你在调NDI HX Camera这类设备注意它通常会把exposure和AE模式映射为ONVIF或厂商私有协议字段App一旦写了touch坐标固件自带的行为是锁定该区域的测光权重直到收到“clear area”指令。很多设备是没有“自动超时恢复”的真出了bug只能靠App周期重置。我个人在实际操作中的体会是这类问题排查到后期最大的敌人不是技术而是耐心。AE策略的切换涉及人脸检测、touch事件、App状态机、HAL状态机四条线的交错影响每一帧日志背后都是多方状态的实时博弈。下次如果你也追了几天还在原地打转建议退一步把人当机器把操作流程固定下来把日志定义清楚问题往往就自己浮出来了。
返回列表