CTSV相机FOV标定失败排查:HAL焦距与传感器尺寸修正

发布时间:2026/10/28 16:03:23
CTSV相机FOV标定失败排查:HAL焦距与传感器尺寸修正

GMS 认证跑到 CTSV(CTS Verifier)手动测试环节,最容易卡人的项之一就是 Camera FOV Calibration。它不像那些自动化用例跑完直接出个结果,而是得有人把机器摆好、对着靶标拍一张、再读判定——中间任何一个环节偏一点,结果就是 failed。我第一次碰到 Camera FOV Calibration failed 的时候,第一反应是“相机拍照明明好好的,怎么可能不过”,然后花了大半天时间在环境和摆位上来回折腾,最后才发现是 HAL 层上报的焦距参数压根就是模组规格书上的标称值,跟实际成像光路差了一截。

这篇东西就是围绕这个场景展开的:一个做 Camera HAL/驱动/认证的工程师,在 CTSV 里跑 Camera FOV Calibration 挂掉之后,该怎么一步步把问题从“测试没过”收敛到“哪个参数错了、错多少、改哪儿”。内容包括这个测试项到底在验什么、FOV 在代码里是怎么算出来的、手动测试的完整操作细节、失败后的分层排查路径,以及参数修正和回归验证的做法。不管你是刚接手认证测试的新手,还是已经跑过几轮想补一补原理的老手,都能从里面拎走可以直接用的东西。

1. 拆解标题:这个测试到底在验什么

1.1 从认证流程看这个测试项的位置

CTSV 是认证流程里专门承接“自动化测不了”的那部分,相机就是重灾区。自动化的 CTS 能验 API 行为、能验输出格式、能验 metadata 的字段类型和取值范围,但它没法验“你上报的这个焦距是不是真的”。因为焦距、传感器物理尺寸这类参数,本质上是从模组规格书和光学设计里搬过来的静态数据,测试框架没有任何办法从一张照片里反推出来——除非它自己拍一张已知场景,然后算。

Camera FOV Calibration 干的就是这件事。它让被测设备在受控的几何条件下拍摄靶标,通过图像上标记点的位置反推实际视场角,再跟设备通过CameraCharacteristics上报的LENS_INFO_AVAILABLE_FOCAL_LENGTHS和SENSOR_INFO_PHYSICAL_SIZE推算出来的理论 FOV 做比对,偏差超过阈值就判 fail。说白了,它验的不是“你能不能拍照”,而是“你告诉应用的那套光学参数,是不是真的”。

这个区别很关键。很多团队第一次接触会把它当成一个功能测试,觉得画面正常、对焦清楚就该过;实际上哪怕画面完美,只要上报的参数和实际光学不符,照样 fail。反过来说,参数是对的,但摆位歪了、光照不对、靶标识别偏了,也一样 fail。所以这个测试项天然有两个失败面:一个是数据面,一个是操作面。后面所有的排查,都是在这两个面之间做区分。

还有一点容易被忽略:多摄设备上,这个测试通常是按 camera id 逐个来的。主摄过了不代表超广角能过,超广角的畸变更大、边缘标记点更容易识别偏,往往是整轮测试里最后卡住的那个。所以第一遍跑的时候,建议把所有 camera id 的测试结果都记下来,看看是普遍性失败还是个别模组失败——这个信息对后面定位根因的价值极高。

1.2 FOV 的数学来源:一条从光学到 API 的链路

要把失败原因说清楚,得先把 FOV 是怎么算出来的捋一遍。标准的薄透镜近似下,水平视场角的表达式是:

FOV_h = 2 * atan( W / (2 * f) )

其中W是传感器在水平方向上的有效成像宽度,单位毫米;f是有效焦距,单位毫米。垂直方向同理,把W换成有效成像高度H。对角线方向则用对角尺寸。三个值算出来通常不相等,因为传感器很少是正方形。

举一组具体数字:假设某模组的传感器物理尺寸上报为 5.645mm × 4.229mm,焦距上报 4.71mm,那么:

import math W, H = 5.645, 4.229 # mm,传感器有效成像尺寸 f = 4.71 # mm,有效焦距 diag = math.hypot(W, H) for name, dim in (("水平", W), ("垂直", H), ("对角", diag)): fov = 2 * math.degrees(math.atan(dim / (2 * f))) print(f"{name} FOV = {fov:.2f}°")

跑出来大约是水平 61.86°、垂直 48.36°、对角 73.66°。这三个数字就是框架认为“你应该看到的世界范围”。测试时设备实际拍到的范围如果明显比这个小,说明要么真实焦距比上报的长,要么有效成像区域比上报的窄。

这里有个特别容易踩的点:W和H必须是实际参与成像的那块区域的物理尺寸,不是整块硅片的尺寸。如果设备在输出某种分辨率或宽高比时做了裁剪,比如 4:3 的 sensor 输出 16:9 时上下各切掉一部分,那垂直方向的有效高度就变了,垂直 FOV 自然跟着变。Camera2 里SENSOR_INFO_PHYSICAL_SIZE描述的是全像素阵列的物理尺寸,而SENSOR_INFO_ACTIVE_ARRAY_SIZE描述的是当前可用的像素区域,两者之间还有一层SCALER_CROP_REGION。这三者任何一处理解错,算出来的理论 FOV 就会和实际对不上。

所以链路是这样的:模组光学设计给出真实焦距和像面尺寸 → 模组厂标定报告(或 EEPROM 里的标定数据)→ vendor 相机配置文件 → HAL 填充CameraCharacteristics→ framework 暴露给应用 → CTSV 读取并计算 → 与实际拍摄结果比对。中间任何一环的数据被“估”“抄”“凑”,最后都会在这一步暴露出来。

1.3 失败意味着什么:三类根因分野

看到 failed 之后,先别急着改代码。我的习惯是先把它归到三类里,因为这三类的处置路径完全不同。

第一类是环境与操作类:靶标距离不对、机器摆歪了、光照不足或有频闪、靶标识别失败、拍摄时手抖了。这类问题的特征是复现性差,同一台机器连续跑三次可能一次过两次挂,或者换个工位结果就变了。

第二类是数据类:HAL 上报的焦距或传感器尺寸不准,或者上报的是等效值、标称值、理想值。这类问题的特征是复现性极好,同型号机器全都一样地挂,而且偏差方向往往一致——要么总是实测偏小,要么总是实测偏大。

第三类是成像链路类:OIS 没归中、EIS 开着、拍摄瞬间切了物理相机、对焦距离太近导致 focus breathing、广角畸变太大导致标记点位置反算偏差。这类问题的特征是跟具体模组和具体配置强相关,换个体位或者关掉某个 feature 结果就变了。

这三类的区分方法很简单:换一台同型号机器复测。如果另一台也一模样地挂,基本可以排除操作类;如果另一台过了,那大概率是这台机器的摆位或环境问题,或者这台机器的模组个体差异。这一步花不了十分钟,但能省掉后面一半的瞎猜。我见过太多人一上来就怀疑 HAL,结果折腾两天发现是支架上那个靶标卡片没贴平。

2. 测试前的环境搭建与前置自检

2.1 硬件摆位:距离、角度与光照的三个硬约束

CTSV 的 Camera FOV Calibration 在界面上会给出靶标摆放的指引,不同版本的具体交互和靶标形式会调整,所以以界面指引为准是第一原则。但不管哪个版本,背后的三个物理约束是不变的:距离要够远、光轴要垂直、光照要均匀。

距离要够远,是因为薄透镜公式里的f是无穷远对焦时的有效焦距。实际拍摄时如果对焦距离太近,镜组为了合焦会整体前移,等效焦距变长,视场角变小,这就是所谓的 focus breathing。大部分手机模组在 40cm 以外 focus breathing 的影响已经很小,但在 20cm 以内就很明显了。所以测试距离不能为了“让靶标填满画面”而一味拉近,得按界面给定的距离来。如果界面没给明确数值,我一般会在保证靶标完整入画的前提下尽量拉远,同时用LENS_INFO_MINIMUM_FOCUS_DISTANCE反查一下该模组的最近对焦距离,确保测试距离远大于它。

光轴要垂直,意思是设备屏幕平面(也就是 sensor 平面)要和靶标平面平行。倾斜带来的误差是系统性的:往一个方向倾,一侧的标记点在图像上的投影位置就整体偏移,反算出来的 FOV 会偏大或偏小。用水平仪或者带角度刻度的支架最省事,没有的话就靠靶标四角的对称性判断——如果拍出来的图像里靶标明显呈梯形,那就是没摆正。

光照要均匀,这一条被低估得最多。室内常用的 LED 灯有频闪,卷帘快门在某一帧里拍到的可能是一半亮一半暗,靶标上暗的那部分标记点识别不出来,反算出来的角度就会偏。我的做法是把设备切到手动曝光模式(如果测试界面允许),或者干脆在漫射自然光或者直流供电的柔光灯下测,避开廉价 LED 面板灯。曝光过度同样致命,靶标上的白色区域一旦过曝糊成一片,标记点位置就废了。

2.2 软件版本与测试配置对齐

硬件摆好了,接下来是软件侧。CTSV 本身是个独立安装的 APK,版本必须跟当前认证目标版本对齐——用错版本的 CTSV 跑出来的结果,测试机构和认证流程都不认。安装之后先确认设备上装的是对应版本,别拿旧的凑数。

设备侧有几个设置会影响结果,上机前建议统一确认一遍。一个是屏幕常亮和锁屏,测试过程中锁屏会导致 Activity 被切走,测试中断。一个是自动亮度,虽然理论上不影响相机,但某些平台的亮度调节会连带影响功耗策略,进而影响相机帧率,属于不必要的变量。还有就是开发者选项里的“不保留活动”,这个开着会导致测试界面反复重建,进度丢失。

第三方相机应用的干扰也要考虑。有些预装或后装的应用会注册相机相关的广播或者在后台持有相机,虽然正常情况下一台干净的认证样机不该有这些,但如果是工程机,装了一堆调试工具,就得提前清一遍。最直接的办法是测试前把非必要应用全卸了,或者直接刷一版干净的认证软件。

还有一项是相机本身的配置开关:EIS、OIS、美颜、HDR、夜景模式这些 feature,在测试前应该全部处于关闭或者默认状态。CTSV 的 FOV 测试走的是标准 Camera2 路径,理论上不受这些影响,但实际项目里我确实遇到过 EIS 开启导致画面被裁切、进而实测 FOV 偏小的情况。稳妥起见,测试期间把这些都关掉,等过了再单独验功能。

2.3 上机前的十分钟自检清单

跑之前花十分钟把下面这些过一遍,能省掉大量无效返工。

  • 设备是否已经刷入待认证的软件版本,版本号有没有记错
  • CTSV 版本是否与目标认证版本对齐
  • 目标 camera id 是否确认,多摄设备是否列全了所有需要单独上报的物理相机
  • 靶标是否平整、有无折痕、有无反光、是否按指引的尺寸打印
  • 支架是否水平,设备是否牢固,拍摄时不会因为按屏幕而位移
  • 环境光是否均匀、是否避开 LED 频闪、是否没有强光源直射镜头
  • EIS/OIS/HDR/美颜等 feature 是否已关闭
  • 设备电量是否充足(低电量策略可能限制相机性能)
  • 是否有其他应用持有相机

这张清单里我觉得最值得单独拎出来说的是靶标平整度。打印出来的图卡如果贴在硬纸板上没贴平,中间鼓起或者边缘翘起,图像上标记点的实际位置就和理论位置有偏差,而这个偏差会直接变成 FOV 计算误差。我吃过这个亏,当时一直以为是 HAL 参数错了,来回改了两轮配置,最后换成一块亚克力背板贴平,一次就过了。

3. 手动测试的完整实操流程

3.1 进入测试项与界面阅读

CTSV 的测试项是按大类组织的,Camera 相关的在对应分类下。进入之后会列出当前设备的各个 camera id,需要逐个选择测试。这一步别偷懒,把所有 id 都过一遍,哪怕你确信只有主摄有问题——因为如果逻辑相机把多个物理相机的参数聚合上报,主摄过了不代表聚合后的结果也对。

选中某个 camera id 之后,界面一般会先给一段说明,讲清楚靶标怎么摆、距离多少、点击哪里开始。这段说明值得认真读一遍,尤其是里面关于容差和判定方式的描述,不同版本之间会有调整。我习惯在第一次跑某个版本的时候把这段说明截个图存着,后面遇到争议可以直接对照,不用重新翻。

界面进入预览之后,通常会显示取景画面。这时候先别急着点拍摄,先在预览里确认几件事:画面里靶标是否完整、四个角都在、没有明显倾斜、没有过曝或欠曝的死白死黑区域、对焦是否已经合上。预览阶段能看出来的问题,就不要带到拍摄阶段去。对焦这一项尤其要注意,有些模组在近距离下会自动切到微距模式,此时镜组位置和无穷远状态差别很大,拍出来的 FOV 会明显偏小。如果预览里能看到对焦在“抽”,那就是环境光不足或者对比度不够,得先解决光照。

3.2 摆位、对焦、拍摄的操作细节

摆位这一步,我的做法是分两段调。先调距离,把设备沿光轴方向推到靶标大致填满画面但四边还留余量的位置,锁定支架。再调角度,用靶标四边在画面里的对称性来判断——让上下边到画面边缘的距离相等、左右边到画面边缘的距离相等,基本就正了。如果有条件,用带刻度的云台会快很多,但手动调也完全够用,只是需要多对几次。

对焦要确认合焦在靶标平面上,而不是合在支架或者背景上。如果测试界面支持点击对焦,就在靶标中心点一下;不支持的话,靠自动对焦收敛后等一两秒再拍。有些模组在低照度下 AF 会反复搜索,这时候拍的瞬间可能正好在对焦行程中间,焦距不是最终值,FOV 就有偏差。判断方法是连续拍两张对比,如果两次结果差得多,那基本就是对焦没锁定。

拍摄瞬间的稳定性也很重要,尤其是设备架得比较高的时候。用手按屏幕上的拍摄按钮,力会传到支架上,画面可能轻微抖动,虽然单帧拍摄理论上不受运动模糊影响太大,但如果靶标识别对清晰度敏感,抖动就会带来误差。我的习惯是用定时拍摄(如果有)或者用耳机线控/蓝牙快门,避开直接触碰设备。

拍完之后如果界面给出结果,先看数值再下结论。判定通常看的是实测值和上报值的相对偏差,我见过的几个版本里,水平垂直两个方向的偏差都控制在 3% 以内才算比较可靠,卡在边缘的结果复测经常翻车。所以哪怕显示通过了,如果余量很小,我也会再跑一遍确认可复现性——认证现场环境未必跟你实验室一样,留点余量比什么都强。

3.3 结果判读与现场取证

failed 之后别急着退出,先把现场信息固定下来,这些东西是后面排查的依据。

第一是界面上的具体数值:实测 FOV 是多少、理论 FOV 是多少、偏差百分比是多少、是水平方向超还是垂直方向超、还是两个都超。这个信息量极大——如果只有垂直方向超,那大概率跟裁剪或宽高比有关;如果两个方向同比超,那多半是焦距的问题;如果两个方向偏差方向相反,那可能是靶标识别或畸变的问题。

第二是当时的现场状态:拍摄距离、光照条件、靶标版本、支架角度、设备型号和软件版本。这些看着琐碎,但等你过两天回头复现的时候,没有记录基本等于重来。

第三是设备侧的参数快照。测试前和测试后各抓一次dumpsys media.camera的输出存下来,方便对比。命令很简单:

# macOS / Linux adb shell dumpsys media.camera > camera_dump_before.txt # Windows adb shell dumpsys media.camera | findstr /C:"Focal length" /C:"Pixel array" /C:"Physical size"

完整 dump 里有该设备所有 camera id 的静态元数据,包括焦距、像素阵列尺寸、物理尺寸、可用分辨率等等,是排查数据面问题的第一手材料。

取证做完,就可以退出测试项,进入排查环节了。这一步多花五分钟,后面能省五小时。

4. 失败排查:从现象反推根因

4.1 先排除环境与操作因素

排查顺序我坚持从外到内:先证明环境和操作没问题,再动数据。因为数据改动成本高、风险大,而环境问题是可以通过复测快速排除的。

最有效的动作是原地重跑三次。如果三次结果分散很大,说明测试本身不稳定,问题在环境或对焦,不在参数。如果三次结果高度一致地 fail,那基本可以认定是系统性问题,继续往下查。这个动作五分钟就能做完,信息量却最大。

重跑通过的话,再换一台同型号机器测。两台都过,说明原来那台是摆位或个体问题;两台都挂且数值接近,说明是软件配置问题;两台都挂但数值差很多,那可能是模组个体差异加上配置问题的叠加,比较麻烦,需要先统一到同一版配置再测。

环境因素里我最常遇到的两个:一是靶标贴得不平,二是光源频闪。前者靠换硬背板解决,后者靠换光源或者拉长曝光时间解决。还有一个隐蔽的是支架的金属件反光,强光打在支架上反射进画面,靶标局部过曝,标记点识别偏位。这种情况把支架用哑光黑布遮一下就好。

操作因素里最常遇到的是拍摄瞬间设备位移。尤其是把手机夹在简易支架上的时候,按屏幕的力会让机身轻微俯仰,虽然角度变化可能只有零点几度,但 FOV 计算的容差本来就窄,零点几度足够把结果推出边界。改用定时拍摄能彻底解决这个问题。

4.2 再查 HAL 上报的标定参数

环境和操作都排除了,就开始看数据。核心就两个值:LENS_INFO_AVAILABLE_FOCAL_LENGTHS和SENSOR_INFO_PHYSICAL_SIZE。

读这两个值最直接的办法是在设备上跑一小段代码,或者从dumpsys输出里翻。用 Camera2 接口读的话大概是这样:

CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); for (String id : manager.getCameraIdList()) { CameraCharacteristics c = manager.getCameraCharacteristics(id); float[] focal = c.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS); SizeF physical = c.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE); Rect active = c.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); Size pixelArray = c.get(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE); Log.d("FOV", id + " focal=" + Arrays.toString(focal) + " physical=" + physical + " active=" + active + " pixelArray=" + pixelArray); }

拿到这些值之后,和模组规格书、模组厂标定报告逐项对照。对照的时候有几个高频错误模式,我按出现频率排一下。

焦距填的是等效焦距。这是最典型的一个。某些模组的规格书上同时给了实际焦距和 35mm 等效焦距,如果配置文件里填成了等效值,比如实际 4.7mm 填成 26mm,算出来的 FOV 只有十几度,测试会以极大的偏差 fail。这种情况一眼就能看出来——理论 FOV 明显偏小,跟人眼直觉都不符。

焦距填的是标称值而不是实测值。模组规格书上的焦距是设计值,实际量产件会有公差,模组厂在标定工位上测出来的有效焦距才是真的。如果配置文件用的是设计标称值,偏差可能在 2%~5%,刚好卡在容差边缘,表现为“有时候过有时候不过”。

传感器尺寸单位错。SENSOR_INFO_PHYSICAL_SIZE的单位是毫米,但有人填成英寸,有人填成像素数,还有人填成微米。填成像素数的话数值会大三个数量级,算出来的 FOV 接近 180°,非常明显;填成英寸的话数值小 25 倍多,FOV 会小得离谱。这类错误一旦发生,测试是惨败而不是边缘失败。

传感器尺寸填的是全阵列而不是有效区域。这个最隐蔽。整块 sensor 的物理尺寸和实际输出时用的有效区域尺寸可能差 5%~10%,如果设备在某种分辨率下做了裁剪,而配置里填的是全尺寸,算出来的理论 FOV 就会比实测大,测试 fail。这种情况的典型特征是偏差不大但稳定存在,且只在特定分辨率或特定宽高比下出现。

4.3 多摄与逻辑相机的专属坑

单摄设备的排查到上面基本就结束了,多摄设备还有一层坑。

现代设备普遍用逻辑相机(logical camera)把多个物理相机聚合起来,应用看到的是一个 camera id,底层可能是主摄、超广角、长焦的组合。CameraCharacteristics里通过LOGICAL_MULTI_CAMERA_PHYSICAL_IDS列出背后的物理相机。问题在于,逻辑相机上报的焦距和传感器尺寸,通常只反映其中一颗(一般是主摄),而不是聚合后的等效参数。

结果就是:CTSV 拿逻辑相机的参数算理论 FOV,但实际拍摄时由于光照、距离或者 zoom ratio 的设置,成像可能已经切到了另一颗物理相机,或者做了数码裁切。这种不匹配会直接导致 fail,而且偏差方向不固定,取决于当时切到了哪颗。

处理办法是在测试时明确指定物理相机。CTSV 的列表里如果同时列出了逻辑相机和物理相机,优先测物理相机;如果只列逻辑相机,就得在设备侧确认测试期间不会发生相机切换——把 SAT(无缝切换)相关的配置暂时关掉,或者通过固定 zoom ratio 把成像锁定在主摄上。测完再打开,别把功能配置改坏了。

另一个坑是超广角模组的畸变。超广角为了控制体积,通常用较多的非球面镜片,畸变(尤其是桶形畸变)在 10% 以上很常见。如果测试用的靶标标记点分布在画面边缘,畸变会把标记点的成像位置往外推或往里拉,反算出来的 FOV 就不准。这种情况的典型表现是超广角总是 fail 而主摄能过,且偏差方向一致。处置方式一般是确认 HAL 是否上报了畸变校正(DISTORTION_CORRECTION_MODE),以及测试时该模式是否生效。

4.4 常见问题速查表

把上面这些整理成一张表,现场排查的时候可以直接对着看。

现象可能根因验证方式处置
三次重跑结果分散很大对焦未锁定 / 光照频闪 / 设备抖动观察预览画面是否对焦抖动、换光源复测改用定时拍摄,换直流柔光灯
同型号两台机器同样 fail 且数值接近配置数据错误对比两台 dumpsys 输出是否一致修正 vendor 相机配置
只有垂直方向偏差大宽高比裁剪 / 有效高度填错核对 SCALER_CROP_REGION 与 active array按实际输出区域修正尺寸
理论 FOV 明显偏小(如只有十几度)焦距填成 35mm 等效值用薄透镜公式反算比对改为实际有效焦距
理论 FOV 接近 180°传感器尺寸单位填成像素数检查数值量级改为毫米
超广角总 fail、主摄正常桶形畸变导致边缘标记偏位观察画面边缘直线是否弯曲确认畸变校正配置
拍摄瞬间结果跳变多摄切换或数码裁切打印实际使用的物理相机 id锁定物理相机后复测
近距离下 FOV 偏小focus breathing拉远距离复测按指引距离摆放

这张表不是穷举,但覆盖了实际项目里八成以上的情况。真遇到表里没有的,回到“环境—数据—成像链路”这三层重新分一遍,基本都能收敛。

5. 参数修正与回归验证

5.1 focal length 与 sensor size 该怎么改

确认是数据问题之后,改哪儿、怎么改,有几个原则得先立住。

改动要落在标定数据源上,不要改 HAL 里的硬编码。正规的做法是修正模组厂提供的标定数据(存在 EEPROM 里的或者随固件下发的标定文件),让 HAL 从标定数据里读出来的就是正确值。直接在 HAL 里写死一个数让它通过测试,属于掩耳盗铃——第三方应用调用同样的接口会拿到错误参数,AR 测距、景深合成、透视校正这些功能全都会跟着偏。而且下一版固件一旦重新生成标定数据,硬编码就被覆盖了,问题原样复现。

焦距优先用实测有效焦距,不要用设计标称值。模组出厂标定工位会给出每颗模组的实测值,有条件的项目应该让 HAL 读取每颗模组的独立标定数据,而不是用一份全局配置。这也是为什么同一型号不同批次可能表现不一样——标称值相同,实测值有公差。

传感器尺寸要用有效成像区域,不是全阵列。具体做法是先确定测试和日常使用的主要输出模式的宽高比,再算出该模式下实际使用的像素区域,然后按像素比例换算物理尺寸:

W_active = W_physical × (activeWidthPixels / fullWidthPixels) H_active = H_physical × (activeHeightPixels / fullHeightPixels)

这个换算的必要性在于,很多模组的像素阵列是 4:3 的,但视频和部分拍照模式输出 16:9,上下各裁掉一部分,垂直方向的有效高度就缩了。如果配置里填的是全阵列高度,垂直 FOV 就会被高估。

改之前先算一遍,改完再算一遍。拿改后的参数代进薄透镜公式,看算出来的 FOV 和实测值差多少。如果改完还是差 5% 以上,说明还有别的因素没考虑到,别急着刷机重测,先把差异来源弄清楚。

5.2 改完之后的回归路径

参数改完、固件重新打包刷入之后,回归不能只跑一次 CTSV 就完事。

第一步是复核参数。刷完机先跑一遍读取代码或者dumpsys,确认 HAL 暴露出来的值确实变成了新值。这一步经常出问题——配置改了但没生效,可能因为配置文件的加载优先级、或者被另一份配置覆盖了、或者编译时压根没打进去。不确认这一步就去跑测试,跑挂了都不知道是参数没生效还是参数还是错的。

第二步是原地重跑 CTSV 的 FOV 测试三次。三次都过且余量充足(偏差控制在一个比较舒服的区间)才算通过。只跑一次通过不算数,因为这个测试本身有一定的操作波动性。

第三步是覆盖全部 camera id。改主摄的配置可能影响到逻辑相机的聚合结果,改超广角可能影响到 SAT 的切换判断。所有 id 都跑一遍,别留尾巴。

第四步是功能回归。参数改了之后,依赖这些参数的相机功能都要过一遍:变焦是否正常、AR 类应用的空间感知是否正常、景深照片的边缘处理是否正常、扫码类应用的识别距离是否合理。我遇到过一次改完焦距之后 FOV 测试过了,但某个依赖焦距做透视校正的功能出现了明显的边缘拉伸,最后发现是改的值虽然在容差内,但和畸变校正的参数不匹配。所以参数不是孤立的,改一个要顺手检查跟它耦合的那几个。

第五步是留档。改前改后的dumpsys输出、测试结果截图、模组标定报告,全部归档到项目目录里。下次换人接手或者下一版认证的时候,这些就是最有价值的参考。

6. 几条踩过坑之后的经验

关于这个测试项,我攒了几条不太会在文档里写的东西,放在这里。

别把 CTSV 的结果当成唯一的真相。它是个判定工具,不是测量工具。它给出的实测 FOV 本身也有误差,误差来自靶标识别精度、镜头畸变、拍摄时的对焦状态。所以当偏差只有 1%~2% 的时候,纠结“到底是谁错了”意义不大,重点应该放在“我的参数是不是从可信来源来的”。如果参数来源扎实(模组厂实测标定 + 正确的有效区域换算),那测试挂了就该怀疑测试条件;如果参数来源本来就是估的,那就先把来源修好,别在测试条件上打转。

建立一个自己的交叉验证手段。我习惯在项目里备一套棋盘格标定流程,用标准的相机标定方法独立算一遍焦距和主点,跟 HAL 上报的值做对比。这个方法不追求精度极致,但能快速判断“上报值靠不靠谱”。棋盘格打印出来贴在硬板上,拍十几张不同角度的图,跑一遍标定脚本,几分钟就能出结果。有了这个交叉验证,跟模组厂沟通的时候底气完全不一样——不是“测试挂了你们看看”,而是“我这边独立标出来是 4.62mm,你们给的 4.71mm 差了 2%,麻烦确认一下”。

环境搭建的成本要提前算进去。一套好用的测试工位——带刻度的云台、哑光黑背板、直流柔光灯、可调高度的支架——加起来可能就几千块,但能省掉的返工时间是以周计的。我见过团队为了省钱用纸箱和胶带搭工位,结果每跑一次结果都不一样,最后排查了两周才发现是支架每次装夹角度都不同。这种钱不能省。

多摄设备的测试顺序有讲究。我的习惯是先测主摄,因为主摄的标定数据通常最扎实,先跑通它能把环境因素排除掉;再测超广角,因为它的畸变最大,最容易暴露靶标识别的问题;最后测长焦和其他特殊模组。按这个顺序跑,前面通过的结果可以作为后面失败的参照系——如果主摄过、超广角挂,那问题基本锁定在超广角自身的光学或标定上,不用再怀疑环境。

改动记录要细到能复现。每次改配置,记清楚改了哪个文件的哪个字段、从什么值改成什么值、依据是什么(哪份标定报告、哪次独立测量)。我吃过一次亏,改了三处参数之后测试过了,但过了一个月要回溯“到底哪一处改动起了作用”,完全想不起来,只能全部回退重来一遍。现在我的习惯是在项目目录里放一个变更日志,每改一次追加一行,写清楚时间和依据,成本极低但价值极高。

最后一点,也是我觉得最重要的:把这个测试项当成一次光学参数的体检,而不是一道要跨过去的坎。参数准了,受益的不只是认证通过,还有所有依赖相机做空间计算的应用——测距、建模、AR 放置、文档透视矫正,这些功能的体验全都建立在这几个毫米级数字的准确性上。反过来,如果只是为了让测试变绿而凑了一个数,那这些功能迟早会在用户手里出问题,而且到那时候排查成本比现在高十倍。

这套流程我在几个项目上连续用过,从最初的手忙脚乱到现在基本能在半天内把一个 FOV fail 收敛到具体字段,靠的不是什么高深技巧,就是把“先排除环境、再核对数据、最后查成像链路”这个顺序守住,不跳步、不臆测。真正难的部分从来不是改哪个参数,而是在改之前能确定它就是那个该改的参数。