示例#1
0
            // MonoBehaviour methods

            protected override void Awake()
            {
                base.Awake();
                ImageSize = new Cv.Size();
                UpdateBoard();
                UpdateArucoHashCode();
            }
示例#2
0
    IEnumerator GetOptimalCameraMatrix(ArucoCameraParameters camCalibration)
    {
        //get dimensions of camera image
        Cv.Size imageSize = new Cv.Size(camCalibration.ImageWidths[0], camCalibration.ImageHeights[0]);

        //wait a frame before reading FOV incase another source is resetting it (i.e. VR SDK)
        yield return(new WaitForEndOfFrame());

        //convert Unity FOV to openCV friendly version
        float cameraFocalLength = imageSize.Height / (2f * Mathf.Tan(0.5f * viewingCamera.fieldOfView * Mathf.Deg2Rad));

        //this is what normally gets passed to opencv function initUndistortRectifyMap()
        float3x3 rectifiedCamMatrices = new float3x3(cameraFocalLength, 0, (float)imageSize.Width / 2,
                                                     0, cameraFocalLength, (float)imageSize.Height / 2,
                                                     0, 0, 1);

        //we get the inverse here rather than doing it in shader since we only have to do it once
        float3x3 inputMatrix = math.inverse(rectifiedCamMatrices);

        SetCameraMatrixValues(camCalibration, inputMatrix);
    }
示例#3
0
        // ArucoBoard methods

        public override Cv.Mat Draw()
        {
#if UNITY_EDITOR
            if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode && (SquaresNumberX <= 1 || SquaresNumberY <= 1 || SquareSideLength <= 0 ||
                                                                                 MarkerSideLength <= 0 || SquareSideLength <= MarkerSideLength || MarkerBorderBits <= 0 || Dictionary == null))
            {
                return(null);
            }
#endif
            int squareSideLength     = GetInPixels(SquareSideLength);
            int markerSideLength     = GetInPixels(MarkerSideLength);
            Aruco.CharucoBoard board = Aruco.CharucoBoard.Create(SquaresNumberX, SquaresNumberY, squareSideLength, markerSideLength, Dictionary);

            Cv.Size imageSize = new Cv.Size();
            imageSize.Width  = GetInPixels(SquaresNumberX * squareSideLength + 2 * MarginsLength);
            imageSize.Height = GetInPixels(SquaresNumberY * squareSideLength + 2 * MarginsLength);

            Cv.Mat image;
            board.Draw(imageSize, out image, MarginsLength, (int)MarkerBorderBits);

            return(image);
        }
示例#4
0
            // ArucoBoard methods

            public override Cv.Mat Draw()
            {
#if UNITY_EDITOR
                if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode && (MarkersNumberX <= 0 || MarkersNumberY <= 0 || MarkerSideLength <= 0 ||
                                                                                     MarkerSeparation <= 0 || MarkerBorderBits <= 0))
                {
                    return(null);
                }
#endif
                int             markerSideLength = GetInPixels(MarkerSideLength);
                int             markerSeparation = GetInPixels(MarkerSeparation);
                Aruco.GridBoard board            = Aruco.GridBoard.Create(MarkersNumberX, MarkersNumberY, markerSideLength, markerSeparation, Dictionary);

                Cv.Size imageSize = new Cv.Size();
                imageSize.Width  = GetInPixels(MarkersNumberX * (markerSideLength + markerSeparation) - markerSeparation + 2 * MarginsLength);
                imageSize.Height = GetInPixels(MarkersNumberY * (markerSideLength + markerSeparation) - markerSeparation + 2 * MarginsLength);

                Cv.Mat image;
                board.Draw(imageSize, out image, MarginsLength, (int)MarkerBorderBits);

                return(image);
            }
示例#5
0
            /// <summary>
            /// Adds the current images of the cameras and the detected corners for the calibration.
            /// </summary>
            public virtual void AddCurrentFrameForCalibration()
            {
                if (!IsConfigured)
                {
                    throw new Exception("Configure the calibration controller before adding the current frame for calibration.");
                }

                // Check for validity
                uint markerIdsNumber = (MarkerIdsCurrentImage[0] != null) ? MarkerIdsCurrentImage[0].Size() : 0;

                for (int cameraId = 0; cameraId < ArucoCamera.CameraNumber; cameraId++)
                {
                    if (MarkerIdsCurrentImage[cameraId] == null || MarkerIdsCurrentImage[cameraId].Size() < 1)
                    {
                        throw new Exception("No markers detected for the camera " + (cameraId + 1) + "/" + ArucoCamera.CameraNumber + " to add the"
                                            + " current images for the calibration. At least one marker detected is required for calibrating the camera.");
                    }

                    if (markerIdsNumber != MarkerIdsCurrentImage[cameraId].Size())
                    {
                        throw new Exception("The cameras must have detected the same number of markers to add the current images for the calibration.");
                    }
                }

                // Save the images and the detected corners
                Cv.Mat[] cameraImages = ArucoCamera.Images;
                for (int cameraId = 0; cameraId < ArucoCamera.CameraNumber; cameraId++)
                {
                    MarkerCorners[cameraId].PushBack(MarkerCornersCurrentImage[cameraId]);
                    MarkerIds[cameraId].PushBack(MarkerIdsCurrentImage[cameraId]);
                    CalibrationImages[cameraId].PushBack(ArucoCamera.Images[cameraId].Clone());

                    if (calibrationImageSizes[cameraId] == null)
                    {
                        calibrationImageSizes[cameraId] = new Cv.Size(ArucoCamera.Images[cameraId].Size.Width, ArucoCamera.Images[cameraId].Size.Height);
                    }
                }
            }
示例#6
0
            /// <summary>
            /// Calibrate 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="CalibrationFlagsController"/> 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 void Calibrate()
            {
                // Prepare data
                Aruco.CharucoBoard charucoBoard = CalibrationBoard.Board as Aruco.CharucoBoard;

                // Check if there is enough captured frames for calibration
                for (int cameraId = 0; cameraId < ArucoCamera.CameraNumber; cameraId++)
                {
                    if (charucoBoard == null && MarkerIds[cameraId].Size() < 1)
                    {
                        throw new Exception("Need at least one frame 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.");
                    }
                }

                // Load the camera parameters if they exist
                string cameraParametersFilePath;
                string cameraParametersFolderPath = Path.Combine((Application.isEditor) ? Application.dataPath : Application.persistentDataPath, CalibrationFolder);

                if (!Directory.Exists(cameraParametersFolderPath))
                {
                    Directory.CreateDirectory(cameraParametersFolderPath);
                }
                if (CalibrationFilename != null && CalibrationFilename.Length > 0)
                {
                    cameraParametersFilePath = cameraParametersFolderPath + CalibrationFilename;
                    CameraParameters         = CameraParameters.LoadFromXmlFile(cameraParametersFilePath);

                    if (CameraParameters.CameraNumber != ArucoCamera.CameraNumber)
                    {
                        throw new ArgumentException("The loaded camera parameters from the file '" + cameraParametersFilePath + "' is for a system with " +
                                                    CameraParameters.CameraNumber + " camera. But the current calibrating camera has " + ArucoCamera.CameraNumber + ". These numbers"
                                                    + " must be equal.", "CalibrationFilename");
                    }
                }
                // Or initialize the camera parameters
                else
                {
                    CameraParameters = new CameraParameters(ArucoCamera.CameraNumber)
                    {
                        CalibrationFlagsValue = CalibrationFlagsController.CalibrationFlagsValue,
                        FixAspectRatioValue   = (calibrationFlagsPinholeController) ? calibrationFlagsPinholeController.FixAspectRatioValue : 0
                    };
                    for (int cameraId = 0; cameraId < ArucoCamera.CameraNumber; cameraId++)
                    {
                        CameraParameters.ImageHeights[cameraId] = ArucoCamera.ImageTextures[cameraId].height;
                        CameraParameters.ImageWidths[cameraId]  = ArucoCamera.ImageTextures[cameraId].width;

                        double cameraMatrixAspectRatio = (calibrationFlagsPinholeController && calibrationFlagsPinholeController.FixAspectRatio)
              ? calibrationFlagsPinholeController.FixAspectRatioValue : 1.0;
                        CameraParameters.CameraMatrices[cameraId] = new Cv.Mat(3, 3, Cv.Type.CV_64F,
                                                                               new double[9] {
                            cameraMatrixAspectRatio, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0
                        });
                        CameraParameters.DistCoeffs[cameraId] = new Cv.Mat();
                        CameraParameters.OmnidirXis[cameraId] = new Cv.Mat();
                    }
                }

                // Calibrate each camera
                Std.VectorVectorPoint3f[] objectPoints = new Std.VectorVectorPoint3f[ArucoCamera.CameraNumber];
                Std.VectorVectorPoint2f[] imagePoints  = new Std.VectorVectorPoint2f[ArucoCamera.CameraNumber];
                for (int cameraId = 0; cameraId < ArucoCamera.CameraNumber; cameraId++)
                {
                    // Get objet and image calibration points from detected ids and corners
                    Std.VectorVectorPoint3f boardObjectPoints = new Std.VectorVectorPoint3f();
                    Std.VectorVectorPoint2f boardImagePoints  = new Std.VectorVectorPoint2f();
                    uint frameCount = MarkerCorners[cameraId].Size();
                    for (uint frame = 0; frame < frameCount; frame++)
                    {
                        Std.VectorPoint3f frameObjectPoints;
                        Std.VectorPoint2f frameImagePoints;
                        Aruco.GetBoardObjectAndImagePoints(CalibrationBoard.Board, MarkerCorners[cameraId].At(frame), MarkerIds[cameraId].At(frame),
                                                           out frameObjectPoints, out frameImagePoints);
                        boardObjectPoints.PushBack(frameObjectPoints);
                        boardImagePoints.PushBack(frameImagePoints);
                    }
                    objectPoints[cameraId] = boardObjectPoints;
                    imagePoints[cameraId]  = boardImagePoints;

                    // Calibrate the camera
                    Cv.Size         imageSize = ArucoCamera.Images[cameraId].Size;
                    Std.VectorVec3d rvecs, tvecs;
                    if (calibrationFlagsPinholeController)
                    {
                        CameraParameters.ReprojectionErrors[cameraId] = Cv.CalibrateCamera(boardObjectPoints, boardImagePoints, imageSize,
                                                                                           CameraParameters.CameraMatrices[cameraId], CameraParameters.DistCoeffs[cameraId], out rvecs, out tvecs,
                                                                                           calibrationFlagsPinholeController.CalibrationFlags);
                    }
                    else if (calibrationFlagsOmnidirController)
                    {
                        CameraParameters.ReprojectionErrors[cameraId] = Cv.Omnidir.Calibrate(boardObjectPoints, boardImagePoints, imageSize,
                                                                                             CameraParameters.CameraMatrices[cameraId], CameraParameters.OmnidirXis[cameraId], CameraParameters.DistCoeffs[cameraId], out rvecs,
                                                                                             out tvecs, calibrationFlagsOmnidirController.CalibrationFlags);
                    }
                    else
                    {
                        rvecs = new Std.VectorVec3d();
                        tvecs = new Std.VectorVec3d();
                    }

                    // If the used board is a charuco board, refine the calibration
                    if (charucoBoard != null)
                    {
                        // Prepare data to refine the calibration
                        Std.VectorVectorPoint3f charucoObjectPoints = new Std.VectorVectorPoint3f();
                        Std.VectorVectorPoint2f charucoImagePoints  = new Std.VectorVectorPoint2f();
                        for (uint frame = 0; frame < frameCount; frame++)
                        {
                            // Interpolate charuco corners using camera parameters
                            Std.VectorPoint2f charucoCorners;
                            Std.VectorInt     charucoIds;
                            Aruco.InterpolateCornersCharuco(MarkerCorners[cameraId].At(frame), MarkerIds[cameraId].At(frame), CameraImages[cameraId].At(frame),
                                                            charucoBoard, out charucoCorners, out charucoIds);
                            charucoImagePoints.PushBack(charucoCorners);

                            // Join the object points corresponding to the detected markers
                            charucoObjectPoints.PushBack(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);
                                charucoObjectPoints.At(frame).PushBack(objectPoint);
                            }
                        }
                        objectPoints[cameraId] = boardObjectPoints;

                        // Refine the calibration
                        if (calibrationFlagsPinholeController)
                        {
                            CameraParameters.ReprojectionErrors[cameraId] = Cv.CalibrateCamera(charucoObjectPoints, charucoImagePoints, imageSize,
                                                                                               CameraParameters.CameraMatrices[cameraId], CameraParameters.DistCoeffs[cameraId], out rvecs, out tvecs,
                                                                                               calibrationFlagsPinholeController.CalibrationFlags);
                        }
                        else if (calibrationFlagsOmnidirController)
                        {
                            CameraParameters.ReprojectionErrors[cameraId] = Cv.Omnidir.Calibrate(boardObjectPoints, boardImagePoints, imageSize,
                                                                                                 CameraParameters.CameraMatrices[cameraId], CameraParameters.OmnidirXis[cameraId], CameraParameters.DistCoeffs[cameraId], out rvecs,
                                                                                                 out tvecs, calibrationFlagsOmnidirController.CalibrationFlags);
                        }
                    }

                    // Save calibration extrinsic parameters
                    Rvecs[cameraId] = rvecs;
                    Tvecs[cameraId] = tvecs;
                }

                // If required, apply a stereo calibration and save the resuts in the camera parameters
                CameraParameters.StereoCameraParametersList = new StereoCameraParameters[StereoCalibrationCameraPairs.Length];
                for (int i = 0; i < StereoCalibrationCameraPairs.Length; i++)
                {
                    CameraParameters.StereoCameraParametersList[i] = StereoCalibrationCameraPairs[i].Calibrate(ArucoCamera, CameraParameters, objectPoints, imagePoints);
                }

                IsCalibrated = true;

                // Save the camera parameters
                cameraParametersFilePath = cameraParametersFolderPath;
                if (CalibrationFilename != null && CalibrationFilename.Length > 0)
                {
                    cameraParametersFilePath += CalibrationFilename;
                }
                else
                {
                    cameraParametersFilePath += ArucoCamera.Name + " - " + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".xml";
                }
                CameraParameters.SaveToXmlFile(cameraParametersFilePath);
            }
示例#7
0
            public StereoCameraParameters Calibrate(ArucoCamera arucoCamera, CameraParameters cameraParameters, Std.VectorVectorPoint3f[] objectPoints,
                                                    Std.VectorVectorPoint2f[] imagePoints)
            {
                // Prepare the camera parameters
                StereoCameraParameters stereoCameraParameters = new StereoCameraParameters()
                {
                    CameraIds             = new int[] { CameraId1, CameraId2 },
                    CalibrationFlagsValue = CalibrationFlagsController.CalibrationFlagsValue
                };

                // Estimates transformation between the two cameras
                Cv.Mat   cameraMatrix1 = cameraParameters.CameraMatrices[CameraId1];
                Cv.Mat   distCoeffs1 = cameraParameters.DistCoeffs[CameraId1];
                Cv.Mat   xi1 = cameraParameters.OmnidirXis[CameraId1];
                Cv.Mat   cameraMatrix2 = cameraParameters.CameraMatrices[CameraId2];
                Cv.Mat   distCoeffs2 = cameraParameters.DistCoeffs[CameraId2];
                Cv.Mat   xi2 = cameraParameters.OmnidirXis[CameraId2];
                Cv.Size  imageSize = arucoCamera.Images[CameraId1].Size;
                Cv.Vec3d rvec, tvec;
                Cv.Mat   essentialMatrix, fundamentalMatrix;
                if (calibrationFlagsPinholeController)
                {
                    stereoCameraParameters.ReprojectionError = Cv.StereoCalibrate(objectPoints[CameraId1], imagePoints[CameraId1], imagePoints[CameraId2],
                                                                                  cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, out rvec, out tvec, out essentialMatrix, out fundamentalMatrix,
                                                                                  calibrationFlagsPinholeController.CalibrationFlags);
                }
                else if (calibrationFlagsOmnidirController)
                {
                    Cv.Mat rvecsL, tvecsL;
                    stereoCameraParameters.ReprojectionError = Cv.Omnidir.StereoCalibrate(objectPoints[CameraId1], imagePoints[CameraId1],
                                                                                          imagePoints[CameraId2], imageSize, imageSize, cameraMatrix1, xi1, distCoeffs1, cameraMatrix2, xi2, distCoeffs2, out rvec, out tvec,
                                                                                          out rvecsL, out tvecsL, calibrationFlagsOmnidirController.CalibrationFlags);
                }
                else
                {
                    rvec = new Cv.Vec3d();
                    tvec = new Cv.Vec3d();
                }

                // Computes rectification transforms
                Cv.Mat rotationMatrix1, rotationMatrix2, newCameraMatrix1, newCameraMatrix2, Q;
                if (calibrationFlagsPinholeController)
                {
                    Cv.StereoRectifyFlags stereoRectifyFlags = (calibrationFlagsPinholeController.ZeroDisparity) ? Cv.StereoRectifyFlags.ZeroDisparity : 0;
                    Cv.StereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, rvec, tvec, out rotationMatrix1,
                                     out rotationMatrix2, out newCameraMatrix1, out newCameraMatrix2, out Q, stereoRectifyFlags,
                                     calibrationFlagsPinholeController.Skew, NewImageSize);
                }
                else if (calibrationFlagsOmnidirController)
                {
                    Cv.Omnidir.StereoRectify(rvec, tvec, out rotationMatrix1, out rotationMatrix2);
                    newCameraMatrix1 = new Cv.Mat();
                    newCameraMatrix2 = new Cv.Mat();
                }
                else
                {
                    rotationMatrix1  = new Cv.Mat();
                    rotationMatrix2  = new Cv.Mat();
                    newCameraMatrix1 = new Cv.Mat();
                    newCameraMatrix2 = new Cv.Mat();
                }

                // Save the camera parameters
                stereoCameraParameters.RotationVector    = rvec;
                stereoCameraParameters.TranslationVector = tvec;
                stereoCameraParameters.RotationMatrices  = new Cv.Mat[] { rotationMatrix1, rotationMatrix2 };
                stereoCameraParameters.NewCameraMatrices = new Cv.Mat[] { newCameraMatrix1, newCameraMatrix2 };

                return(stereoCameraParameters);
            }