运行现场标定
介绍
如需在相机上运行现场验证和/或校正,您可以使用:
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)捕获模式来观察捕获情况以正确地对齐标定板。将棋盘格放置在您想要成像的区域中最近距离处,作为现场标定数据集的第一次捕获。使标定板尽可能地平行于相机坐标系,并确保整个标定板在相机坐标系中可见。
然后,打开现场标定工具(Infield Correction)。在工具栏中,单击 Tools → Infield Correction 。
单击 Capture & Measure 以验证所连接相机的局部尺寸准确度误差。
结果将显示在 Current Camera Metrics 下:
使用命令行运行带有输入参数 verify
的验证功能(不要忘记在Zivid Studio中断开与相机的连接):
ZividExperimentalInfieldCorrection verify
潜在问题
如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:
标定板在X、Y或Z平面上过于倾斜。
并非所有特征点都是可检测的。
基准标记不可见。
标定板的图像质量太差,无法提供足够的数据。
如需通过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}%"
)
潜在问题
如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:
标定板在X、Y或Z平面上过于倾斜。
并非所有特征点都是可检测的。
基准标记不可见。
标定板的图像质量太差,无法提供足够的数据。
Correct(校正)
在相机上执行现场标定时,请在FOV中的不同距离和不同位置单击 Capture & Measure 来收集数据,如同 进行现场标定的准则 中所描述的那样。
当您进行现场标定捕获时,您将看到给定捕获次数的预期尺寸精度误差(如果您要应用校正)。
完成此过程返回的信息包括:
最新计算出的FOV大部分区域的最大尺寸真实度误差。
该误差的范围取决于拍摄校正图像的距离。
如果对校正的结果满意,请选择将校正参数应用于相机。
备注
Expected Post-Correction Metrics 的值大于 Camera Metrics 下的值并非异常。这是因为 Expected Post-Correction Metrics 是根据现场校正数据集中使用的大部分FOV和距离范围给出的。另一方面, Camera Metrics 是根据标定板所覆盖的FOV以及与标定板的距离的捕获而计算出的*局部*尺寸准确度误差。
最后,通过单击 Save Correction to Camera 在相机上应用现场校正结果。
使用命令行运行带有输入参数 correct
的校正功能(不要忘记在Zivid Studio中断开与相机的连接):
ZividExperimentalInfieldCorrection correct
潜在问题
如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:
标定板在X、Y或Z平面上过于倾斜。
并非所有特征点都是可检测的。
基准标记不可见。
标定板的图像质量太差,无法提供足够的数据。
备注
预期的校正后尺寸精度误差大于每次捕获测量的值并不意外。这是因为预期的校正后指标是根据现场校正数据集中使用的大部分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.",
)
完成此过程返回的信息包括:
最新计算出的FOV大部分区域的最大尺寸真实度误差。
该误差的范围取决于拍摄校正图像的距离。
如果对校正的结果满意,请选择将校正参数应用于相机。
备注
预期的校正后尺寸精度误差大于每次捕获测量的值并不意外。这是因为预期的校正后指标是根据现场校正数据集中使用的大部分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)
潜在问题
如果标定板偏离方向太远或捕获质量太差导致无法提供足够的数据,您将被告知存在潜在的设置问题:
标定板在X、Y或Z平面上过于倾斜。
并非所有特征点都是可检测的。
基准标记不可见。
标定板的图像质量太差,无法提供足够的数据。
Read(读取)
可以查看最后一次校正写入相机的日期和时间。
使用输入参数 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(重置)
可以删除已应用于相机的校正结果。在测试和应用新的校正之前,没有必要删除校正结果。
使用输入参数 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 的支持。 |