/// <summary> /// Initializes and configure the <see cref="CameraParametersController.CameraParameters"/>. /// </summary> /// <param name="calibrationFlags">The calibration flags that will be used in <see cref="Calibrate"/>.</param> protected virtual void InitializeCameraParameters(CameraCalibrationFlags calibrationFlags = null) { if (calibrationFlags != null && calibrationFlags.UseIntrinsicGuess) { if (CameraParametersController.CameraParameters == null || CameraParametersController.CameraParameters.CameraMatrices == null) { throw new Exception("CalibrationFlags.UseIntrinsicGuess flag is set but CameraParameters is null or has no valid values. Set" + " CameraParametersFilename or deactivate this flag."); } } else { CameraParametersController.Initialize(ArucoCamera.CameraNumber); for (int cameraId = 0; cameraId < ArucoCamera.CameraNumber; cameraId++) { CameraParametersController.CameraParameters.CameraMatrices[cameraId] = new Cv.Mat(); CameraParametersController.CameraParameters.DistCoeffs[cameraId] = new Cv.Mat(); CameraParametersController.CameraParameters.OmnidirXis[cameraId] = new Cv.Mat(); } } CameraParametersController.CameraParameters.CalibrationFlagsValue = (calibrationFlags != null) ? calibrationFlags.CalibrationFlagsValue : default(int); for (int cameraId = 0; cameraId < ArucoCamera.CameraNumber; cameraId++) { CameraParametersController.CameraParameters.ImageHeights[cameraId] = calibrationImageSizes[cameraId].Height; CameraParametersController.CameraParameters.ImageWidths[cameraId] = calibrationImageSizes[cameraId].Width; } }
/// <summary> /// Calibrates each camera of the <see cref="ArucoObjectDetector.ArucoCamera"/> system using the detected markers added with /// <see cref="AddCurrentFrameForCalibration()"/>, the <see cref="CameraParameters"/>, the <see cref="ArucoCameraUndistortion"/> and save /// the results on a calibration file. Stereo calibrations will be additionally executed on these results for every camera pair in /// <see cref="StereoCalibrationCameraPairs"/>. /// </summary> public virtual void Calibrate() { if (!IsConfigured) { throw new Exception("Configure the calibration controller before starting the calibration."); } // Update state calibratingMutex.WaitOne(); { IsCalibrated = false; CalibrationRunning = true; } calibratingMutex.ReleaseMutex(); // Check if there is enough captured frames for calibration Aruco.CharucoBoard charucoBoard = CalibrationBoard.Board as Aruco.CharucoBoard; for (int cameraId = 0; cameraId < ArucoCamera.CameraNumber; cameraId++) { if (charucoBoard == null && MarkerIds[cameraId].Size() < 3) { throw new Exception("Need at least three frames captured for the camera " + (cameraId + 1) + "/" + ArucoCamera.CameraNumber + " to calibrate."); } else if (charucoBoard != null && MarkerIds[cameraId].Size() < 4) { throw new Exception("Need at least four frames captured for the camera " + (cameraId + 1) + "/" + ArucoCamera.CameraNumber + " to calibrate with a ChAruco board."); } } InitializeCameraParameters(); // Initialize and configure the camera parameters // Get objet and image calibration points from detected ids and corners Std.VectorVectorPoint2f[] imagePoints = new Std.VectorVectorPoint2f[ArucoCamera.CameraNumber]; Std.VectorVectorPoint3f[] objectPoints = new Std.VectorVectorPoint3f[ArucoCamera.CameraNumber]; for (int cameraId = 0; cameraId < ArucoCamera.CameraNumber; cameraId++) { imagePoints[cameraId] = new Std.VectorVectorPoint2f(); objectPoints[cameraId] = new Std.VectorVectorPoint3f(); uint frameCount = MarkerCorners[cameraId].Size(); for (uint frame = 0; frame < frameCount; frame++) { Std.VectorPoint2f frameImagePoints; Std.VectorPoint3f frameObjectPoints; if (charucoBoard == null) { // Using a grid board Aruco.GetBoardObjectAndImagePoints(CalibrationBoard.Board, MarkerCorners[cameraId].At(frame), MarkerIds[cameraId].At(frame), out frameObjectPoints, out frameImagePoints); } else { // Using a charuco board Std.VectorInt charucoIds; Aruco.InterpolateCornersCharuco(MarkerCorners[cameraId].At(frame), MarkerIds[cameraId].At(frame), CalibrationImages[cameraId].At(frame), charucoBoard, out frameImagePoints, out charucoIds); // Join the object points corresponding to the detected markers frameObjectPoints = new Std.VectorPoint3f(); uint markerCount = charucoIds.Size(); for (uint marker = 0; marker < markerCount; marker++) { uint pointId = (uint)charucoIds.At(marker); Cv.Point3f objectPoint = charucoBoard.ChessboardCorners.At(pointId); frameObjectPoints.PushBack(objectPoint); } } imagePoints[cameraId].PushBack(frameImagePoints); objectPoints[cameraId].PushBack(frameObjectPoints); } } // Calibrate the Aruco camera Calibrate(imagePoints, objectPoints); // Save the camera parameters CameraParametersController.CameraParametersFilename = ArucoCamera.Name + " - " + CameraParametersController.CameraParameters.CalibrationDateTime.ToString("yyyy-MM-dd_HH-mm-ss") + ".xml"; CameraParametersController.Save(); // Update state calibratingMutex.WaitOne(); { IsCalibrated = true; } calibratingMutex.ReleaseMutex(); }