示例#1
0
        public static bool TryLoadFromFile(string fileName, out Intrinsics intrinsics)
        {
            intrinsics = null;

            if (!Directory.Exists(TrackingToolsConstants.intrinsicsDirectoryPath))
            {
                Debug.LogError(logPrepend + "Directory missing.\n" + TrackingToolsConstants.intrinsicsDirectoryPath);
                return(false);
            }

            string filePath = TrackingToolsConstants.intrinsicsDirectoryPath + "/" + fileName;

            if (!fileName.EndsWith(".json"))
            {
                filePath += ".json";
            }
            if (!File.Exists(filePath))
            {
                Debug.LogError(logPrepend + "File missing.\n" + filePath);
                return(false);
            }

            intrinsics = JsonUtility.FromJson <Intrinsics>(File.ReadAllText(filePath));
            return(true);
        }
示例#2
0
        void Awake()
        {
            Intrinsics intrinsics;

            if (!Intrinsics.TryLoadFromFile(_intrinsicsFileName, out intrinsics))
            {
                return;
            }

            Camera cam = GetComponent <Camera>();

            intrinsics.ApplyToCamera(cam);
        }
示例#3
0
        public IntrinsicsCalibrator(int imageWidth, int imageHeight)
        {
            const int regularSampleCount = 4;

            _intrinsics          = new Intrinsics();
            _patternImageSamples = new List <Mat>(regularSampleCount);
            _patternRealSamples  = new List <Mat>(regularSampleCount);
            _distortionCoeffsMat = new MatOfDouble();
            _rotationSamples     = new List <Mat>(regularSampleCount);
            _translationSamples  = new List <Mat>(regularSampleCount);
            _sensorMat           = Mat.eye(3, 3, CvType.CV_64FC1);
            _textureSize         = new Size(imageWidth, imageHeight);
        }
示例#4
0
        void Awake()
        {
            if (!Intrinsics.TryLoadFromFile(_intrinsicsFileName, out _intrinsics))
            {
                Debug.LogError("Intrinsics file '" + _intrinsicsFileName + "' not found.\n");
                enabled = false;
                return;
            }

            _undistortMap1 = new Mat();
            _undistortMap2 = new Mat();

            _extrinsicsCalibrator = new CameraExtrinsicsCalibrator();

            TrackingToolsHelper.RenderPattern(_chessPatternSize, TrackingToolsHelper.PatternType.Chessboard, 1024, ref _chessPatternTexture, ref _patternRenderMaterial);

            // Prepare UI.
            _aspectFitter = _processedCameraImage.GetComponent <AspectRatioFitter>();
            if (!_aspectFitter)
            {
                _aspectFitter = _processedCameraImage.gameObject.AddComponent <AspectRatioFitter>();
            }
            _aspectFitter.aspectMode       = AspectRatioFitter.AspectMode.FitInParent;
            _previewMaterial               = new Material(Shader.Find(TrackingToolsConstants.previewShaderName));
            _processedCameraImage.material = _previewMaterial;
            _processedCameraImage.color    = Color.white;
            _arImage = new GameObject("ARImage").AddComponent <RawImage>();
            _arImage.transform.SetParent(_processedCameraImage.transform);
            _arImage.rectTransform.FitParent();
            _arImage.gameObject.SetActive(false);
            _mainCamera.backgroundColor       = Color.clear;
            _chessPatternTransform            = GameObject.CreatePrimitive(PrimitiveType.Quad).transform;
            _chessPatternTransform.name       = "Chessboard";
            _chessPatternTransform.localScale = new Vector3((_chessPatternSize.x - 1) * _chessTileSize * 0.001f, (_chessPatternSize.y - 1) * _chessTileSize * 0.001f, 0);
            Shader   unlitTextureShader = Shader.Find("Unlit/Texture");
            Material chessboardMaterial = new Material(unlitTextureShader);

            chessboardMaterial.mainTexture = _chessPatternTexture;
            _chessPatternTransform.GetComponent <Renderer>().material = chessboardMaterial;
            _precisionDotsContainerObject = TrackingToolsHelper.CreatePrecisionTestDots(_chessPatternTransform, _testPrecisionDotsLayer, _chessPatternSize, _chessTileSize / 1000f);

            // Update world points.
            TrackingToolsHelper.UpdateWorldSpacePatternPoints(_chessPatternSize, _chessPatternTransform.localToWorldMatrix, TrackingToolsHelper.PatternType.Chessboard, Vector2.zero, ref _chessCornersWorldMat);
        }
示例#5
0
        /// <summary>
        /// Update the extrinsics of projector relative to camera.
        /// </summary>
        /// <param name="cameraIntrinsics"></param>
        /// <param name="projectorIntrinsics"></param>
        /// <param name="textureSize"></param>
        public void Update(Intrinsics cameraIntrinsics, Intrinsics projectorIntrinsics, Size textureSize)
        {
            int w = (int)textureSize.width;
            int h = (int)textureSize.height;

            cameraIntrinsics.ToOpenCV(ref _cameraSensorMat, w, h);
            projectorIntrinsics.ToOpenCV(ref _projectorSensorMat, w, h);

            // In order to match OpenCV's pixel space (zero at top-left) and Unity's camera space (up is positive), we flip the sensor matrix.

            _cameraSensorMat.WriteValue(-_cameraSensorMat.ReadValue(1, 1), 1, 1);                           // fy
            _cameraSensorMat.WriteValue(textureSize.height - _cameraSensorMat.ReadValue(1, 2), 1, 2);       // cy
            _projectorSensorMat.WriteValue(-_projectorSensorMat.ReadValue(1, 1), 1, 1);                     // fy
            _projectorSensorMat.WriteValue(textureSize.height - _projectorSensorMat.ReadValue(1, 2), 1, 2); // cy

            int flag = 0;

            // Don't recompute and change intrinsics parameters.
            flag |= Calib3d.CALIB_FIX_INTRINSIC;

            // Don't recompute distortions, ignore them. We assume the incoming points have already bee undistorted.
            flag |=
                Calib3d.CALIB_FIX_TANGENT_DIST |
                Calib3d.CALIB_FIX_K1 |
                Calib3d.CALIB_FIX_K2 |
                Calib3d.CALIB_FIX_K3 |
                Calib3d.CALIB_FIX_K4 |
                Calib3d.CALIB_FIX_K5;

            // Compute!
            Calib3d.stereoCalibrate
            (
                _patternWorldSamples, _cameraPatternImageSamples, _projectorPatternImageSamples,
                _cameraSensorMat, _noDistCoeffs,
                _projectorSensorMat, _noDistCoeffs,
                textureSize,
                _rotation3x3Mat, _translationVecMat, _essentialMat, _fundamentalMat,
                flag
            );

            _extrinsics.UpdateFromOpenCvStereoCalibrate(_rotation3x3Mat, _translationVecMat);
        }
示例#6
0
        void Awake()
        {
            // Create UI.
            if (!_containerUI)
            {
                _containerUI = new GameObject("CameraPoser").AddComponent <RectTransform>();
                _containerUI.transform.SetParent(_canvas.transform);
            }
            CanvasGroup wrapperGroup = _containerUI.GetComponent <CanvasGroup>();

            if (!wrapperGroup)
            {
                wrapperGroup = _containerUI.gameObject.AddComponent <CanvasGroup>();
            }
            wrapperGroup.alpha = _alpha;
            Image backgroundImage = new GameObject("Background").AddComponent <Image>();

            backgroundImage.transform.SetParent(_containerUI.transform);
            _rawImageUI = new GameObject("CameraImage").AddComponent <RawImage>();
            _rawImageUI.transform.SetParent(_containerUI.transform);
            _rawImageUI.uvRect         = _flipTexture ? new UnityEngine.Rect(0, 1, 1, -1) : new UnityEngine.Rect(0, 0, 1, 1);
            _rawImageRect              = _rawImageUI.GetComponent <RectTransform>();
            _uiMaterial                = new Material(Shader.Find("Hidden/SingleChannelTexture"));
            _rawImageUI.material       = _uiMaterial;
            _aspectFitterUI            = _rawImageUI.gameObject.AddComponent <AspectRatioFitter>();
            _aspectFitterUI.aspectMode = AspectRatioFitter.AspectMode.HeightControlsWidth;
            backgroundImage.color      = Color.black;
            ExpandRectTransform(_containerUI);
            ExpandRectTransform(backgroundImage.GetComponent <RectTransform>());
            ExpandRectTransform(_rawImageRect);
            _userPointRects  = new RectTransform[pointCount];
            _userPointImages = new Image[pointCount];
            for (int p = 0; p < pointCount; p++)
            {
                GameObject pointObject = new GameObject("Point" + p);
                pointObject.transform.SetParent(_rawImageRect);
                Image pointImage = pointObject.AddComponent <Image>();
                pointImage.color = Color.cyan;
                RectTransform pointRect = pointObject.GetComponent <RectTransform>();
                pointRect.sizeDelta = Vector2.one * 5;
                SetAnchoredPosition(pointRect, defaultPointPositions[p]);
                pointRect.anchoredPosition = Vector3.zero;
                Text pointLabel = new GameObject("Label").AddComponent <Text>();
                pointLabel.text = p.ToString();
                pointLabel.transform.SetParent(pointRect);
                pointLabel.rectTransform.anchoredPosition = Vector2.zero;
                pointLabel.rectTransform.sizeDelta        = new Vector2(_fontSize, _fontSize) * 2;
                pointLabel.font     = _font;
                pointLabel.fontSize = _fontSize;
                _userPointRects[p]  = pointRect;
                _userPointImages[p] = pointImage;
            }

            // Hide.
            //if( !_interactable ) _containerUI.transform.gameObject.SetActive( false );

            // Prepare OpenCV.
            _noDistCoeffs         = new MatOfDouble(new double[] { 0, 0, 0, 0 });
            _rVec                 = new Mat();
            _tVec                 = new Mat();
            _anchorPointsImage    = new Point[pointCount];
            _anchorPointsWorld    = new Point3[pointCount];
            _anchorPointsImageMat = new MatOfPoint2f();
            _anchorPointsWorldMat = new MatOfPoint3f();
            _anchorPointsImageMat.alloc(pointCount);
            _anchorPointsWorldMat.alloc(pointCount);
            for (int p = 0; p < pointCount; p++)
            {
                _anchorPointsImage[p] = new Point();
                _anchorPointsWorld[p] = new Point3();
            }

            // Load files.
            if (Intrinsics.TryLoadFromFile(_intrinsicsFileName, out _intrinsics))
            {
                enabled = false;
                return;
            }
            LoadCircleAnchorPoints();

            // Update variables.
            if (!Application.isEditor)
            {
                OnValidate();
            }
        }
示例#7
0
        void Awake()
        {
            Application.targetFrameRate = 30;

            // Check resources.
            if (_operationMode == OperationMode.ManualSamlping && !_manualSampleButton)
            {
                Debug.LogError(logPrepend + "Missing sample button. You must provide a sample button when OperationMode is " + OperationMode.ManualSamlping);
                enabled = false;
                return;
            }

            // Load files.
            if (!Intrinsics.TryLoadFromFile(_cameraIntrinsicsFileName, out _cameraIntrinsics))
            {
                enabled = false;
                return;
            }

            // Find shaders.
            Shader unlitColorShader         = Shader.Find("Unlit/Color");
            Shader unlitTextureShader       = Shader.Find("Unlit/Texture");
            Shader unlitTintedTextureShader = Shader.Find("Unlit/TintedInvertibleTexture");

            _sb = new StringBuilder();

            // Operation mode dependent things.
            _stableSampleCountThreshold = _operationMode == OperationMode.ManualSamlping ? stableFrameCountThresholdForManualSampling : stableFrameCountThresholdForTimedSampling;
            if (_manualSampleButton)
            {
                _manualSampleButton.gameObject.SetActive(_operationMode == OperationMode.ManualSamlping);
                _manualSampleButton.interactable = false;
            }

            // Prepare OpenCV.
            _cameraExtrinsicsCalibrator    = new CameraExtrinsicsCalibrator();
            _projectorExtrinsicsCalibrator = new ProjectorFromCameraExtrinsicsCalibrator();
            _noDistCoeffs = new MatOfDouble(new double[] { 0, 0, 0, 0 });
            _circlePointsProjectorRenderImageMat = new MatOfPoint2f();
            _circlePointsRealModelMat            = new MatOfPoint3f();
            _circlePointsDetectedWorldMat        = new MatOfPoint3f();
            _undistortMap1 = new Mat();
            _undistortMap2 = new Mat();

            // Create patterns.
            TrackingToolsHelper.RenderPattern(_chessPatternSize, TrackingToolsHelper.PatternType.Chessboard, 1024, ref _chessPatternTexture, ref _patternRenderMaterial);

            // Layers.
            int uiLayer             = LayerMask.NameToLayer("UI");
            int mainCameraLayerMask = LayerMask.GetMask("Default");
            int projectorLayer      = LayerMask.NameToLayer("TransparentFX");
            int projectorLayerMask  = LayerMask.GetMask("TransparentFX");

            // Objects.
            _calibrationBoardTransform = new GameObject("CalibrationBoard").transform;

            // Create and prepare UI.
            _cameraAspectFitter = _processedCameraImage.GetComponent <AspectRatioFitter>();
            if (!_cameraAspectFitter)
            {
                _cameraAspectFitter = _processedCameraImage.gameObject.AddComponent <AspectRatioFitter>();
            }
            _cameraAspectFitter.aspectMode = AspectRatioFitter.AspectMode.FitInParent;
            _previewMaterial = new Material(Shader.Find(TrackingToolsConstants.previewShaderName));
            _processedCameraImage.gameObject.layer = uiLayer;
            _processedCameraImage.material         = _previewMaterial;
            _processedCameraImage.color            = Color.white;

            _arImage = new GameObject("ARImage").AddComponent <RawImage>();
            _arImage.transform.SetParent(_processedCameraImage.transform);
            _arImage.transform.SetAsFirstSibling();
            _arImage.raycastTarget = false;
            _arImage.rectTransform.FitParent();
            _arImage.gameObject.layer = uiLayer;

            _mainCamera.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
            _mainCamera.cullingMask = mainCameraLayerMask;

            _projectorCamera.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
            _projectorCamera.cullingMask           = projectorLayerMask;
            _projectorCamera.usePhysicalProperties = false;

            _chessPatternTransform = GameObject.CreatePrimitive(PrimitiveType.Quad).transform;
            _chessPatternTransform.SetParent(_calibrationBoardTransform);
            _chessPatternTransform.name = "Chessboard";
            Material chessboardMaterial = new Material(unlitTextureShader);

            chessboardMaterial.mainTexture = _chessPatternTexture;
            _chessPatternTransform.GetComponent <Renderer>().material = chessboardMaterial;
            float chessTileSizeMeters = _chessTileSize * 0.001f;

            _chessPatternTransform.localScale = new Vector3((_chessPatternSize.x - 1) * chessTileSizeMeters, (_chessPatternSize.y - 1) * chessTileSizeMeters, 0);
            TrackingToolsHelper.UpdateWorldSpacePatternPoints(_chessPatternSize, _chessPatternTransform.localToWorldMatrix, TrackingToolsHelper.PatternType.Chessboard, Vector2.zero, ref _chessCornersWorldMat);

            _circlePatternTransform      = GameObject.CreatePrimitive(PrimitiveType.Quad).transform;
            _circlePatternTransform.name = "Circlesboard";
            _circlePatternBoardMaterial  = new Material(unlitTintedTextureShader);
            _circlePatternTransform.GetComponent <Renderer>().material = _circlePatternBoardMaterial;
            _circlePatternTransform.position         = Vector3.forward;
            _circlePatternTransform.gameObject.layer = projectorLayer;

            _precisionDotsContainerObject = TrackingToolsHelper.CreatePrecisionTestDots(_calibrationBoardTransform, projectorLayer, _chessPatternSize, chessTileSizeMeters);
            _precisionDotsContainerObject.SetActive(false);

            _projectorSampleMeterTransform = GameObject.CreatePrimitive(PrimitiveType.Quad).transform;
            _projectorSampleMeterTransform.gameObject.layer = projectorLayer;
            _projectorSampleMeterTransform.name             = "ProjectorSampleMeter";
            _projectorSampleMeterTransform.localScale       = new Vector3(_chessPatternTransform.localScale.x, TrackingToolsConstants.precisionTestDotSize, 0);
            _projectorSampleMeterTransform.SetParent(_calibrationBoardTransform);
            float dotOffsetY = ((_chessPatternSize.y - 4) * 0.5f + 1) * chessTileSizeMeters;

            _projectorSampleMeterTransform.localPosition = new Vector3(0, -dotOffsetY - chessTileSizeMeters);
            Material sampleMeterMaterial = new Material(unlitColorShader);

            _projectorSampleMeterTransform.GetComponent <Renderer>().sharedMaterial = sampleMeterMaterial;
            _projectorSampleMeterTransform.gameObject.SetActive(false);

            _intrinsicsErrorText.gameObject.SetActive(false);
            _extrinsicsErrorText.gameObject.SetActive(false);
            _saveButton.gameObject.SetActive(false);
            _undoSampleButton.gameObject.SetActive(false);

            _screenBorderMaterial = new Material(unlitColorShader);

            _circlePatternToWorldPrevFrame = Matrix4x4.identity;

            _previewFlasher = new MaterialPropFlasher(_previewMaterial, "_Whiteout", TrackingToolsConstants.flashDuration);
            UpdateSampleCounterUI();

            // Subscribe.
            _circlePatternScaleSlider.onValueChanged.AddListener(( float v ) => _manualCirclePatternTransformationRequested   = true);            //OnCirclePatternScaleSliderChanged );
            _circlePatternOffsetXSlider.onValueChanged.AddListener(( float v ) => _manualCirclePatternTransformationRequested = true);
            _circlePatternOffsetYSlider.onValueChanged.AddListener(( float v ) => _manualCirclePatternTransformationRequested = true);
            _saveButton.onClick.AddListener(SaveToFiles);
            _undoSampleButton.onClick.AddListener(UndoSample);
            if (_manualSampleButton)
            {
                _manualSampleButton.onClick.AddListener(() => _sampleManuallyRequested = true);;
            }
        }
        public bool UpdateExtrinsics(MatOfPoint3f patternPointsWorldMat, MatOfPoint2f patternPointsImageMat, Intrinsics intrinsics, int imageWidth, int imageHeight)
        {
            intrinsics.ToOpenCV(ref _sensorMatrix, imageWidth, imageHeight);

            // In order to match OpenCV's pixel space (zero at top-left) and Unity's camera space (up is positive), we flip the sensor matrix.
            _sensorMatrix.WriteValue(-_sensorMatrix.ReadValue(1, 1), 1, 1);                  // fy
            _sensorMatrix.WriteValue(imageHeight - _sensorMatrix.ReadValue(1, 2), 1, 2);     // cy

            // Find pattern pose, relative to camera (at zero position) using solvePnP.
            _isValid = Calib3d.solvePnP(patternPointsWorldMat, patternPointsImageMat, _sensorMatrix, _noDistCoeffs, _rotationVecMat, _translationVecMat);

            if (_isValid)
            {
                _extrinsics.UpdateFromOpenCvSolvePnp(_rotationVecMat, _translationVecMat);
            }

            return(_isValid);
        }