Beispiel #1
0
        public static Dictionary GetPredefinedDictionary(PredefinedDictionaryName name)
        {
            Dictionary dictionary = new Dictionary(au_getPredefinedDictionary(name));

            dictionary.Name = name;
            return(dictionary);
        }
 public ChArUcoImageContainer(int squaresX, int squaresY, float squareLength, float markerLength, PredefinedDictionaryName dictionary)
 {
     _SquaresX     = squaresX;
     _SquaresY     = squaresY;
     _SquareLength = squareLength;
     _MarkerLength = markerLength;
     _Dictionary   = dictionary;
 }
 private void _Timer_Elapsed(object sender, ElapsedEventArgs e)
 {
     Parent.SyncContext.Post(o =>
     {
         if (AutoSnapshot)
         {
             int squaresX       = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresX;
             int squaresY       = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresY;
             float squareLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquareLength;
             float markerLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.MarkerLength;
             PredefinedDictionaryName dictionary = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.Dictionary;
             ChArUcoImageContainer cauic         = new ChArUcoImageContainer(squaresX, squaresY, squareLength, markerLength, dictionary);
             cauic.OriginalImage = Parent.CameraViewModel.Image;
             Images.Add(cauic);
         }
     }, null);
 }
        private Task DoTakeSnapshot(object o)
        {
            return(Task.Factory.StartNew(() =>
            {
                Parent.SyncContext.Post(c =>
                {
                    int squaresX = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresX;
                    int squaresY = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresY;
                    float squareLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquareLength;
                    float markerLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.MarkerLength;
                    PredefinedDictionaryName dictionary = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.Dictionary;

                    ChArUcoImageContainer cauic = new ChArUcoImageContainer(squaresX, squaresY, squareLength, markerLength, dictionary);
                    cauic.OriginalImage = Parent.CameraViewModel.Image;
                    Images.Add(cauic);
                }, null);
            }));
        }
Beispiel #5
0
 /// <summary>
 /// Returns one of the predefined dictionaries defined in PREDEFINED_DICTIONARY_NAME
 /// </summary>
 /// <param name="name"></param>
 /// <returns></returns>
 public static Dictionary GetPredefinedDictionary(PredefinedDictionaryName name)
 {
     NativeMethods.HandleException(
         NativeMethods.aruco_getPredefinedDictionary((int)name, out IntPtr p));
     return(new Dictionary(p));
 }
        private Task DoValidate(object o)
        {
            return(Task.Factory.StartNew(() =>
            {
                Parent.SyncContext.Post(async c =>
                {
                    VectorOfInt allIds = new VectorOfInt();
                    VectorOfVectorOfPointF allCorners = new VectorOfVectorOfPointF();
                    VectorOfInt allCharucoIds = new VectorOfInt();
                    VectorOfPointF allCharucoCorners = new VectorOfPointF();
                    VectorOfInt markerCounterPerFrame = new VectorOfInt();
                    VectorOfInt charucoCounterPerFrame = new VectorOfInt();
                    int squaresX = 0;
                    int squaresY = 0;
                    float squareLength = 0f;
                    float markerLength = 0f;
                    PredefinedDictionaryName dictionary = PredefinedDictionaryName.Dict4X4_50;
                    System.Drawing.Size size = new System.Drawing.Size();

                    bool fisheye = false;

                    Parent.SyncContext.Send(async d =>
                    {
                        fisheye = Parent.CameraViewModel.FishEyeCalibration;

                        squaresX = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresX;
                        squaresY = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresY;
                        squareLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquareLength;
                        markerLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.MarkerLength;
                        dictionary = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.Dictionary;
                        size = new System.Drawing.Size(Parent.CameraViewModel.ImageWidth, Parent.CameraViewModel.ImageHeight);

                        foreach (ChArUcoImageContainer image in Images)
                        {
                            if (image.MarkerCorners != null && image.CharucoCorners.Size > 4)
                            {
                                allIds.Push(image.MarkerIds);
                                allCorners.Push(image.MarkerCorners);
                                allCharucoIds.Push(image.CharucoIds);
                                allCharucoCorners.Push(image.CharucoCorners);
                                markerCounterPerFrame.Push(new int[] { image.MarkerCorners.Size });
                                charucoCounterPerFrame.Push(new int[] { image.CharucoCorners.Size });
                            }
                        }
                    }, null);

                    if (markerCounterPerFrame.Size > 0)
                    {
                        MetroDialogSettings settings = new MetroDialogSettings()
                        {
                            AnimateShow = false,
                            AnimateHide = false
                        };

                        var controller = await Parent.DialogCoordinator.ShowProgressAsync(Parent, "Please wait...", "Validate parameter now!", settings: Parent.MetroDialogSettings);
                        controller.SetIndeterminate();
                        controller.SetCancelable(false);

                        bool error = false;
                        double rms = 0.0;
                        try
                        {
                            Mat cameraMatrix = new Mat(3, 3, Emgu.CV.CvEnum.DepthType.Cv64F, 1);
                            Mat distCoeffs = new Mat(1, Parent.CameraViewModel.FishEyeCalibration ? 4 : _DistCoeffs.Count, Emgu.CV.CvEnum.DepthType.Cv64F, 1);

                            cameraMatrix.SetValue(0, 0, Fx);
                            cameraMatrix.SetValue(1, 1, Fy);
                            cameraMatrix.SetValue(0, 1, Fx * Alpha);
                            cameraMatrix.SetValue(0, 2, Cx);
                            cameraMatrix.SetValue(1, 2, Cy);
                            cameraMatrix.SetValue(2, 2, 1.0f);

                            for (int i = 0; i < distCoeffs.Cols && (Parent.CameraViewModel.FishEyeCalibration ? i < 4 : true); i++)
                            {
                                distCoeffs.SetValue(0, i, _DistCoeffs[i]);
                            }

                            rms = ChArUcoCalibration.ValidateCharuco(squaresX, squaresY, squareLength, markerLength, dictionary, size, allCharucoIds, allCharucoCorners, charucoCounterPerFrame, fisheye, delegate(byte[] input)
                            {
                                return Parent.IOProxy.GetRemoteChessboardCorner(input);
                            }, cameraMatrix, distCoeffs);
                        }
                        catch (Exception ex)
                        {
                            error = true;
                        }

                        await controller.CloseAsync();
                        if (!error)
                        {
                            var con = await Parent.DialogCoordinator.ShowMessageAsync(Parent, "Result", string.Format("RMS: {0}", rms), MessageDialogStyle.Affirmative, null);
                        }
                        else
                        {
                            await Parent.DialogCoordinator.ShowMessageAsync(Parent, "Error", "Error during validation!");
                        }
                    }
                    else
                    {
                        await Parent.DialogCoordinator.ShowMessageAsync(Parent, "Error", "Not enough valide input frames available!");
                    }
                }, null);
            }));
        }
        private Task DoLoadFromFile(object o)
        {
            return(Task.Factory.StartNew(() =>
            {
                Parent.SyncContext.Post(c =>
                {
                    CustomDialog customDialog = new CustomDialog()
                    {
                        Title = "Select calibration file"
                    };

                    var dataContext = new ReplaySelectDialogModel(obj =>
                    {
                        Parent.SyncContext.Post(d =>
                        {
                            Task.Factory.StartNew(async() =>
                            {
                                ReplaySelectDialogModel replaySelectDialogModel = obj as ReplaySelectDialogModel;
                                if (replaySelectDialogModel.SelectedFile != null)
                                {
                                    MetroDialogSettings settings = new MetroDialogSettings()
                                    {
                                        AnimateShow = false,
                                        AnimateHide = false
                                    };
                                    var controller = await Parent.DialogCoordinator.ShowProgressAsync(Parent, "Please wait...", "Loading calibration images!", settings: Parent.MetroDialogSettings);
                                    controller.SetCancelable(false);
                                    controller.SetIndeterminate();

                                    string file = null;
                                    string outputPath = null;

                                    Parent.SyncContext.Send(async d2 =>
                                    {
                                        file = replaySelectDialogModel.SelectedFile.FullPath;
                                        outputPath = Path.Combine(Path.GetTempPath(), "firefly", Guid.NewGuid().ToString());
                                    }, null);

                                    RawDataReader reader = new RawDataReader(file, RawReaderMode.Camera0);
                                    reader.Open();
                                    MemoryImageExporter exporter = new MemoryImageExporter();
                                    exporter.AddFromReader(reader, delegate(double percent)
                                    {
                                        double value = percent;
                                        value = value > 1 ? 1 : value;
                                        controller.SetProgress(value);
                                    });

                                    reader.Close();

                                    Parent.SyncContext.Post(d2 =>
                                    {
                                        int i = 0;
                                        int count = exporter.Images.Count;
                                        foreach (Mat m in exporter.Images)
                                        {
                                            //double value = 0.5 + i / count * 0.5;
                                            //value = value > 1 ? 1 : value;
                                            //controller.SetProgress(value);

                                            if (i++ % 20 == 0)
                                            {
                                                int squaresX = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresX;
                                                int squaresY = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresY;
                                                float squareLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquareLength;
                                                float markerLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.MarkerLength;
                                                PredefinedDictionaryName dictionary = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.Dictionary;

                                                ChArUcoImageContainer cauic = new ChArUcoImageContainer(squaresX, squaresY, squareLength, markerLength, dictionary);
                                                CvImageContainer container = new CvImageContainer();
                                                container.CvImage = m;
                                                cauic.OriginalImage = container;
                                                Images.Add(cauic);
                                            }
                                        }

                                        controller.CloseAsync();
                                    }, null);
                                }
                            }, TaskCreationOptions.LongRunning);
                            Parent.DialogCoordinator.HideMetroDialogAsync(Parent, customDialog);
                        }, null);
                    });
                    Parent.ReplayViewModel.Refresh();
                    dataContext.FilesForReplay.AddRange(Parent.ReplayViewModel.FilesForReplay.Where(x => !x.Item1.IsRemote));
                    customDialog.Content = new ReplaySelectDialog {
                        DataContext = dataContext
                    };

                    Parent.DialogCoordinator.ShowMetroDialogAsync(Parent, customDialog);
                }, null);
            }));
        }
        private Task DoCalibrate(object o)
        {
            return(Task.Factory.StartNew(async() =>
            {
                VectorOfInt allIds = new VectorOfInt();
                VectorOfVectorOfPointF allCorners = new VectorOfVectorOfPointF();
                VectorOfInt allCharucoIds = new VectorOfInt();
                VectorOfPointF allCharucoCorners = new VectorOfPointF();
                VectorOfInt markerCounterPerFrame = new VectorOfInt();
                VectorOfInt charucoCounterPerFrame = new VectorOfInt();
                int squaresX = 0;
                int squaresY = 0;
                float squareLength = 0f;
                float markerLength = 0f;
                PredefinedDictionaryName dictionary = PredefinedDictionaryName.Dict4X4_50;
                System.Drawing.Size size = new System.Drawing.Size();

                bool fisheye = false;

                Parent.SyncContext.Send(async c =>
                {
                    fisheye = Parent.CameraViewModel.FishEyeCalibration;

                    squaresX = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresX;
                    squaresY = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquaresY;
                    squareLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.SquareLength;
                    markerLength = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.MarkerLength;
                    size = Parent.CameraViewModel.Image.CvImage.Size;
                    dictionary = Parent.SettingContainer.Settings.CalibrationSettings.ChArucoCalibrationSettings.Dictionary;
                    foreach (ChArUcoImageContainer image in Images)
                    {
                        if (image.MarkerCorners != null && image.CharucoCorners.Size > 4)
                        {
                            allIds.Push(image.MarkerIds);
                            allCorners.Push(image.MarkerCorners);
                            allCharucoIds.Push(image.CharucoIds);
                            allCharucoCorners.Push(image.CharucoCorners);
                            markerCounterPerFrame.Push(new int[] { image.MarkerCorners.Size });
                            charucoCounterPerFrame.Push(new int[] { image.CharucoCorners.Size });
                        }
                    }
                }, null);

                if (markerCounterPerFrame.Size > 0)
                {
                    MetroDialogSettings settings = new MetroDialogSettings()
                    {
                        AnimateShow = true,
                        AnimateHide = true
                    };

                    var controller = await Parent.DialogCoordinator.ShowProgressAsync(Parent, "Please wait...", "Calculating calibration parameter now!", settings: settings);
                    controller.SetIndeterminate();
                    controller.SetCancelable(false);

                    bool error = false;
                    (Mat cameraMatrix, Mat distCoeffs, double rms)result = (null, null, 0.0);
                    try
                    {
                        result = ChArUcoCalibration.CalibrateCharuco(squaresX, squaresY, squareLength, markerLength, dictionary, size, allCharucoIds, allCharucoCorners, charucoCounterPerFrame, fisheye, delegate(byte[] input)
                        {
                            return Parent.IOProxy.GetRemoteChessboardCorner(input);
                        });
                    }
                    catch (Exception ex)
                    {
                        error = true;
                    }

                    await controller.CloseAsync();
                    if (!error)
                    {
                        var con = await Parent.DialogCoordinator.ShowMessageAsync(Parent, "Result", string.Format("RMS: {0}\nDo you want to save?", result.rms), MessageDialogStyle.AffirmativeAndNegative, null);
                        if (con == MessageDialogResult.Affirmative)
                        {
                            Parent.SyncContext.Post(async c =>
                            {
                                Parent.SettingContainer.Settings.CalibrationSettings.IntrinsicCalibrationSettings.Fx = result.cameraMatrix.GetValue(0, 0);
                                Parent.SettingContainer.Settings.CalibrationSettings.IntrinsicCalibrationSettings.Fy = result.cameraMatrix.GetValue(1, 1);
                                Parent.SettingContainer.Settings.CalibrationSettings.IntrinsicCalibrationSettings.Cx = result.cameraMatrix.GetValue(0, 2);
                                Parent.SettingContainer.Settings.CalibrationSettings.IntrinsicCalibrationSettings.Cy = result.cameraMatrix.GetValue(1, 2);
                                Parent.SettingContainer.Settings.CalibrationSettings.IntrinsicCalibrationSettings.Alpha = result.cameraMatrix.GetValue(0, 1) / result.cameraMatrix.GetValue(0, 0);;

                                Parent.SettingContainer.Settings.CalibrationSettings.IntrinsicCalibrationSettings.DistCoeffs.Clear();

                                if (Parent.CameraViewModel.FishEyeCalibration)
                                {
                                    for (int i = 0; i < result.distCoeffs.Rows && i < 8; i++)
                                    {
                                        Parent.SettingContainer.Settings.CalibrationSettings.IntrinsicCalibrationSettings.DistCoeffs.Add(result.distCoeffs.GetValue(i, 0));
                                    }
                                }
                                else
                                {
                                    for (int i = 0; i < result.distCoeffs.Cols && i < 8; i++)
                                    {
                                        Parent.SettingContainer.Settings.CalibrationSettings.IntrinsicCalibrationSettings.DistCoeffs.Add(result.distCoeffs.GetValue(0, i));
                                    }
                                }

                                Parent.UpdateSettings(false);
                            }, null);
                        }
                    }
                    else
                    {
                        await Parent.DialogCoordinator.ShowMessageAsync(Parent, "Error", "Error during calibration!");
                    }
                }
                else
                {
                    await Parent.DialogCoordinator.ShowMessageAsync(Parent, "Error", "Not enough valide input frames available!");
                }
            }));
        }
        public static (Mat cameraMatrix, Mat distCoeffs, double rms) CalibrateCharuco(int squaresX, int squaresY, float squareLength, float markerLength, PredefinedDictionaryName dictionary, Size imageSize, VectorOfInt charucoIds, VectorOfPointF charucoCorners, VectorOfInt markerCounterPerFrame, bool fisheye, Func <byte[], byte[]> GetRemoteChessboardCorner)
        {
            Mat    cameraMatrix = new Mat(3, 3, Emgu.CV.CvEnum.DepthType.Cv64F, 1);
            Mat    distCoeffs   = new Mat(1, 4, Emgu.CV.CvEnum.DepthType.Cv64F, 1);
            double rms          = 0.0;

            VectorOfVectorOfPoint3D32F processedObjectPoints = new VectorOfVectorOfPoint3D32F();
            VectorOfVectorOfPointF     processedImagePoints  = new VectorOfVectorOfPointF();

            int k = 0;

            for (int i = 0; i < markerCounterPerFrame.Size; i++)
            {
                int                nMarkersInThisFrame = markerCounterPerFrame[i];
                VectorOfPointF     currentImgPoints    = new VectorOfPointF();
                VectorOfPoint3D32F currentObjPoints    = new VectorOfPoint3D32F();

                for (int j = 0; j < nMarkersInThisFrame; j++)
                {
                    currentImgPoints.Push(new PointF[] { charucoCorners[k] });
                    currentObjPoints.Push(new MCvPoint3D32f[] { GetChessboardCorner(squaresX, squaresY, squareLength, markerLength, charucoIds[k], dictionary, GetRemoteChessboardCorner) });
                    k++;
                }

                processedImagePoints.Push(currentImgPoints);
                processedObjectPoints.Push(currentObjPoints);
            }

            VectorOfPoint3D32F rvecs = new VectorOfPoint3D32F();
            VectorOfPoint3D32F tvecs = new VectorOfPoint3D32F();

            if (fisheye)
            {
                Fisheye.Calibrate(processedObjectPoints, processedImagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, Fisheye.CalibrationFlag.FixSkew | Fisheye.CalibrationFlag.RecomputeExtrinsic, new MCvTermCriteria(400, double.Epsilon));
            }
            else
            {
                CvInvoke.CalibrateCamera(processedObjectPoints, processedImagePoints, imageSize, cameraMatrix, distCoeffs, new Mat(), new Mat(), CalibType.FixK3, new MCvTermCriteria(30, 1e-4));
            }

            rms = Validate(processedObjectPoints, processedImagePoints, cameraMatrix, distCoeffs, rvecs, tvecs, fisheye);

            return(cameraMatrix, distCoeffs, rms);
        }
Beispiel #10
0
 /// <summary>
 /// Create a Dictionary using predefined values
 /// </summary>
 /// <param name="name">The name of the predefined dictionary</param>
 public Dictionary(PredefinedDictionaryName name)
 {
     _ptr = ArucoInvoke.cveArucoGetPredefinedDictionary(name);
 }
Beispiel #11
0
 static extern IntPtr au_getPredefinedDictionary(PredefinedDictionaryName name);
 public static Mat DrawBoard(int squaresX, int squaresY, float squareLength, float markerLength, Size imageSize, int margin, PredefinedDictionaryName dictionary)
 {
     return(DrawBoard(CreateBoard(squaresX, squaresY, squareLength, markerLength, new Dictionary(dictionary)), imageSize, margin));
 }
        public static (VectorOfInt markerIds, VectorOfVectorOfPointF markerCorners, VectorOfInt charucoIds, VectorOfPointF charucoCorners) Detect(Mat image, int squaresX, int squaresY, float squareLength, float markerLength, PredefinedDictionaryName dictionary)
        {
            VectorOfInt            markerIds             = new VectorOfInt();
            VectorOfVectorOfPointF markerCorners         = new VectorOfVectorOfPointF();
            VectorOfInt            charucoIds            = new VectorOfInt();
            VectorOfPointF         charucoCorners        = new VectorOfPointF();
            VectorOfVectorOfPointF rejectedMarkerCorners = new VectorOfVectorOfPointF();

            DetectorParameters decParameters = DetectorParameters.GetDefault();

            ArucoInvoke.DetectMarkers(image, new Dictionary(dictionary), markerCorners, markerIds, decParameters, rejectedMarkerCorners);

            ArucoInvoke.RefineDetectedMarkers(image, CreateBoard(squaresX, squaresY, squareLength, markerLength, new Dictionary(dictionary)), markerCorners, markerIds, rejectedMarkerCorners, null, null, 10, 3, true, null, decParameters);

            if (markerIds.Size > 0)
            {
                ArucoInvoke.InterpolateCornersCharuco(markerCorners, markerIds, image, CreateBoard(squaresX, squaresY, squareLength, markerLength, new Dictionary(dictionary)), charucoCorners, charucoIds, null, null, 2);
            }

            return(markerIds, markerCorners, charucoIds, charucoCorners);
        }
        private static MCvPoint3D32f GetChessboardCorner(int squaresX, int squaresY, float squareLength, float markerLength, int markerId, PredefinedDictionaryName dictionary, Func <byte[], byte[]> getRemoteChessboardCorner)
        {
            MCvPoint3D32f result = new MCvPoint3D32f();

            byte[] inputData = new byte[6 * 4];

            Array.Copy(BitConverter.GetBytes(squaresX), 0, inputData, 0, sizeof(int));
            Array.Copy(BitConverter.GetBytes(squaresY), 0, inputData, 4, sizeof(int));
            Array.Copy(BitConverter.GetBytes(squareLength), 0, inputData, 8, sizeof(float));
            Array.Copy(BitConverter.GetBytes(markerLength), 0, inputData, 12, sizeof(float));
            Array.Copy(BitConverter.GetBytes(markerId), 0, inputData, 16, sizeof(int));
            Array.Copy(BitConverter.GetBytes((int)dictionary), 0, inputData, 20, sizeof(int));

            byte[] outputData = getRemoteChessboardCorner(inputData);

            result.X = BitConverter.ToSingle(outputData, 0);
            result.Y = BitConverter.ToSingle(outputData, 4);
            result.Z = BitConverter.ToSingle(outputData, 8);

            return(result);
        }
Beispiel #15
0
 /// <summary>
 /// Create a Dictionary using predefined values
 /// </summary>
 /// <param name="name">The name of the predefined dictionary</param>
 public Dictionary(PredefinedDictionaryName name)
 {
     //_predefined = true;
     _ptr = ArucoInvoke.cveArucoGetPredefinedDictionary(name, ref _sharedPtr);
 }
Beispiel #16
0
 /// <summary>
 /// Create a Dictionary using predefined values
 /// </summary>
 /// <param name="name">The name of the predefined dictionary</param>
 public Dictionary(PredefinedDictionaryName name)
 {
    _ptr = ArucoInvoke.cveArucoGetPredefinedDictionary(name);
 }
Beispiel #17
0
        /// <summary>
        /// Returns one of the predefined dictionaries defined in PREDEFINED_DICTIONARY_NAME
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Dictionary GetPredefinedDictionary(PredefinedDictionaryName name)
        {
            IntPtr ptr = NativeMethods.aruco_getPredefinedDictionary((int)name);

            return(new Dictionary(ptr));
        }
        public static double ValidateCharuco(int squaresX, int squaresY, float squareLength, float markerLength, PredefinedDictionaryName dictionary, Size imageSize, VectorOfInt charucoIds, VectorOfPointF charucoCorners, VectorOfInt markerCounterPerFrame, bool fisheye, Func <byte[], byte[]> GetRemoteChessboardCorner, Mat cameraMatrix, Mat distCoeffs)
        {
            VectorOfVectorOfPoint3D32F processedObjectPoints = new VectorOfVectorOfPoint3D32F();
            VectorOfVectorOfPointF     processedImagePoints  = new VectorOfVectorOfPointF();
            VectorOfPoint3D32F         rvecs = new VectorOfPoint3D32F();
            VectorOfPoint3D32F         tvecs = new VectorOfPoint3D32F();

            int k = 0;

            for (int i = 0; i < markerCounterPerFrame.Size; i++)
            {
                int                nMarkersInThisFrame       = markerCounterPerFrame[i];
                VectorOfPointF     currentImgPoints          = new VectorOfPointF();
                VectorOfPointF     currentImgPointsUndistort = new VectorOfPointF();
                VectorOfInt        currentIds       = new VectorOfInt();
                VectorOfPoint3D32F currentObjPoints = new VectorOfPoint3D32F();
                Mat                tvec             = new Mat();
                Mat                rvec             = new Mat();

                for (int j = 0; j < nMarkersInThisFrame; j++)
                {
                    currentImgPoints.Push(new PointF[] { charucoCorners[k] });
                    currentIds.Push(new int[] { charucoIds[k] });
                    currentObjPoints.Push(new MCvPoint3D32f[] { GetChessboardCorner(squaresX, squaresY, squareLength, markerLength, charucoIds[k], dictionary, GetRemoteChessboardCorner) });
                    k++;
                }

                Mat distCoeffsNew = new Mat(1, 4, DepthType.Cv64F, 1);
                distCoeffsNew.SetValue(0, 0, 0);
                distCoeffsNew.SetValue(0, 1, 0);
                distCoeffsNew.SetValue(0, 2, 0);
                distCoeffsNew.SetValue(0, 3, 0);

                Fisheye.UndistorPoints(currentImgPoints, currentImgPointsUndistort, cameraMatrix, distCoeffs, Mat.Eye(3, 3, DepthType.Cv64F, 1), Mat.Eye(3, 3, DepthType.Cv64F, 1));
                if (ArucoInvoke.EstimatePoseCharucoBoard(currentImgPointsUndistort, currentIds, CreateBoard(squaresX, squaresY, squareLength, markerLength, new Dictionary(dictionary)), Mat.Eye(3, 3, DepthType.Cv64F, 1), distCoeffsNew, rvec, tvec))
                {
                    rvecs.Push(new MCvPoint3D32f[] { new MCvPoint3D32f((float)rvec.GetValue(0, 0), (float)rvec.GetValue(1, 0), (float)rvec.GetValue(2, 0)) });
                    tvecs.Push(new MCvPoint3D32f[] { new MCvPoint3D32f((float)tvec.GetValue(0, 0), (float)tvec.GetValue(1, 0), (float)tvec.GetValue(2, 0)) });

                    processedImagePoints.Push(currentImgPoints);
                    processedObjectPoints.Push(currentObjPoints);
                }
            }

            return(Validate(processedObjectPoints, processedImagePoints, cameraMatrix, distCoeffs, rvecs, tvecs, fisheye));
        }