相机内参
Zivid相机模型比一些广为人知的针孔相机模型(例如OpenCV相机模型)更复杂,使用了更多的内参。此外,我们的相机使用了一种滚动校准技术,这意味着点云是作为光圈、温度和颜色通道的函数生成的。
Zivid 相机中的 3D 到 2D 映射
每个相机在空间中的 3D 点与其对应的 2D 像素索引之间都有物理关系。对于 Zivid 相机:
相同分辨率:当 2D 和 3D 数据具有相同的分辨率时,两者之间存在直接的 1:1 映射。
不同的分辨率:如果 2D 和 3D 分辨率不同,则映射取决于以下设置:
Settings2D::Sampling::Pixel
Zivid::Settings::Sampling::Pixel
为了在 2D 和 3D 数据之间保持 1:1 的对应关系,您可以使用 Settings::Processing::Resampling
设置对 3D 点云进行重新采样。有关更多信息,请参阅 Resampling(重采样) 。
或者,如果没有进行重采样,您可以使用 pixelMapping(camera, settings)
函数来获取 3D 和全分辨率 2D 中任何采样配置的正确点到像素映射。
小心
由于以下原因,我们建议不要使用相机内参:
信息丢失:近似值可能会导致有价值信息的丢失。
更好的替代方案:通常可以采用更有效的方法来获得类似或更好的结果。
我们建议直接使用点云数据和 像素映射 而不是内参。
Zivid 相机模型是专有的,这就是为什么我们的内部相机的内参在 SDK 中不可用。但是,由于许多机器视觉算法依赖于标准模型,Zivid 提供了 OpenCV 和 Halcon 内在函数模型的近似值以实现兼容性。
OpenCV相机内参
Zivid SDK 提供了一些获取 OpenCV 相机内参的方法。
函数名称 |
返回的内参对应的分辨率 |
---|---|
|
相机的 |
|
|
|
|
|
用于捕获 |
我们建议从点云中估算内参以获得最准确的结果。硬编码相机内参是根据特定的光圈和温度给出的。因此,它不会像估计的内参那样准确。请参阅下面的列表以了解每个相机型号的数值。
相机型号 |
镜头温度 (°C) |
光圈 |
---|---|---|
Zivid 2+ |
35 |
2.68 |
Zivid 2 |
35 |
2.30 |
相机内参是根据点云估算出来的,同时考虑到了拍摄过程中使用的光圈和温度。
要获得估计的OpenCV内参,您首先必须连接到相机:
调用捕获函数获取 frame:
然后,您可以从 frame 中获取估算的内参:
估算内参的函数考虑了采样策略。例如,如果将 Zivid::Settings::Sampling::Pixel
设置为 by2x2
并将 Zivid::Settings::Resampling
设置为 disiabled
,则会得到正确的(子采样后的)内内参:
const auto settingsSubsampled = subsampledSettingsForCamera(camera);
const auto frame = camera.capture2D3D(settingsSubsampled);
const auto estimatedIntrinsicsForSubsampledSettings =
Zivid::Experimental::Calibration::estimateIntrinsics(frame);
硬编码内参是根据特定光圈和温度给出的。如需获取硬编码相机内参,请先连接到相机:
然后,您可以获取默认的 OpenCV 格式的相机内参:
std::cout << "Getting camera intrinsics" << std::endl;
const auto intrinsics = Zivid::Experimental::Calibration::intrinsics(camera);
如果您使用了采样功能,则可以获取与 settings
中的 Zivid::Settings::Sampling::Pixel
和 Zivid::Settings::Resampling
的组合相所对应的 OpenCV 相机内参:
const auto settingsSubsampled = subsampledSettingsForCamera(camera);
const auto fixedIntrinsicsForSubsampledSettings =
Zivid::Experimental::Calibration::intrinsics(camera, settingsSubsampled);
使用 2D 设置采集时的硬编码内参:
const auto settings2D =
Zivid::Settings2D{ Zivid::Settings2D::Acquisitions{ Zivid::Settings2D::Acquisition{} } };
const auto fixedIntrinsicsForSettings2D = Zivid::Experimental::Calibration::intrinsics(camera, settings2D);
小心
硬编码的 OpenCV 内参是固定的,与 estimateIntrinsics
不同,它无法适应温度或光圈的变化。这意味着它们可能与在不同条件下拍摄的图像不匹配。
环境温度变化会影响相机的内部温度。虽然热稳定对此有所帮助,但镜头温度在部署开始和稳定后仍然会有很大差异。这种温差可能会导致硬编码内参和点云数据之间出现差异。光圈变化,特别是在 HDR 模式下,每次采集使用不同的光圈时,会进一步使硬编码内参的准确性复杂化。
由于这些复杂性,我们建议从点云估算相机内参以获得更准确的结果。
保存相机内参
您可以使用以下代码将 OpenCV 相机内参保存到 YML 文件:
Halcon相机内参
Halcon使用的是不同于Zivid和OpenCV的相机模型。有两种方法可以获得Halcon内参,两者都基于OpenCV模型的近似值。
小心
如果您需要使用 Halcon 格式的内参(相机内部参数),请使用下面描述的方法之一来获取它们。请勿在 Halcon 中校准我们的 2D 相机以获取 Halcon 内参;它无法很好地与我们的相机配合使用。
要求:
安装了Python和具备运行Python脚本的技能
安装了 Zivid-Python
为您的相机获取Halcon内参的最简单方法是运行 convert_intrinsics_opencv_to_halcon.py 代码示例。阅读示例描述,重点关注 example when reading from camera。
备注
此方法仅限于获取硬编码的相机内参。
要求:
安装了Python和具备运行Python脚本的技能
构建C++或C#代码示例的技能
为您的相机获取Halcon内参的另一种方法是从YML文件加载OpenCV相机内参并将它们转换为Halcon格式。
要获取OpenCV相机内参并将它们保存到文件中,请运行以下示例之一:
要获取OpenCV相机内参并将它们保存到文件中,请运行 GetCameraIntrinsics.cpp 。查看 使用 CMake 配置 C++ 示例并在 Windows 的 Visual Studio 中构建它们 。
要获取OpenCV相机内参并将它们保存到文件中,请运行 GetCameraIntrinsics.cs 。查看 使用Visual Studio构建C#示例 构建C#示例。
要获取OpenCV相机内参并将它们保存到文件中,请运行 get_camera_intrinsics.py 。
然后,运行 convert_intrinsics_opencv_to_halcon.py 代码示例。阅读示例描述,重点关注*Example when reading from file*。
备注
这种方法允许获得硬编码的相机内参和从点云估计的相机内参。但是对于后面一种方式,您需要保存和加载您需要的内参的每一次捕获。
我应该使用哪种相机内参?
一般来说,我们建议使用实际点云数据和 pixelMapping(camera, settings)
函数而不是内参。如果绝对必要,请参阅以下指南以选择正确的相机内部函数。
硬编码相机内参
我们建议仅在以下情况下使用硬编码相机内参:
有下列情形之一的,
使用
capture2D()
从 2D 采集获取彩色图像使用
capture2D()
从 2D 采集中获取彩色图像,并使用capture3D()
从 3D 采集中获取点云使用
capture2D3D()
从 3D 采集中获取点云
对于与硬编码光圈类似的光圈(用于 2D 和 3D)(参见 表 )。
接近*室内*温度的环境温度。
仅使用2D数据的应用,例如,使图像不失真以检测直线。
通过点云估计相机内参
我们建议在几乎所有情况下都使用估算的内参:
不论您是如何获得彩色图像和点云的。这是因为点云可能是使用不同光圈和不同温度(与硬编码内参对应的温度不同)采集的结果。
使用 OpenCV 格式的内参时的任何用例都是必要的,例如:
使用 projectPoints() 将3D数据投影到2D图像。
使用 solvePnP() 从 2D 图像估计 3D 位姿。
备注
在我们推荐使用硬编码内参的所有情况下,估算的相机内参也能使用。但是,估算内参需要一些计算时间,而从相机获取硬编码内参则是即时的。
不同分辨率的 2D 和 3D 捕获
我们建议使用 像素映射 和点云数据来使用 2D 和 3D 数据。这样可以正确处理分辨率差异。
另一种方法是通过对 2D 图像进行下采样或子采样以匹配 3D 分辨率,从而使 2D 数据的分辨率与 3D 数据相匹配。如需了解更多信息,请参阅 Sampling(采样) - 3D 、 Sampling(采样)- 2D 和 Resampling(重采样) 。
如果您仍然需要使用内参,我们建议使用 estimateIntrinsics(frame)
。
手眼标定
我们推荐Zivid的 手眼标定 标定,因为它最适合 Zivid 相机。我们的手眼标定方法不需要使用相机内参;但是许多其他方法都需要。如果您使用其他方法之一,我们建议使用通过点云 estimateIntrinsics()
。阅读有关 选择正确的手眼标定方法 的更多信息。
将3D点投影到2D图像平面
我们建议在将 Zivid 点云投影到 2D 图像平面时使用 estimateIntrinsics
。
这将导致比使用硬编码内参更小的重新投影误差。但是,请记住,如果使用了我们的校正过滤器,例如 Gaussian Smoothing(高斯平滑) 和 Contrast Distortion Filter(对比度失真过滤器) ,将会增加重新投影的误差。在没有使用校正过滤器捕获的点云上使用估算的内参时,预期的重新投影误差小于 1 个像素。当使用了校正过滤器时,对于显著校正的点,重新投影误差会更大。但是,对于大多数点,重新投影误差应该小于 1 个像素。
降采样或子采样 2D
当您对 2D 数据进行子采样/降采样时,您可以重新获得 2D 和 3D 之间的直接 1 对 1 映射,请参阅 Sampling(采样) - 3D 。
在对全分辨率 2D 图像进行降采样时,了解哪些像素用于生成降采样像素是非常重要的。如果您在所需像素周围对称地使用像素,则平均像素应落在与 3D 数据相对应的像素位置上。这与 SDK 提供的内参最相符。
更多信息请参阅:
从2D图像估计3D位姿
将二维像素投影到三维空间时,我们建议使用点云中的 estimateIntrinsics
。
与硬编码的相机固定内参相比,从点云估计的内参将提供更好的结果。然而,我们更建议直接从点云估计位姿,因为这样会更准确。
2D图像处理算法
如果您的应用只使用2D数据,那么硬编码的内参和从点云估计的内参都可以正常工作。一个例子是校正2D图像的失真来校正镜头失真,从而保证直线的检测。
版本历史
SDK |
变更 |
---|---|
2.10.0 |
Monochrome Capture(单色捕获) 需要在使用它们之前修改内参。 |