Android Camera2 API LEGACY模式下无需OpenCV获取相机内参
首先直接给结论:完全可以不用OpenCV通过Camera2 API获取相机内参,但你的设备处于LEGACY支持级别,正是导致LENS_INTRINSIC_CALIBRATION返回null的核心原因。
为什么LEGACY级别拿不到LENS_INTRINSIC_CALIBRATION?
Camera2 API的设备支持级别分为四个档次:LEGACY、LIMITED、FULL、LEVEL_3。其中LEGACY是最低级别的兼容模式,本质是把Camera2的调用转接到旧的Camera1 API实现上——这类设备的硬件或驱动并没有原生支持Camera2的全部高级特性,而LENS_INTRINSIC_CALIBRATION属于需要硬件层面提供校准数据的参数,所以在LEGACY模式下系统无法返回有效数据,只能返回null。
LEGACY级别设备获取内参的替代方案(无需OpenCV)
下面是几种可行的方法,按实用性排序:
1. 基于公开参数手动计算近似内参
Camera2在LEGACY模式下依然能返回几个关键参数,我们可以用这些参数推导近似的内参:
LENS_FOCAL_LENGTH:镜头的物理焦距(单位:mm,LEGACY模式下基本都能拿到)SENSOR_INFO_PHYSICAL_SIZE:传感器的物理尺寸(单位:mm)SENSOR_INFO_ACTIVE_ARRAY_SIZE:传感器活跃区域的像素尺寸
计算内参的核心公式(以fx为例,fy同理):
fx = (物理焦距 × 图像宽度像素) / 传感器宽度mm
光心cx、cy可以近似取图像的中心像素位置。
示例代码(Kotlin):
val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager val cameraId = // 你的目标相机ID(前置/后置) val characteristics = cameraManager.getCameraCharacteristics(cameraId) // 提取关键参数 val focalLength = characteristics.get(CameraCharacteristics.LENS_FOCAL_LENGTH) ?: 3.9f // 默认值适配多数手机 val sensorPhysicalSize = characteristics.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE) ?: Size(4.8f, 3.6f) val activeArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE) ?: Rect(0, 0, 1920, 1080) // 计算内参 val fx = focalLength * activeArraySize.width() / sensorPhysicalSize.width val fy = focalLength * activeArraySize.height() / sensorPhysicalSize.height val cx = activeArraySize.width() / 2.0f val cy = activeArraySize.height() / 2.0f // 最终内参矩阵可以表示为: // [fx, 0, cx] // [0, fy, cy] // [0, 0, 1]
注意:这种方法得到的是近似值,忽略了镜头畸变,但对于多数非高精度场景(比如简单的AR、扫码)完全够用。
2. 借助Camera1 API兼容获取
因为LEGACY模式本质是Camera1的封装,你可以直接使用Camera1的Camera.Parameters来获取相关参数,再进行计算。比如Camera1中可以通过parameters.getFocalLength()拿到焦距,结合传感器尺寸计算内参。这种方法和上面的思路一致,但如果你的项目已经基于Camera2,可能需要额外处理Camera1的权限和生命周期。
3. 预校准存储内参(高精度场景)
如果你的应用针对特定型号的设备,可以提前用相机标定工具获取该设备的精确内参,然后将参数硬编码到应用中,或者存储在本地配置文件里。这种方法精度最高,但只适合固定设备的场景。
额外说明
如果你的设备支持LIMITED及以上级别,直接调用characteristics.get(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION)就能拿到包含fx、fy、cx、cy以及畸变系数的数组,无需额外计算。
内容的提问来源于stack exchange,提问作者Sakala Bhargava Ram

