运行现场标定

介绍

如需在相机上运行现场验证和/或校正,您可以使用:

  • Zivid Studio

  • 命令行工具(CLI)

  • SDK

小技巧

如果您是第一次运行现场标定,我们建议使用Zivid Studio。

现场标定功能概述

  • Last correction 显示最近一次现场标定写入相机的日期和时间。

  • Capture & Measure 捕获图像以确定放置了Zivid标定板的区域的点云局部尺寸准确度误差。

  • Current Camera Metrics 显示最近一次使用 Capture & Measure 捕获的点云的局部尺寸准确度误差,以及所有捕获的误差的平均值和最大值。

  • Current trueness 显示最近一次使用 Capture & Measure 捕获的点云的局部尺寸准确度误差。

  • Average trueness 显示到目前为止使用 Capture & Measure 进行的所有捕获的局部尺寸准确度误差的平均值。

  • Maximum trueness 显示到目前为止使用 Capture & Measure 进行的所有捕获的局部尺寸准确度误差的最大值。

  • Expected Post-Correction Metrics 显示在拍摄图像的工作距离上的1σ(标准差)统计学不确定性内的估计的校正后的误差。

  • Save Correction to Camera 将参数写入相机,以提高点云的精度,这些点云是通过 Capture & Measure 拍摄的Zivid标定板确定的。

  • Reset Camera Correction 删除在之前的正确实例中应用的任何现场标定结果。在进行新的现场标定之前不需要进行重置。

DESCRIPTION
Tool for verifying, computing and updating infield correction parameters on a Zivid camera

SYNOPSIS
        ZividExperimentalInfieldCorrection.exe (verify|correct|read|reset) [-h]

OPTIONS
        verify      verify camera correction quality based on a single capture
        correct     calculate infield correction based on a series of captures at different distances and positions
        read        get information about the correction currently on the connected camera
        reset       reset correction on connected camera to factory settings

如果在安装期间将Zivid安装到自定义路径,则CLI工具也位于该路径下,否则,CLI工具位于 C:\Program Files\Zivid\bin 下。

CLI工具位于主路径中。

  • verify :此功能使用单次捕获来确定放置的Zivid标定板点云的局部尺寸准确度误差。

  • correct :此功能通过拍摄Zivid标定板来确定必要的参数,以提高点云的精度。该功能还将返回在拍摄图像的工作距离上的1σ(标准差)统计不确定性内的校正后的误差。

  • reset : 使用重置功能将删除之前正确应用的现场标定的结果。 在进行新的现场标定之前不需要进行重置。

  • read :读取功能将返回上一次将现场标定结果写入相机的时间。

Verify(验证)

将标定板放置需要验证的位置。我们建议使用Zivid Studio的实时(live)捕获模式来观察捕获情况以正确地对齐标定板。将棋盘格放置在您想要成像的区域中最近距离处,作为现场标定数据集的第一次捕获。使标定板尽可能地平行于相机坐标系,并确保整个标定板在相机坐标系中可见。

../../../_images/infield-in-studio-live.png

然后,打开现场标定工具(Infield Correction)。在工具栏中,单击 ToolsInfield Correction

../../../_images/infield-in-studio-toolbar.png

单击 Capture & Measure 以验证所连接相机的局部尺寸准确度误差。

../../../_images/infield-in-studio-capture-and-measure.png

结果将显示在 Current Camera Metrics 下:

../../../_images/infield-in-studio-capture-and-measure-with-metrics.png
潜在问题

如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:

  1. 标定板在X、Y或Z平面上过于倾斜。

  2. 并非所有特征点都是可检测的。

  3. 基准标记不可见。

  4. 标定板的图像质量太差,无法提供足够的数据。

../../../_images/infield-in-studio-issue-1.png ../../../_images/infield-in-studio-issue-2.png ../../../_images/infield-in-studio-issue-3.png ../../../_images/infield-in-studio-issue-4.png

使用命令行运行带有输入参数 verify 的验证功能(不要忘记在Zivid Studio中断开与相机的连接):

ZividExperimentalInfieldCorrection verify

潜在问题

如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:

  1. 标定板在X、Y或Z平面上过于倾斜。

  2. 并非所有特征点都是可检测的。

  3. 基准标记不可见。

  4. 标定板的图像质量太差,无法提供足够的数据。

如需通过SDK验证相机的局部尺寸准确度误差,首先需要连接到相机(不要忘记在Zivid Studio中断开与相机的连接)。

跳转到源码

源码

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()

然后,通过捕获Zivid标定板来收集数据。

跳转到源码

源码

std::cout << "Capturing calibration board" << std::endl;
const auto detectionResult = Zivid::Calibration::detectCalibrationBoard(camera);
跳转到源码

源码

Console.WriteLine("Capturing calibration board");
var detectionResult = Zivid.NET.Calibration.Detector.DetectCalibrationBoard(camera);
跳转到源码

源码

print("Capturing calibration board")
detection_result = zivid.calibration.detect_calibration_board(camera)

通过 ZDF 文件验证

为什么通过ZDF文件验证相机精度很有用?

让我们假设您的系统正在进行生产。您想在系统运行时验证相机的准确度。同时,您希望最大限度地减少机器人和相机用于其主要任务(例如料箱拣选)以外的任何事情的时间。您无需实时运行完整的现场验证功能(包括捕获、检测和估计准确度),而是可以仅捕获结果并将结果保存到磁盘上的ZDF文件中。当机器人和相机返回到它们的主要任务时,您可以使用另外一台PC加载ZDF文件并离线验证相机的准确度。此外,您还可以将这些ZDF文件发送给Zivid Customer Success进行检查。

如需通过ZDF文件验证相机精度,请先捕获标定板图像。

跳转到源码

源码

std::cout << "Capturing calibration board" << std::endl;
const auto frame = Zivid::Calibration::captureCalibrationBoard(camera);
跳转到源码

源码

Console.WriteLine("Capturing calibration board");
var frame = Zivid.NET.Calibration.Detector.CaptureCalibrationBoard(camera);
跳转到源码

源码

print("Capturing calibration board")
with zivid.calibration.capture_calibration_board(camera) as frame:

然后,将frame保存到磁盘。

跳转到源码

源码

const auto dataFile = "FrameWithCalibrationBoard.zdf";
frame.save(dataFile);
跳转到源码

源码

var dataFile = "FrameWithCalibrationBoard.zdf";
frame.Save(dataFile);
跳转到源码

源码

data_file = "FrameWithCalibrationBoard.zdf"
frame.save(data_file)

从ZDF文件加载frame。

跳转到源码

源码

std::cout << "Reading frame from file: " << dataFile << ", for offline infield verification" << std::endl;
const auto loadedFrame = Zivid::Frame(dataFile);
跳转到源码

源码

Console.WriteLine("Reading ZDF frame from file: " + dataFile + ", for offline infield verification");
var loadedFrame = new Zivid.NET.Frame(dataFile);
跳转到源码

源码

print(f"Reading frame from file: {data_file}, for offline infield verification")
with zivid.Frame(data_file) as frame:

然后,从frame中检测标定板特征点。

跳转到源码

源码

std::cout << "Detecting calibration board" << std::endl;
const auto detectionResult = Zivid::Calibration::detectCalibrationBoard(loadedFrame);
跳转到源码

源码

Console.WriteLine("Detecting calibration board");
var detectionResult = Zivid.NET.Calibration.Detector.DetectCalibrationBoard(loadedFrame);
跳转到源码

源码

print("Detecting calibration board")
detection_result = zivid.calibration.detect_calibration_board(frame)

备注

使用 captureCalibrationBoard(camera) 捕获的frame与 capture(camera) 生成的frame不同。函数 detectFeaturePoints 仅支持从 captureCalibrationBoard(camera) 函数返回的frame对象。

之后,准备数据并检查它是否适合现场验证。

跳转到源码

源码

const auto input = Zivid::Experimental::Calibration::InfieldCorrectionInput{ detectionResult };
if(!input.valid())
{
    throw std::runtime_error(
        "Capture not valid for infield verification! Feedback: " + input.statusDescription());
}
跳转到源码

源码

var input = new Zivid.NET.Experimental.Calibration.InfieldCorrectionInput(detectionResult);
if (!input.Valid)
{
    throw new Exception("Capture not valid for infield verification! Feedback: " + input.StatusDescription());
}
跳转到源码

源码

infield_input = zivid.experimental.calibration.InfieldCorrectionInput(detection_result)
if not infield_input.valid():
    raise RuntimeError(
        f"Capture not valid for infield verification! Feedback: {infield_input.status_description()}"
    )

最后显示验证结果。

跳转到源码

源码

std::cout << "Successful measurement at " << detectionResult.centroid() << std::endl;
const auto verification = Zivid::Experimental::Calibration::verifyCamera(input);
std::cout << "Estimated dimension trueness error at measured position: " << std::setprecision(2) << std::fixed
          << verification.localDimensionTrueness() * 100.0F << "%" << std::endl;
跳转到源码

源码

Console.WriteLine("Successful measurement at " + detectionResult.Centroid().ToString());
var verification = Zivid.NET.Experimental.Calibration.Calibrator.VerifyCamera(input);
Console.WriteLine("Estimated dimenstion trueness error at measured position: " + (verification.LocalDimensionTrueness * 100).ToString("0.00") + "%");
跳转到源码

源码

print(f"Successful measurement at {detection_result.centroid()}")
camera_verification = zivid.experimental.calibration.verify_camera(infield_input)
print(
    f"Estimated dimension trueness error at measured position: {camera_verification.local_dimension_trueness() * 100:.3f}%"
)

潜在问题

如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:

  1. 标定板在X、Y或Z平面上过于倾斜。

  2. 并非所有特征点都是可检测的。

  3. 基准标记不可见。

  4. 标定板的图像质量太差,无法提供足够的数据。

Correct(校正)

在相机上执行现场标定时,请在FOV中的不同距离和不同位置单击 Capture & Measure 来收集数据,如同 进行现场标定的准则 中所描述的那样。

../../../_images/infield-in-studio-capture-and-measure.png

当您进行现场标定捕获时,您将看到给定捕获次数的预期尺寸精度误差(如果您要应用校正)。

../../../_images/infield-in-studio-expected-metrics.png

完成此过程返回的信息包括:

  1. 最新计算出的FOV大部分区域的最大尺寸真实度误差。

  2. 该误差的范围取决于拍摄校正图像的距离。

如果对校正的结果满意,请选择将校正参数应用于相机。

Clear Measurements(清空测量数值)

如果您想清空测量值数据并重新开始捕获,请单击 Capture 里的三个点。然后,点击 Clear Measurements

../../../_images/infield-in-studio-clear-measurements.png

备注

Expected Post-Correction Metrics 的值大于 Camera Metrics 下的值并非异常。这是因为 Expected Post-Correction Metrics 是根据现场校正数据集中使用的大部分FOV和距离范围给出的。另一方面, Camera Metrics 是根据标定板所覆盖的FOV以及与标定板的距离的捕获而计算出的*局部*尺寸准确度误差。

最后,通过单击 Save Correction to Camera 在相机上应用现场校正结果。

../../../_images/infield-in-studio-save.png
潜在问题

如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:

  1. 标定板在X、Y或Z平面上过于倾斜。

  2. 并非所有特征点都是可检测的。

  3. 基准标记不可见。

  4. 标定板的图像质量太差,无法提供足够的数据。

../../../_images/infield-in-studio-issue-1.png ../../../_images/infield-in-studio-issue-2.png ../../../_images/infield-in-studio-issue-3.png ../../../_images/infield-in-studio-issue-4.png

使用命令行运行带有输入参数 correct 的校正功能(不要忘记在Zivid Studio中断开与相机的连接):

ZividExperimentalInfieldCorrection correct

潜在问题

如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:

  1. 标定板在X、Y或Z平面上过于倾斜。

  2. 并非所有特征点都是可检测的。

  3. 基准标记不可见。

  4. 标定板的图像质量太差,无法提供足够的数据。

备注

预期的校正后尺寸精度误差大于每次捕获测量的值并不意外。这是因为预期的校正后指标是根据现场校正数据集中使用的大部分FOV和距离范围计算出来的。另一方面,捕获测量值是根据标定板覆盖的FOV和与板的距离的捕获计算出的*局部*尺寸准确度误差。

通过SDK对相机执行现场标定时,首先需要连接到相机(不要忘记在Zivid Studio中断开与相机的连接)。

跳转到源码

源码

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()

然后,将相机对准Zivid标定板并收集数据以进行现场校正。

跳转到源码

源码

std::vector<Zivid::Experimental::Calibration::InfieldCorrectionInput> dataset;
std::cout << "Please point the camera at a Zivid infield calibration board. " << std::endl;

const std::string printLine = "------------------------------------------------------------------------";
while(true)
{
    std::cout << printLine << std::endl;
    if(yesNoPrompt("Capture (y) or finish (n)?"))
    {
        std::cout << "Capturing calibration board" << std::endl;
        const auto detectionResult = Zivid::Calibration::detectCalibrationBoard(camera);
        const auto input = Zivid::Experimental::Calibration::InfieldCorrectionInput{ detectionResult };

        if(input.valid())
        {
            dataset.emplace_back(input);
            std::cout << "Valid measurement at: " << input.detectionResult().centroid() << std::endl;
        }
        else
        {
            std::cout << "****INVALID****" << std::endl;
            std::cout << "Feedback: " << input.statusDescription() << std::endl;
        }
        std::cout << printLine << std::endl;
    }
    else
    {
        std::cout << "End of capturing stage." << std::endl;
        std::cout << printLine << std::endl;
        break;
    }
    std::cout << "You have collected " << dataset.size() << " valid measurements so far." << std::endl;
}
跳转到源码

源码

var dataset = new List<Zivid.NET.Experimental.Calibration.InfieldCorrectionInput>();
Console.WriteLine("Please point the camera at a Zivid infield calibration board.");

const string printLine = "------------------------------------------------------------------------";
while (true)
{
    Console.WriteLine(printLine);
    if (YesNoPrompt("Capture (y) or finish (n)?"))
    {
        Console.WriteLine("Capturing calibration board");
        var detectionResult = Zivid.NET.Calibration.Detector.DetectCalibrationBoard(camera);
        var input = new Zivid.NET.Experimental.Calibration.InfieldCorrectionInput(detectionResult);

        if (input.Valid)
        {
            dataset.Add(input);
            Console.WriteLine("Valid measurement at: " + input.DetectionResult.Centroid().ToString());
        }
        else
        {
            Console.WriteLine("****INVALID****");
            Console.WriteLine("Feedback: " + input.StatusDescription());
        }
        Console.WriteLine(printLine);
    }
    else
    {
        Console.WriteLine("End of capturing stage.");
        Console.WriteLine(printLine);
        break;
    }
    Console.WriteLine("You have collected " + dataset.Count + " valid measurements so far.");
}
跳转到源码

源码

dataset = []
print("Please point the camera at a Zivid infield calibration board. ")

print_line = "------------------------------------------------------------------------"
while True:
    print(print_line)
    if _yes_no_prompt("Capture (y) or finish (n)? "):
        print("Capturing calibration board")
        detection_result = zivid.calibration.detect_calibration_board(camera)
        infield_input = zivid.experimental.calibration.InfieldCorrectionInput(detection_result)

        if infield_input.valid():
            dataset.append(infield_input)
        else:
            print("****INVALID****")
            print(f"Feedback: {infield_input.status_description()}")

        print(print_line)
    else:
        print("End of capturing stage.")
        print(print_line)
        break

    print(f"You have collected {len(dataset)} valid measurements so far.")

跳转到源码

源码

std::cout << "Computing new camera correction..." << std::endl;
const auto correction = Zivid::Experimental::Calibration::computeCameraCorrection(dataset);
跳转到源码

源码

Console.WriteLine("Computing new camera correction...");
var correction = Zivid.NET.Experimental.Calibration.Calibrator.ComputeCameraCorrection(dataset);
跳转到源码

源码

print("Computing new camera correction...")
correction = zivid.experimental.calibration.compute_camera_correction(dataset)

在应用新的标定数据之前,请先估计新校正的预期尺寸精度误差。

跳转到源码

源码

const auto accuracyEstimate = correction.accuracyEstimate();
std::cout
    << "If written to the camera, this correction can be expected to yield a dimension accuracy error of "
    << std::fixed << std::setprecision(2) << 100.0F * accuracyEstimate.dimensionAccuracy()
    << "% or better in the range of z=[" << static_cast<int>(std::round(accuracyEstimate.zMin())) << ","
    << static_cast<int>(std::round(accuracyEstimate.zMax()))
    << "] across the full FOV. Accuracy close to where the correction data was collected is likely better."
    << std::endl;
跳转到源码

源码

var accuracyEstimate = correction.AccuracyEstimate;
Console.WriteLine("If written to the camera, this correction can be expected to yield a dimension accuracy error of "
        + (accuracyEstimate.DimensionAccuracy * 100).ToString("0.00") + "% or better in the range of z=["
        + accuracyEstimate.ZMin.ToString("0.00") + "," + accuracyEstimate.ZMax.ToString("0.00")
        + "] across the full FOV. Accuracy close to where the correction data was collected is likely better.");
跳转到源码

源码

accuracy_estimate = correction.accuracy_estimate()

print(
    "If written to the camera, this correction can be expected to yield a dimension accuracy error of",
    f"{accuracy_estimate.dimension_accuracy() * 100:.3f}% or better in the range of z=[{accuracy_estimate.z_min():.3f}, {accuracy_estimate.z_max():.3f}] across the full FOV.",
    "Accuracy close to where the correction data was collected is likely better.",
)

完成此过程返回的信息包括:

  1. 最新计算出的FOV大部分区域的最大尺寸真实度误差。

  2. 该误差的范围取决于拍摄校正图像的距离。

如果对校正的结果满意,请选择将校正参数应用于相机。

备注

预期的校正后尺寸精度误差大于每次捕获测量的值并不意外。这是因为预期的校正后指标是根据现场校正数据集中使用的大部分FOV和距离范围计算出来的。另一方面,捕获测量值是根据标定板覆盖的FOV和与板的距离的捕获计算出的*局部*尺寸准确度误差。

最后,在相机上应用现场校正结果。

跳转到源码

源码

std::cout << "Writing camera correction..." << std::endl;
Zivid::Experimental::Calibration::writeCameraCorrection(camera, correction);
跳转到源码

源码

Console.WriteLine("Writing camera correction...");
Zivid.NET.Experimental.Calibration.Calibrator.WriteCameraCorrection(camera, correction);
跳转到源码

源码

print("Writing correction to camera")
zivid.experimental.calibration.write_camera_correction(camera, correction)

潜在问题

如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:

  1. 标定板在X、Y或Z平面上过于倾斜。

  2. 并非所有特征点都是可检测的。

  3. 基准标记不可见。

  4. 标定板的图像质量太差,无法提供足够的数据。

Read(读取)

可以查看最后一次校正写入相机的日期和时间。

Camera 部分会始终显示最后一次校正应用于相机的时间。

../../../_images/infield-in-studio-last-correction.png

使用输入参数 read 来查看最后一次校正何时应用于相机。

ZividExperimentalInfieldCorrection read

使用读取功能查看上次对相机应用校正的时间。

跳转到源码

源码

if(Zivid::Experimental::Calibration::hasCameraCorrection(camera))
{
    const auto timestamp = Zivid::Experimental::Calibration::cameraCorrectionTimestamp(camera);
    const auto time = std::chrono::system_clock::to_time_t(timestamp);
    std::cout << "Timestamp of current camera correction: " << std::put_time(std::gmtime(&time), "%FT%TZ")
              << std::endl;
}
else
{
    std::cout << "This camera has no infield correction written to it." << std::endl;
}
跳转到源码

源码

if (Zivid.NET.Experimental.Calibration.Calibrator.HasCameraCorrection(camera))
{
    var timestamp = Zivid.NET.Experimental.Calibration.Calibrator.CameraCorrectionTimestamp(camera);
    Console.WriteLine("Timestamp of curent camera correction: " + timestamp.ToString());
}
else
{
    Console.WriteLine("This camera has no infield correction written to it.");
}
跳转到源码

源码

if zivid.experimental.calibration.has_camera_correction(camera):
    timestamp = zivid.experimental.calibration.camera_correction_timestamp(camera)
    print(f"Timestamp of current camera correction: {timestamp.strftime(r'%Y-%m-%d %H:%M:%S')}")
else:
    print("This camera has no infield correction written to it.")

Reset(重置)

可以删除已应用于相机的校正结果。在测试和应用新的校正之前,没有必要删除校正结果。

Camera 部分,单击三个点。然后,点击 Reset Camera Correction

../../../_images/infield-in-studio-reset-correction.png

使用输入参数 reset 来删除已应用于相机的校正结果。

ZividExperimentalInfieldCorrection reset

使用重置功能删除已应用于相机的校正结果。

跳转到源码

源码

std::cout << "Reset infield correction on the camera" << std::endl;
Zivid::Experimental::Calibration::resetCameraCorrection(camera);
跳转到源码

源码

Console.WriteLine("Reset infield correction on the camera");
Zivid.NET.Experimental.Calibration.Calibrator.ResetCameraCorrection(camera);
跳转到源码

源码

print("Reset infield correction on the camera")
zivid.experimental.calibration.reset_camera_correction(camera)

备注

Zivid在新相机发货前已对其进行了现场标定。该重置功能也会清除该校正结果,将相机重置为仅具有出厂标定的状态。我们建议您在您的环境中进行现场标定以获得最佳的性能。

版本历史

SDK

变更

2.11.0

添加了对 Python 的支持。