19、Camera测试与自动化:从CTS到生产流水线
做Camera驱动开发这么多年,我越来越觉得:测试不是终点,而是起点。你想想看,一个Camera HAL写出来,跑一遍CTS就完事了?那太天真了。真正的坑,往往藏在压力测试和图像质量评估里。
今天这一章,我带你完整走一遍Camera测试的体系。从Google官方的CTS/CTS Verifier,到自动化框架CameraITS,再到图像质量分析工具Imatest/IE,最后咱们亲手搭一条自动化测试流水线。
19.1 CTS与CTS Verifier:Camera测试的“入场券”
CTS(Compatibility Test Suite)是Google给Android设备发的“通行证”。你的Camera HAL能不能过CTS,直接决定了设备能不能预装GMS。说白了,这是底线。
CTS里跟Camera相关的测试项,主要分三块:
- Camera CTS:纯自动化测试,覆盖基本功能、参数、格式转换等。跑一遍大概2-3小时。
- CTS Verifier:半自动化测试,需要人工参与。比如测试闪光灯同步、对焦准确性、多摄像头切换等。
- Camera ITS:图像测试套件,后面单独讲。
关键测试项速查表
| 测试模块 | 测试内容 | 常见失败原因 |
|---|---|---|
| CameraManagerTest | 摄像头枚举、打开/关闭 | HAL返回的摄像头ID不匹配 |
| CaptureRequestTest | 各种参数设置(AE/AWB/AF) | 3A算法未收敛就返回结果 |
| StreamConfigurationMapTest | 输出格式、分辨率支持 | 漏掉了某些必须的格式(如YUV420) |
| ReprocessTest | YUV→JPEG重处理 | 重处理管线实现有bug |
我记得有一次,一个项目CTS跑了三天都没过。最后发现是HAL里把摄像头朝向(facing)写反了。前置摄像头写成了BACK,后置写成了FRONT。这种低级错误,在CTS面前一抓一个准。
我的习惯:每次提交HAL代码前,先跑一遍Camera CTS的“冒烟测试”子集。大概20分钟就能知道有没有致命问题。别等到集成测试才发现,那太晚了。
19.2 CameraITS:自动化图像测试框架
CameraITS(Image Test Suite)是Google专门用来评估图像质量的自动化框架。它跟CTS不同,CTS测的是“能不能用”,ITS测的是“好不好用”。
ITS的测试场景包括:
- 色彩还原准确性
- 曝光一致性
- 噪声水平
- 动态范围
- 几何畸变
它的工作流程是这样的:
# ITS测试流程伪代码
1. 控制摄像头拍摄特定场景(色卡、灰卡、分辨率卡)
2. 从HAL获取RAW或YUV图像
3. 用Python脚本分析图像指标
4. 与参考值对比,给出pass/fail
ITS的测试脚本是用Python写的,放在tools/tradefederation/contrib/its/目录下。你可以直接跑:
# 运行单个ITS测试项
python3 its_main.py --test test_sensor_noise.py --camera 0
# 运行全部ITS测试
python3 its_main.py --all --camera 0
我曾经踩过的坑:ITS测试对光照环境要求极高。有一次我在普通办公室灯光下跑色彩还原测试,结果全红。后来才发现,ITS要求用D65标准光源,照度在500-1000 lux之间。换了灯箱之后,一次就过了。
19.3 压力测试与稳定性测试
压力测试,说白了就是“往死里用”。我见过太多HAL在单次调用时表现完美,但连续开关1000次摄像头后就崩了。
常用的压力测试手段:
- Camera Stress Test:连续打开/关闭摄像头,每次随机切换参数
- Memory Leak Test:长时间录像,监控内存增长
- Concurrent Test:多路摄像头同时工作
- Thermal Test:高温环境下长时间运行
我自己写过一个简单的压力测试脚本,核心逻辑就几行:
# 压力测试核心循环
for i in range(10000):
camera = Camera.open(camera_id)
session = camera.create_capture_session()
session.capture(request)
session.close()
camera.close()
# 检查是否有ANR或crash
check_logcat_for_errors()
你想想看,如果这个循环能跑完10000次不报错,那稳定性基本就稳了。但现实往往是:跑到第500次左右,内存就涨上去了。
避坑指南:我曾经遇到一个案例,压力测试跑到第3000次时,Camera HAL返回了-EBUSY。查了三天才发现,是底层驱动在关闭摄像头时没有完全释放DMA buffer。这种问题,单次测试根本发现不了。
19.4 图像质量测试:Imatest与IE
图像质量测试,是Camera开发的“最后一公里”。你用Imatest或者Image Engineering(IE)的软件,对着标准测试卡拍一张,软件就能自动算出MTF、SNR、色彩误差等指标。
常用的测试卡和对应指标:
| 测试卡 | 测试指标 | 典型要求 |
|---|---|---|
| ISO 12233分辨率卡 | MTF50、MTF30 | 中心MTF50 > 0.5 |
| X-Rite ColorChecker | ΔE、饱和度 | ΔE < 5 |
| 灰阶卡(20阶) | 动态范围、Gamma | 动态范围 > 60dB |
| 均匀光源 | Shading、Lens Roll-off | 亮度均匀性 > 80% |
Imatest的操作流程大致是:
- 拍摄测试卡图像(建议用RAW格式)
- 导入Imatest软件
- 选择对应的测试模块(SFR、Colorcheck、Uniformity等)
- 软件自动分析,生成报告
我的经验:图像质量测试最怕“人肉对比”。我见过有人用肉眼判断两张照片哪个更清晰,结果两个人给出完全不同的结论。用Imatest量化指标,才能让测试结果可复现、可追溯。
19.5 实战:搭建Camera自动化测试流水线
好了,前面讲了这么多测试工具,现在咱们把它们串起来,搭一条完整的自动化测试流水线。
流水线的核心流程:
- 代码提交触发:Git hook或CI系统检测到HAL代码变更
- 编译部署:编译HAL模块,刷入测试设备
- CTS冒烟测试:跑Camera CTS子集(约20分钟)
- 压力测试:跑1000次开关+录像循环(约30分钟)
- ITS图像测试:在灯箱环境下跑ITS核心项(约40分钟)
- 报告生成:汇总所有测试结果,发送邮件通知
下面是我用Python写的一个简化版流水线调度脚本:
#!/usr/bin/env python3
# camera_test_pipeline.py
import subprocess
import sys
import time
def run_cts_smoke():
print("[Pipeline] 开始CTS冒烟测试...")
result = subprocess.run([
"cts-tradefed", "run", "cts", "-m", "Camera",
"--include-filter", "android.hardware.camera2.cts.CameraManagerTest"
], capture_output=True)
return result.returncode == 0
def run_stress_test():
print("[Pipeline] 开始压力测试...")
result = subprocess.run([
"python3", "stress_test.py", "--iterations", "1000"
], capture_output=True)
return result.returncode == 0
def run_its_tests():
print("[Pipeline] 开始ITS图像测试...")
result = subprocess.run([
"python3", "its_main.py", "--test", "test_color_reproduction.py",
"--camera", "0"
], capture_output=True)
return result.returncode == 0
def main():
results = {}
results['cts'] = run_cts_smoke()
results['stress'] = run_stress_test()
results['its'] = run_its_tests()
# 生成报告
for test, passed in results.items():
status = "PASS" if passed else "FAIL"
print(f"[Pipeline] {test}: {status}")
if all(results.values()):
print("[Pipeline] 所有测试通过!")
sys.exit(0)
else:
print("[Pipeline] 有测试失败,请检查日志。")
sys.exit(1)
if __name__ == "__main__":
main()
关键点:流水线里最容易被忽略的是“环境一致性”。我建议用Docker或者专门的测试机柜,保证每次测试的光照、温度、设备状态都一样。否则你今天测的结果和明天测的,可能完全不一样。
下面这张图展示了整个测试流水线的架构:
这条流水线跑起来之后,你每天上班第一件事就是看邮件报告。哪个测试项挂了,直接定位到对应的HAL模块。效率比人工测试高出一个数量级。
最后提醒一句:自动化测试不是万能的。它只能发现你预设好的问题。真正的“硬骨头”,比如特定场景下的图像闪烁、低温下的帧率下降,往往需要人工去复现。所以,自动化测试 + 人工抽检,才是最佳实践。
公众号:蓝海资料掘金营,微信deep3321