Camera Calibration and Capture Bounds in C# (AR51.Net)
Run a camera calibration from your app, follow its progress, read the result — and read or set the tracked area (capture bounds).
Starting a calibration from code doesn't change how it's done: someone still walks the lit calibration sphere through the capture area. See Camera calibration for good technique.
Run a calibration
Tracking keeps running on the current calibration while a calibration runs. When it succeeds, it replaces every camera's calibration for every app connected to the AR 51 system; if it fails or is cancelled, the current calibration stays.
A calibration ends by itself once it has collected enough data. Subscribe to the events, then start it:
ar51.Calibration.CalibrationProgressChanged += (_, e) =>
Console.WriteLine($"{e.Status.Progress:P0}, error {e.Status.ReprojectionErrorPixels:F2} px {e.Status.Message}");
ar51.Calibration.CalibrationEnded += (_, e) =>
Console.WriteLine($"calibration {e.Result.Outcome}, error {e.Result.ReprojectionErrorPixels:F2} px");
await ar51.Calibration.StartCalibrationAsync();
- Progress runs from 0 to 1. Reprojection error is in pixels — lower is better.
- To finish now, call
StopCalibrationAsync. It stops the running calibration — whoever started it, including one an operator started in Mocap Studio — and returns the result. Stopped before it has enough data, it ends asCancelledand the cameras keep their previous values. - Starting one while another is running throws
AR51ExceptionwithRejected.
If your client is stopped or disposed — for example the app shuts down — before the calibration ends, the calibration is cancelled.
The result
| Outcome | Meaning |
|---|---|
Succeeded | The calibration succeeded; GetCamerasAsync returns the new values |
Failed | The calibration failed; the cameras keep their previous values |
Cancelled | Stopped before it had enough data; the cameras keep their previous values |
Unknown | The calibration was started by another app, or none was running |
The events report every calibration, whoever started it (your app, Mocap Studio or another client). The outcome is known only for a calibration your client started.
Capture bounds
The tracked area — the capture-area bounding box — is a box in the AR 51 world (meters): people outside it are not tracked.
CaptureBounds bounds = await ar51.Calibration.GetCaptureBoundsAsync();
Console.WriteLine($"center {bounds.Center} m, size {bounds.Size} m");
SetCaptureBoundsAsync applies immediately, and anyone outside the new box stops being tracked. Double-check the values first.
await ar51.Calibration.SetCaptureBoundsAsync(bounds with { Size = new Vector3(6, 2.5f, 6) });
CaptureBounds also gives you Min, Max and Contains(point).
Complete sample
Run a calibration and follow its progress. It ends by itself once it has enough data; Ctrl+C stops it now (before it has enough data, that ends as Cancelled).
// Run a camera calibration and follow its progress. It ends by itself once it has enough data; Ctrl+C finishes it now.
using AR51.Net;
await using IAR51Client ar51 = AR51Client.Create();
var ended = new TaskCompletionSource<CalibrationResult>(TaskCreationOptions.RunContinuationsAsynchronously);
ar51.Calibration.CalibrationStarted += (_, e) => Console.WriteLine("Calibration started. Move the lit calibration sphere through the whole area.");
ar51.Calibration.CalibrationProgressChanged += (_, e) =>
Console.WriteLine($"{e.Status.Progress:P0}, error {e.Status.ReprojectionErrorPixels:F2} px {e.Status.Message}");
ar51.Calibration.CalibrationEnded += (_, e) => ended.TrySetResult(e.Result);
await ar51.StartAsync();
await ar51.Calibration.StartCalibrationAsync();
Console.CancelKeyPress += async (_, e) =>
{
e.Cancel = true;
CalibrationResult result = await ar51.Calibration.StopCalibrationAsync(); // "finish now"
ended.TrySetResult(result);
};
CalibrationResult final = await ended.Task;
Console.WriteLine($"Calibration ended: {final.Outcome}, error {final.ReprojectionErrorPixels:F2} px");
if (final.Outcome == CalibrationOutcome.Succeeded)
Console.WriteLine("The cameras' new calibration values are in ar51.Cameras.GetCamerasAsync().");
View this sample on Bitbucket — clone the samples repository to run it.
Reference
ICalibrationClient · CalibrationStatus · CalibrationResult · CaptureBounds