OpencvSharp 算子学习教案之 - Cv2.CalibrationMatrixValues 重载1
大家好,Opencv在很多工程项目中都会用到,而OpencvSharp则是以C#开发与实现的Opencv操作库,对.NET开发人员友好,但很多API的中文资料、应用场景及常见坑点等缺乏系统性归纳,因此这系列博客将给大家带来Cv2及Mat对象全系列算子学习教案,供大家参考学习。
Cv2.CalibrationMatrixValues
- 教案版本:V1.0
- 面向对象:OpenCvSharp 初学者
- 所属模块:calib3d / 相机标定与相机模型
- 源码位置:OpenCvSharp/Cv2/Cv2_calib3d.cs,1567
摘要:本页演示CalibrationMatrixValues(InputArray cameraMatrix, Size imageSize, double apertureWidth, double apertureHeight, out double fovx, out double fovy, out double focalLength, out Point2d principalPoint, out double aspectRatio)的输入方式与输出含义。示例以Mat包装为InputArray的写法说明相机内参与传感器尺寸之间的换算关系,帮助初学者理解它只是“读取并派生计算”的函数,不会修改输入矩阵。
1. 函数名称(带参数签名)
publicstaticvoidCalibrationMatrixValues(InputArraycameraMatrix,SizeimageSize,doubleapertureWidth,doubleapertureHeight,outdoublefovx,outdoublefovy,outdoublefocalLength,outPoint2dprincipalPoint,outdoubleaspectRatio)这个重载适合已经把相机矩阵放进Mat或其它 OpenCvSharp 容器的场景。它的写法很贴近 OpenCvSharp 的高层 API 风格:先准备一个可被读取的矩阵容器,再传给函数进行派生量计算。
2. 函数用途
Cv2.CalibrationMatrixValues的作用非常明确:它根据一个已知的相机内参矩阵,计算出更容易理解的物理和几何量。
常见用途包括:
- 快速检查标定结果是否合理,例如主点是否接近图像中心。
- 把像素意义下的内参换算成更直观的视场角和物理焦距。
- 在相机选型、镜头分析、标定报告中展示结果。
- 在教学场景中把
fx / fy / cx / cy和fovx / fovy / principalPoint关联起来。
它的核心不是“重新标定”,而是“解释已有标定结果”。如果你手里已经有相机矩阵,这个函数就像一个翻译器,把抽象的内参翻译成更好理解的派生量。
3. 函数公式
当apertureWidth和apertureHeight使用真实物理尺寸时,OpenCV 会先计算像素到物理单位的换算比例:
m x = i m a g e W i d t h a p e r t u r e W i d t h , m y = i m a g e H e i g h t a p e r t u r e H e i g h t mx=\frac{imageWidth}{apertureWidth},\quad my=\frac{imageHeight}{apertureHeight}mx=apertureWidthimageWidth,my=apertureHeightimageHeight
随后根据内参矩阵中的焦距与主点位置计算输出量:
f o v x = [ arctan ( c x f x ) + arctan ( W − c x f x ) ] ⋅ 180 π fovx=\left[\arctan\left(\frac{c_x}{f_x}\right)+\arctan\left(\frac{W-c_x}{f_x}\right)\right]\cdot\frac{180}{\pi}fovx=[arctan(fxcx)+arctan(fxW−cx)]⋅π180
f o v y = [ arctan ( c y f y ) + arctan ( H − c y f y ) ] ⋅ 180 π fovy=\left[\arctan\left(\frac{c_y}{f_y}\right)+\arctan\left(\frac{H-c_y}{f_y}\right)\right]\cdot\frac{180}{\pi}fovy=[arctan(fycy)+arctan(fyH−cy)]⋅π180
f o c a l L e n g t h = f x m x , p r i n c i p a l P o i n t = ( c x m x , c y m y ) , a s p e c t R a t i o = f y f x focalLength=\frac{f_x}{mx},\quad principalPoint=\left(\frac{c_x}{mx},\frac{c_y}{my}\right),\quad aspectRatio=\frac{f_y}{f_x}focalLength=mxfx,principalPoint=(mxcx,mycy),aspectRatio=fxfy
这里最容易误解的点是:focalLength并不是直接返回像素单位,而是和传感器尺寸保持一致的物理单位;principalPoint也不是新的像素坐标,而是把原来的主点换算到物理平面之后的结果。
4. 函数原理说明
可以把这个函数理解成“内参解释器”。它的步骤很简单,但意义很清晰:
- 读取相机矩阵中的
fx、fy、cx、cy。 - 根据图像尺寸和传感器尺寸计算像素与物理单位之间的比例。
- 把焦距、主点和视场角统一换算成更容易分析的输出。
它不做以下事情:
- 不会修改输入矩阵。
- 不会估计新的内参。
- 不会校正畸变。
- 不会替代
CalibrateCamera或StereoCalibrate。
也就是说,它适合放在“标定之后的分析阶段”,而不是“标定过程本身”。如果你把它理解为“把相机矩阵翻译成可读报告”,就很容易掌握它的定位。
5. 参数含义解析
| 参数 | 含义 | 初学者要点 |
|---|---|---|
| cameraMatrix | 3x3 相机内参矩阵 | 必须是标准针孔相机矩阵 |
| imageSize | 图像尺寸 | 要和当前内参对应的分辨率一致 |
| apertureWidth | 传感器物理宽度 | 与高度必须使用同一单位 |
| apertureHeight | 传感器物理高度 | 常见单位是毫米 |
| fovx | 水平视场角 | 输出单位是度 |
| fovy | 垂直视场角 | 输出单位是度 |
| focalLength | 焦距 | 与传感器单位保持一致 |
| principalPoint | 主点坐标 | 仍然是“物理平面意义下”的主点 |
| aspectRatio | 纵横焦距比 | 本质是fy / fx |
补充说明:
cameraMatrix的左上角通常是fx和fy。- 第三列前两项通常是
cx和cy。 aspectRatio不是图像宽高比,不要把它和分辨率混为一谈。- 如果
apertureWidth或apertureHeight填得不真实,输出的物理焦距也会失去意义。
6. 应用场景列表
- 相机标定后做结果审查。
- 镜头选型时估算实际视场角。
- 工业视觉项目中输出标定报告。
- 教学中帮助初学者建立“像素内参”和“物理相机参数”的联系。
- 在调试多分辨率系统时确认当前内参是否与图像尺寸匹配。
7. 函数使用示例
下面的 Console 示例直接把 3x3 相机矩阵包装成InputArray后调用CalibrationMatrixValues。这也是对应 WPF 示例里最贴近 OpenCvSharp 容器风格的写法。
usingSystem;usingSystem.Text;usingOpenCvSharp;namespaceDemo;internalstaticclassProgram{privatestaticvoidMain(){// 显式设置 UTF-8,避免中文输出在控制台里出现乱码。Console.OutputEncoding=Encoding.UTF8;// 直接创建一个标准 3x3 相机矩阵,和 WPF 示例中的 Mat 数据保持一致。usingvarcameraMatrix=Mat.FromPixelData(3,3,MatType.CV_64FC1,newdouble[]{980.0,0.0,640.0,0.0,976.0,360.0,0.0,0.0,1.0,});// 图像尺寸必须和这组内参对应的分辨率保持一致。varimageSize=newSize(1280,720);// 传感器物理尺寸使用毫米只是演示,关键是宽高必须使用同一单位。varapertureWidth=6.40;varapertureHeight=3.60;// 先把 Mat 包装成 InputArray,再调用 CalibrationMatrixValues。Cv2.CalibrationMatrixValues(InputArray.Create(cameraMatrix),imageSize,apertureWidth,apertureHeight,outdoublefovx,outdoublefovy,outdoublefocalLength,outPoint2dprincipalPoint,outdoubleaspectRatio);Console.WriteLine("=== Cv2.CalibrationMatrixValues(InputArray) ===");Console.WriteLine($"imageSize ={imageSize.Width}x{imageSize.Height}");Console.WriteLine($"aperture ={apertureWidth:F2}mm x{apertureHeight:F2}mm");Console.WriteLine($"fovx ={fovx:F4}deg");Console.WriteLine($"fovy ={fovy:F4}deg");Console.WriteLine($"focalLength ={focalLength:F4}mm");Console.WriteLine($"principalPoint = ({principalPoint.X:F4},{principalPoint.Y:F4})");Console.WriteLine($"aspectRatio ={aspectRatio:F6}");}}这段代码有三个关键点:
InputArray.Create(cameraMatrix)让示例贴近 OpenCvSharp 的容器风格。Console.OutputEncoding = Encoding.UTF8保证中文在控制台正确显示。- 输入矩阵保持 3x3,不需要你先转成其它容器再调用。
8. 注意事项
cameraMatrix必须是 3x3。imageSize需要与当前内参对应的分辨率一致。apertureWidth和apertureHeight必须使用同一单位。principalPoint仍然是主点概念,不是图像外的新坐标系。- 如果只是验证像素关系,传感器尺寸也必须填写得合理,否则物理焦距会失真。
9. 调优建议
- 在教学时故意设置略有差异的
fx和fy,更容易理解aspectRatio的意义。 - 如果你在做真实项目,建议从相机说明书或标定流程中读取传感器尺寸,而不是随便填写。
- 如果输出的视场角和预期差很多,先检查图像尺寸和内参是否来自同一分辨率。
- 把
CalibrationMatrixValues和CalibrateCamera的输出一起看,更容易发现单位错误或配置错误。
10. 进阶扩展
- 把这个函数放进标定报告生成流程中,自动输出视场角、主点和焦距。
- 与
StereoCalibrate的结果配合,分析左右相机内参是否接近一致。 - 在 WPF 教学界面里把输入矩阵、传感器信息和结果图同时展示,方便初学者理解流程。
- 如果你需要批量审查多组相机参数,可以把此函数包装成一个校验工具。
11. 常见错误排查
- 如果报“矩阵尺寸不对”,先检查是不是传了 2x2、2x3 或空矩阵。
- 如果焦距看起来不合理,通常是传感器尺寸和图像尺寸没有配套。
- 如果
principalPoint明显偏离中心,先检查内参是否真的来自当前分辨率。 - 如果把
aspectRatio当成宽高比,就会误解这个参数的含义。 - 如果中文输出乱码,先确认控制台编码已经设置为 UTF-8。
相关链接:
- WPF 教学控件:Cv2CalibrationMatrixValuesControl.xaml.cs
- 示例实现:CalibrationMatrixValuesInputArraySample.cs
- 同一函数的另一重载:Cv2.CalibrationMatrixValues.matrix-array.md