运行现场标定

介绍

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

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

备注

This reset will also clear the current correction, resetting the camera to have only the factory calibration. We recommend that you do infield correction in your environment for optimal performance.

版本历史

SDK

变更

2.11.0

添加了对 Python 的支持。