Intrinsically & extrinsically calibrate point clouds using a laser triangulation sensor
The following describes an example workflow in CVB.Net
to:
- reconstruct an intrinsically calibrated point cloud from a range map and an intrinsic calibration file
- extrinsically calibrate a system using an AQS12 calibration target
- create a rectified range map from the calibrated point cloud
using Stemmer.Cvb;
using Stemmer.Cvb.Foundation;
namespace cvbNet_ExtrinsicCalibration_Console
{
class Program
{
static void Main(string[] args)
{
// load range map
var rangemap = Image.FromFile(@"%CVB%\Tutorial\Metric\Images\RangeMap_CalibrationPattern.tif");
// load intrinsic calibration (e.g. from an AT compact sensor)
var calibrator = Calibrator3D.FromFile(Environment.ExpandEnvironmentVariables(@"%cvb%\Tutorial\Metric\Images\Test.xml"));
// reconstruct point cloud without extrinsic calibration
PointCloud pointCloud = calibrator.CreatePointCloud(rangemap, PointCloudFlags.Double);
pointCloud.Save(Environment.ExpandEnvironmentVariables(@"%cvb%\Tutorial\Metric\Images\PointCloud.ply"));
// set pattern points
AQS12Piece aqs12 = new AQS12Piece();
aqs12.TopBasePlaneDistance = 60;
aqs12.ReferencePoints[0] = new Point3Dd(0, 40, 60);
aqs12.ReferencePoints[1] = new Point3Dd(10, 53, 60);
aqs12.ReferencePoints[2] = new Point3Dd(10, 96, 60);
aqs12.ReferencePoints[3] = new Point3Dd(0, 110, 60);
aqs12.ReferencePoints[4] = new Point3Dd(-10, 96, 60);
aqs12.ReferencePoints[5] = new Point3Dd(-10, 53, 60);
aqs12.ReferencePoints[6] = new Point3Dd(0, 0, 30);
aqs12.ReferencePoints[7] = new Point3Dd(30, 40, 30);
aqs12.ReferencePoints[8] = new Point3Dd(30, 110, 30);
aqs12.ReferencePoints[9] = new Point3Dd(0, 150, 30);
aqs12.ReferencePoints[10] = new Point3Dd(-30, 110, 30);
aqs12.ReferencePoints[11] = new Point3Dd(-30, 40, 30);
// perform calibration
Point3Dd[] residuals = new Point3Dd[12];
calibrator.ExtrinsicMatrix = Metric.ExtrinsicTransformationFromPiece(rangemap.Planes[0], aqs12, calibrator, out residuals);
calibrator.Save(Environment.ExpandEnvironmentVariables(@"%cvb%\Tutorial\Metric\Images\TestOut.json"));
// reconstruct point cloud with extrinsic calibration
PointCloud calibratedPointCloud = calibrator.CreatePointCloud(rangemap, PointCloudFlags.Double);
calibratedPointCloud.Save(Environment.ExpandEnvironmentVariables(@"%cvb%\Tutorial\Metric\Images\calibratedPointCloud.ply"));
//create rectified range map
//(parameters for rectification can be set differently)
var boundingBox = calibratedPointCloud.CalculateBoundingBox();
ValueRange<double> xRange = new ValueRange<double>(double.MinValue, double.MaxValue);
ValueRange<double> yRange = new ValueRange<double>(double.MinValue, double.MaxValue);
xRange.Min = boundingBox.X.Min;
xRange.Max = boundingBox.X.Max;
yRange.Min = boundingBox.Y.Min;
yRange.Max = boundingBox.Y.Max;
int targetWidth = rangemap.Width;
int targetHeight = rangemap.Height;
double bgValue = boundingBox.Z.Min - 10;
var rectifiedRangemap = calibratedPointCloud.ToRangeMap(xRange, yRange, targetWidth, targetHeight, bgValue);
rectifiedRangemap.Save(Environment.ExpandEnvironmentVariables(@"%cvb%\Tutorial\Metric\Images\rectifiedRangemap.tiff"));
}
}
}