相机内参

Zivid相机模型比一些广为人知的针孔相机模型(例如OpenCV相机模型)更复杂,使用了更多的内参。此外,我们的相机使用了一种滚动校准技术,这意味着点云是作为光圈、温度和颜色通道的函数生成的。

Zivid相机模型是专有的,这就是我们的内部相机内参无法通过SDK获取的原因。但是,我们提供了OpenCV和Halcon模型的近似值,因为许多机器视觉算法都依赖它们。

小心

一般来说,我们倾向于不鼓励使用相机内参。其中一个原因是在近似值中丢失了一些有价值的信息。另一个原因是通常有更好的方法可以达到相同的结果。由于主题的复杂性,我们建议您联络我们来讨论您的用例。内参是复杂的,建议尽可能使用点云!

OpenCV相机内参

Zivid SDK提供了两种获取OpenCV相机内参的选项。

针对固定光圈和固定温度给出的硬编码的相机内参。这个温度和光圈对应于我们认为的典型条件。

相机型号

镜头温度 (°C)

光圈

One+

35

6.2

Two

35

2.38

要获得硬编码的相机内参,您首先必须连接到相机:

跳转到源码

源码

std::cout << "Connecting to camera" << std::endl;
auto camera = zivid.connectCamera();
跳转到源码

源码

Console.WriteLine("Connecting to camera");
var camera = zivid.ConnectCamera();
跳转到源码

源码

print("Connecting to camera")
camera = app.connect_camera()

然后,您可以获得OpenCV相机内参(此函数会立即返回):

跳转到源码

源码

std::cout << "Getting camera intrinsics" << std::endl;
const auto intrinsics = Zivid::Experimental::Calibration::intrinsics(camera);
跳转到源码

源码

Console.WriteLine("Getting camera intrinsics");
var intrinsics = Zivid.NET.Experimental.Calibration.Calibrator.Intrinsics(camera);
跳转到源码

源码

print("Getting camera intrinsics")
intrinsics = calibration.intrinsics(camera)

小心

与我们的点云不同,硬编码的OpenCV内参不是温度和光圈的函数。因此,它们无法完全地对应于在不同温度下使用不同光圈拍摄的照片。如果使用每次采集都应用了不同光圈的HDR模式来捕获点云,那么情况会变得更加复杂。这是因为确定这种情况的内参并非易事。由于这些复杂性,我们提供了一种获取OpenCV相机内参的替代方法:通过点云估计相机内参。

这些相机内参是从点云中估计出来的。Zivid标定下的点云是由包括温度和光圈数据的函数生成的。因此,估计的内参间接利用了温度和光圈数据。

要获得估计的OpenCV内参,您首先必须连接到相机:

跳转到源码

源码

std::cout << "Connecting to camera" << std::endl;
auto camera = zivid.connectCamera();
跳转到源码

源码

Console.WriteLine("Connecting to camera");
var camera = zivid.ConnectCamera();
跳转到源码

源码

print("Connecting to camera")
camera = app.connect_camera()

然后您必须捕获一幅图像:

跳转到源码

源码

const auto frame = camera.capture(settings);
跳转到源码

源码

var frame = camera.Capture(settings);
跳转到源码

源码

with camera.capture(settings=settings) as frame:

然后,您可以从frame估计内参(因为涉及计算,此函数不会立即返回):

跳转到源码

源码

const auto estimated_intrinsics = Zivid::Experimental::Calibration::estimateIntrinsics(frame);
跳转到源码

源码

var estimatedIntrinsics = Zivid.NET.Experimental.Calibration.Calibrator.EstimateIntrinsics(frame);
跳转到源码

源码

estimated_intrinsics = calibration.estimate_intrinsics(frame)

保存相机内参

可以将OpenCV相机内参保存到YML文件中:

跳转到源码

源码

const std::string outputFile = "Intrinsics.yml";
std::cout << "Saving camera intrinsics to file: " << outputFile << std::endl;
intrinsics.save(outputFile);
跳转到源码

源码

var intrinsicsFile = "Intrinsics.yml";
Console.WriteLine("Saving camera intrinsics to file: " + intrinsicsFile);
intrinsics.Save(intrinsicsFile);
跳转到源码

源码

output_file = "Intrinsics.yml"
print(f"Saving camera intrinsics to file: {output_file}")
intrinsics.save(output_file)

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*。

备注

这种方法允许获得硬编码的相机内参和从点云估计的相机内参。但是对于后面一种方式,您需要保存和加载您需要的内参的每一次捕获。

我应该使用哪种相机内参?

硬编码相机内参

我们建议仅在以下情况下使用硬编码相机内参:

  • 您可以从以下任一方式获得彩色图像:

    • 2D捕获

    • 单次采集3D捕获

    • Color Mode 设置为 UseFirstAcquisition 的多次采集HDR 3D捕获。

  • 对于您的相关采集(上述三个选项之一),您可以使用我们提供硬编码内参的光圈值(参见 )。

  • 接近*室内*温度的环境温度。

  • 仅使用2D数据的应用,例如,使图像不失真以检测直线。

通过点云估计相机内参

我们建议在以下情况使用估计的内参:

  • 您从多次采集HDR 3D捕获中获取彩色图像,且 Color Mode 被设置为 AutomaticToneMapping 。这是因为点云很可能是使用不同光圈和在不同于对应硬编码内参的温度下进行采集的结果。

  • 存在必须使用OpenCV内参的任何其他用例时,例如:

    • 使用projectPoints()将3D数据投影到2D图像。

    • 使用solvePnP()从2D图像估计3D位姿。

备注

估计的相机内参也适用于我们推荐硬编码相机内参的所有情况。因此,为简单起见,您始终可以使用估计的内参。然而,从点云中估计内参需要一定的时间,而从相机中获取硬编码的内参是可以立即得到的。

手眼标定

一般来说,我们推荐的手眼标定是Zivid 手眼标定 ,因为它最适合Zivid相机。我们的手眼标定方法不需要相机内参,但是许多其它方法需要内参。如果您使用这些方法中的某一种,我们建议使用从点云估计的相机内参。阅读有关 选择正确的手眼标定方法 了解更多信息。

将3D点投影到2D图像平面

在将Zivid点云投影到2D图像平面时,使用估计的内参将获得比使用硬编码内参更小的重新投影误差。但是请记住,如果使用我们的校正过滤器,比如 Gaussian Smoothing(高斯平滑)Contrast Distortion Filter(对比度失真过滤器) ,那么将导致更大的重新投影误差。当在没有使用校正过滤器的情况下捕获的点云上使用估计的内参时,预计的重新投影误差小于1个像素。当使用了校正过滤器时,对于显着校正的点,重新投影误差会更大。然而,对于大多数点,应该仅有小于1个像素的重新投影误差。

从2D图像估计3D位姿

假设您正在根据2D图像估计对象的3D位姿,例如,使用OpenCV中的solvePnP()。与硬编码相机内参相比,从点云估计的内参将提供更好的结果。但是,我们不建议从2D图像中估计位姿,因为可以直接从点云中更准确地估计位姿。

2D图像处理算法

如果您的应用只使用2D数据,那么硬编码的内参和从点云估计的内参都可以正常工作。一个例子是校正2D图像的失真来校正镜头失真,从而保证直线的检测。