OpencvSharp 算子学习教案之 - Cv2.CalibrationMatrixValues 重载1
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. 函数名称(带参数签名)
public static void 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 或其它 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 容器风格的写法。
using System;
using System.Text;
using OpenCvSharp;
namespace Demo;
internal static class Program
{
private static void Main()
{
// 显式设置 UTF-8,避免中文输出在控制台里出现乱码。
Console.OutputEncoding = Encoding.UTF8;
// 直接创建一个标准 3x3 相机矩阵,和 WPF 示例中的 Mat 数据保持一致。
using var cameraMatrix = Mat.FromPixelData(3, 3, MatType.CV_64FC1, new double[]
{
980.0, 0.0, 640.0,
0.0, 976.0, 360.0,
0.0, 0.0, 1.0,
});
// 图像尺寸必须和这组内参对应的分辨率保持一致。
var imageSize = new Size(1280, 720);
// 传感器物理尺寸使用毫米只是演示,关键是宽高必须使用同一单位。
var apertureWidth = 6.40;
var apertureHeight = 3.60;
// 先把 Mat 包装成 InputArray,再调用 CalibrationMatrixValues。
Cv2.CalibrationMatrixValues(
InputArray.Create(cameraMatrix),
imageSize,
apertureWidth,
apertureHeight,
out double fovx,
out double fovy,
out double focalLength,
out Point2d principalPoint,
out double aspectRatio);
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。
相关链接:
更多推荐


所有评论(0)