Exemple #1
0
        void AdaptResources()
        {
            int w = _cameraTexture.width;
            int h = _cameraTexture.height;

            if (_undistortedCameraTexture != null && _undistortedCameraTexture.width == w && _undistortedCameraTexture.height == h)
            {
                return;
            }

            _camTexMat              = TrackingToolsHelper.GetCompatibleMat(_cameraTexture);
            _camTexGrayMat          = new Mat(h, w, CvType.CV_8UC1);
            _camTexGrayUndistortMat = new Mat(h, w, CvType.CV_8UC1);

            _undistortedCameraTexture      = new Texture2D(w, h, GraphicsFormat.R8_UNorm, 0, TextureCreationFlags.None);
            _undistortedCameraTexture.name = "UndistortedCameraTex";

            _intrinsics.ToOpenCV(ref _cameraMatrix, ref _distCoeffs, w, h);

            // UI.
            _rawImageUI.texture         = _undistortedCameraTexture;
            _aspectFitterUI.aspectRatio = w / (float)h;

            // Forward the news.
            if (_arCamera)
            {
                _intrinsics.ApplyToCamera(_arCamera);
            }
        }
Exemple #2
0
        void Update()
        {
            if (!AdaptResources() || !_dirtyTexture)
            {
                return;
            }

            // Convert texture to mat (If the texture looks right in Unity, it needs to be flipped for OpenCV).
            TrackingToolsHelper.TextureToMat(_inputTexture, true, ref _camTexMat, ref _tempTransferColors, ref _tempTransferTexture);

            // Convert to grayscale if more than one channel, else copy (and convert bit rate if necessary).
            TrackingToolsHelper.ColorMatToLumanceMat(_camTexMat, _camTexGrayMat);

            // Correct levels.
            if (!Mathf.Approximately(_blackValue, 0) || !Mathf.Approximately(_whiteValue, 1) || !Mathf.Approximately(_gammaValue, 1f))
            {
                if (_dirtyLevelsLookup)
                {
                    UpdateLevelsLookup();
                }
                Core.LUT(_camTexGrayMat, _levelsLookup, _camTexGrayMat);
            }

            Utils.fastMatToTexture2D(_camTexGrayMat, _processedCameraTexture);               // Flips the texture vertically by default

            _outputTexture.Invoke(_processedCameraTexture);

            _dirtyTexture = false;
        }
Exemple #3
0
        void Update()
        {
            if (!_cameraTexture || !_dirtyCameraTexture)
            {
                return;
            }

            // Init.
            AdaptResources();

            // Update mat texture ( If the texture looks correct in Unity, then it needs to be flipped for OpenCV ).
            TrackingToolsHelper.TextureToMat(_cameraTexture, !_flipCameraTexture, ref _camTexMat, ref _tempTransferColors, ref _tempTransferTexture);

            // Convert to grayscale if more than one channel, else copy (and convert bit rate if necessary).
            TrackingToolsHelper.ColorMatToLumanceMat(_camTexMat, _camTexGrayMat);

            // During testing, undistort before.
            if (_state == State.Testing)
            {
                Calib3d.undistort(_camTexGrayMat, _camTexGrayUndistortMat, _intrinsicsCalibrator.sensorMat, _intrinsicsCalibrator.distortionCoeffsMat);
            }

            // Find chessboard.
            Mat  chessboardSourceMat = _state == State.Calibrating ? _camTexGrayMat : _camTexGrayUndistortMat;
            bool foundBoard          = TrackingToolsHelper.FindChessboardCorners(chessboardSourceMat, _chessPatternSize, ref _chessCornersImageMat);

            if (foundBoard)
            {
                TrackingToolsHelper.DrawFoundPattern(chessboardSourceMat, _chessPatternSize, _chessCornersImageMat);
            }

            // During calibration, undistort after.
            if (_state == State.Calibrating)
            {
                if (_intrinsicsCalibrator.sampleCount > correctDistortionSampleCountThreshold)
                {
                    Calib3d.undistort(_camTexGrayMat, _camTexGrayUndistortMat, _intrinsicsCalibrator.sensorMat, _intrinsicsCalibrator.distortionCoeffsMat);
                }
                else
                {
                    _camTexGrayMat.copyTo(_camTexGrayUndistortMat);
                }
            }

            // State dependent updates.
            switch (_state)
            {
            case State.Calibrating: UpdateCalibration(foundBoard); break;

            case State.Testing: UpdateTesting(foundBoard); break;
            }

            // UI.
            Utils.fastMatToTexture2D(_camTexGrayUndistortMat, _processedCameraTexture);               // Will flip as default.
            _previewFlasher.Update();
            UpdateSampleCounterUI();

            _dirtyCameraTexture = false;
        }
Exemple #4
0
        void UpdateCirclePatternSize()
        {
            if (_state == State.Initiating || _state == State.BlindCalibration)
            {
                _circlePatternSize = defaultCirclesPatternSize;
            }
            else
            {
                const int circlePatternSizeYMin = 7;
                const int desiredPixelsPerCirclePatternSegment = 25;                                               // 50px is recommended, but for a 720p camera, this will give too fex dots.
                float     desiredCirclePatternNumAspect        = _chessPatternSize.x / (_chessPatternSize.y) / 2f; // 3f / 4f / 2f;

                float patternDistance             = Vector3.Distance(_mainCamera.transform.position, _circlePatternTransform.position);
                float patternHeight               = _chessPatternTransform.localScale.y;
                float viewHeightAtPatternPosition = Mathf.Tan(_mainCamera.fieldOfView * Mathf.Deg2Rad * 0.5f) * patternDistance * 2;
                int   circlePatternPixelHeight    = (int)((patternHeight / viewHeightAtPatternPosition) * _cameraTexture.height);
                int   optimalPatternSizeY         = Mathf.Max(circlePatternSizeYMin, Mathf.FloorToInt(circlePatternPixelHeight / (float)desiredPixelsPerCirclePatternSegment));
                int   optimalPatternSizeX         = Mathf.FloorToInt(optimalPatternSizeY * desiredCirclePatternNumAspect);
                _circlePatternSize = TrackingToolsHelper.GetClosestValidPatternSize(new Vector2Int(optimalPatternSizeX, optimalPatternSizeY), TrackingToolsHelper.PatternType.AsymmetricCircleGrid);
            }

            _circlePatternPointCount = _circlePatternSize.x * _circlePatternSize.y;

            if (_circlePointsProjectorRenderImageMat != null && _circlePointsProjectorRenderImageMat.rows() == _circlePatternPointCount)
            {
                return;
            }

            if (_circlePointsProjectorRenderImageMat != null)
            {
                _circlePointsProjectorRenderImageMat.release();
            }
            if (_circlePointsRealModelMat != null)
            {
                _circlePointsRealModelMat.release();
            }
            if (_circlePointsDetectedWorldMat != null)
            {
                _circlePointsDetectedWorldMat.release();
            }
            _circlePointsProjectorRenderImageMat.alloc(_circlePatternPointCount);
            _circlePointsRealModelMat.alloc(_circlePatternPointCount);
            _circlePointsDetectedWorldMat.alloc(_circlePatternPointCount);

            // Render pattern to texture.
            _circlePatternBorderSizeUV = TrackingToolsHelper.RenderPattern(_circlePatternSize, TrackingToolsHelper.PatternType.AsymmetricCircleGrid, 2048, ref _circlePatternTexture, ref _patternRenderMaterial, circlePatternBorder, true);
            _circlePatternBoardMaterial.mainTexture = _circlePatternTexture;

            // Update transform to match.
            float circleTextureAspect = _circlePatternTexture.width / (float)_circlePatternTexture.height;
            float borderProportion    = (_circlePatternSize.y - 1 + 2f) / (_circlePatternSize.y - 1f);              // Asymmetric patttern tiles are half the height.

            _circlePatternTransform.localScale = new Vector3(circleTextureAspect, 1, 0) * _chessPatternTransform.localScale.y * borderProportion;

            if (_state == State.TrackedCalibration || _state == State.Testing)
            {
                _circlePatternTransform.localPosition = -Vector3.right * (_chessCirclePatternCenterOffset / 1000f);
            }
        }
Exemple #5
0
        void Update()
        {
            if (Input.GetKeyDown(_interactibaleHotKey))
            {
                if (!interactable && _cameraTexture == null)
                {
                    Debug.LogWarning(logPrepend + "Missing camera texture.\n");
                    return;
                }
                interactable = !interactable;
            }

            if (!_cameraTexture)
            {
                return;
            }

            // Adapt resources.
            AdaptResources();

            if (_dirtyTexture)
            {
                // Undistort.
                if (_cameraTexture is WebCamTexture)
                {
                    Utils.webCamTextureToMat(_cameraTexture as WebCamTexture, _camTexMat, flip: false);
                }
                else if (_cameraTexture is Texture2D)
                {
                    Utils.fastTexture2DToMat(_cameraTexture as Texture2D, _camTexMat, flip: false);
                }
                else
                {
                    Debug.LogWarning(logPrepend + "Only Texture2D and WenCamTexture is supported.\n");
                    return;
                }
                TrackingToolsHelper.ColorMatToLumanceMat(_camTexMat, _camTexGrayMat);
                Calib3d.undistort(_camTexGrayMat, _camTexGrayUndistortMat, _cameraMatrix, _distCoeffs);
                Utils.fastMatToTexture2D(_camTexGrayUndistortMat, _undistortedCameraTexture);
                _dirtyTexture = false;
            }

            if (_interactable)
            {
                UpdateInteraction();
            }

            if (_dirtyPoints)
            {
                UpdateCameraTransform();
                _dirtyPoints = false;
            }
        }
Exemple #6
0
        void PreProcessCameraImage()
        {
            // Convert texture to mat (If the texture looks right in Unity, it needs to be flipped for OpenCV).
            TrackingToolsHelper.TextureToMat(_cameraTexture, !_flipCameraTexture, ref _camTexMat, ref _tempTransferColors, ref _tempTransferTexture);

            // Convert to grayscale if more than one channel, else copy (and convert bit rate if necessary).
            TrackingToolsHelper.ColorMatToLumanceMat(_camTexMat, _camTexGrayMat);

            // Undistort.
            //Calib3d.undistort( _camTexGrayMat, _camTexGrayUndistortMat, _sensorMat, _distortionCoeffsMat );
            Imgproc.remap(_camTexGrayMat, _camTexGrayUndistortMat, _undistortMap1, _undistortMap2, Imgproc.INTER_LINEAR);
        }
Exemple #7
0
        void Awake()
        {
            Application.targetFrameRate = 30;

            _chessPatternPointCount = _chessPatternSize.x * _chessPatternSize.y;

            // Prepare OpenCV.
            _extrinsicsCalibrator     = new CameraExtrinsicsCalibrator();
            _prevChessCorners         = new Vector2[_chessPatternPointCount];
            _chessCornersRealModelMat = TrackingToolsHelper.CreateRealModelPatternPoints(_chessPatternSize, _chessTileSize, TrackingToolsHelper.PatternType.Chessboard);

            // Create objects.
            _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);

            // Prepare world points.
            TrackingToolsHelper.UpdateWorldSpacePatternPoints(_chessPatternSize, _chessPatternTransform.localToWorldMatrix, TrackingToolsHelper.PatternType.Chessboard, Vector2.zero, ref _chessCornersWorldMat);

            // Prepare UI.
            TrackingToolsHelper.RenderPattern(_chessPatternSize, TrackingToolsHelper.PatternType.Chessboard, 1024, ref _chessPatternTexture, ref _patternRenderMaterial);
            _aspectFitter = _processedCameraImage.GetComponent <AspectRatioFitter>();
            if (!_aspectFitter)
            {
                _aspectFitter = _processedCameraImage.gameObject.AddComponent <AspectRatioFitter>();
            }
            _aspectFitter.aspectMode = AspectRatioFitter.AspectMode.FitInParent;
            Shader shader = Shader.Find(TrackingToolsConstants.previewShaderName);

            _previewMaterial = new Material(shader);
            _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);
            Shader   unlitTextureShader = Shader.Find("Unlit/Texture");
            Material chessboardMaterial = new Material(unlitTextureShader);

            chessboardMaterial.mainTexture = _chessPatternTexture;
            _chessPatternTransform.GetComponent <Renderer>().material = chessboardMaterial;
            if (_sampleCountMeterFillImage)
            {
                _sampleCountMeterFillImage.fillAmount = 0;
            }
            _previewFlasher = new MaterialPropFlasher(_previewMaterial, "_Whiteout", TrackingToolsConstants.flashDuration);

            // Setup camera.
            _mainCamera.backgroundColor = Color.clear;
            _mainCamera.gameObject.SetActive(false);
        }
Exemple #8
0
        bool FindAndApplyChessPatternExtrinsics()
        {
            bool found = TrackingToolsHelper.FindChessboardCorners(_camTexGrayUndistortMat, _chessPatternSize, ref _chessCornersImageMat);

            if (found)
            {
                TrackingToolsHelper.DrawFoundPattern(_camTexGrayUndistortMat, _chessPatternSize, _chessCornersImageMat);
                _cameraExtrinsicsCalibrator.UpdateExtrinsics(_chessCornersWorldMat, _chessCornersImageMat, _cameraIntrinsics, _cameraTexture.width, _cameraTexture.height);
                const bool transformBoard = true;
                _cameraExtrinsicsCalibrator.extrinsics.ApplyToTransform(_calibrationBoardTransform, _mainCamera.transform, transformBoard);
            }
            _chessPatternTransform.gameObject.SetActive(found);
            return(found);
        }
Exemple #9
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);
        }
Exemple #10
0
        void UpdateCirclePatternInProjectorImage()
        {
            // We will be raycasting from the projector camera. In the editor, the aspect can change depending on the main game view, so we have to ensure that it matches.
            _projectorCamera.targetTexture = _arTexture;

            // Use the circle pattern transform from last update frame, because it is more likely that it will match the detected reality.
            TrackingToolsHelper.UpdateWorldSpacePatternPoints(_circlePatternSize, _circlePatternToWorldPrevFrame, TrackingToolsHelper.PatternType.AsymmetricCircleGrid, _circlePatternBorderSizeUV, ref _circlePointsRenderedWorldMat);
            for (int p = 0; p < _circlePatternPointCount; p++)
            {
                Vector3 worldPoint    = _circlePointsRenderedWorldMat.ReadVector3(p);
                Vector3 viewportPoint = _projectorCamera.WorldToViewportPoint(worldPoint);
                Vector2 imagePoint    = new Vector2(viewportPoint.x * _cameraTexture.width, (1 - viewportPoint.y) * _cameraTexture.height);                  // Viewport space has zero at bottom-left, image space (opencv) has zero at top-left. So flip y.
                _circlePointsProjectorRenderImageMat.WriteVector2(imagePoint, p);
            }
            //TrackingToolsHelper.DrawFoundPattern( _camTexGrayUndistortMat, circlesPatternSize, _circlePointsProjectorRenderImageMat ); // Testing

            // Reset render target.
            _projectorCamera.targetTexture = null;
        }
Exemple #11
0
        void UpdateCameraTransform()
        {
            // Update points.
            for (int p = 0; p < pointCount; p++)
            {
                Vector2 posImage = _userPointRects[p].anchorMin;
                posImage.Scale(new Vector2(_cameraTexture.width, _cameraTexture.height));
                _anchorPointsImage[p].set(new double[] { posImage.x, posImage.y });
                Vector3 posWorld = _anchorTransform.TransformPoint(defaultPointPositions[p] - Vector2.one * 0.5f);
                _anchorPointsWorld[p].set(new double[] { posWorld.x, posWorld.y, posWorld.z });
            }
            _anchorPointsImageMat.fromArray(_anchorPointsImage);
            _anchorPointsWorldMat.fromArray(_anchorPointsWorld);

            // Compute
            bool success = Calib3d.solvePnP(_anchorPointsWorldMat, _anchorPointsImageMat, _cameraMatrix, _noDistCoeffs, _rVec, _tVec);

            if (!success)
            {
                return;
            }

            // Convert.
            bool inverse = true;

            TrackingToolsHelper.ApplyPose(_rVec, _tVec, _targetCameraTransform, inverse);

            /*
             * Vector3 translation = TrackingToolsHelper.TranslationMatVectorToVector3( _tVec  );
             * Quaternion rotation = TrackingToolsHelper.RotationMatVectorToQuaternion( _rVec );
             * translation = rotation * translation;
             *
             * // Apply.
             * _targetCameraTransform.SetPositionAndRotation( translation, rotation );
             */

            // Save.
            SaveCircleAnchorPoints();
        }
Exemple #12
0
        bool DetectAndRaycastCirclePatternOntoChessboardPlane()
        {
            // Find circle pattern in camera image
            Core.bitwise_not(_camTexGrayUndistortMat, _camTexGrayUndistortInvMat);               // Invert. We need dark circles on a bright background.
            if (!TrackingToolsHelper.FindAsymmetricCirclesGrid(_camTexGrayUndistortInvMat, _circlePatternSize, ref _circlePointsCameraImageMat))
            {
                return(false);
            }

            // Draw deteted circles.
            TrackingToolsHelper.DrawFoundPattern(_camTexGrayUndistortMat, _circlePatternSize, _circlePointsCameraImageMat);

            // Raycast circles against chessboard plane.
            _calibrationboardPlane.SetNormalAndPosition(_calibrationBoardTransform.forward, _calibrationBoardTransform.position);
            for (int p = 0; p < _circlePatternPointCount; p++)
            {
                // Tranform from points detected by camera to points in Unity world space.
                Vector2 cameraImagePoint = _circlePointsCameraImageMat.ReadVector2(p);
                cameraImagePoint.y = _cameraTexture.height - cameraImagePoint.y;                 // Unity screen space has zero at bottom-left, OpenCV textures has zero at top-left.
                Ray   ray = _mainCamera.ScreenPointToRay(cameraImagePoint);
                float hitDistance;
                if (!_calibrationboardPlane.Raycast(ray, out hitDistance))
                {
                    return(false);
                }

                // For extrinsics calibration (using stereoCalibrate()).
                Vector3 worldPoint = ray.origin + ray.direction * hitDistance;
                _circlePointsDetectedWorldMat.WriteVector3(worldPoint, p);

                // For intrinsics calibration (using calibrateCalmera()).
                Vector3 realModelPoint = Quaternion.Inverse(_calibrationBoardTransform.rotation) * (worldPoint - _calibrationBoardTransform.position);
                realModelPoint.z = 0;                 // Remove very small numbers. It seems CalibrateCamera() does not accept varying z values. I got an execption.
                realModelPoint  *= 1000;              // To millimeters
                _circlePointsRealModelMat.WriteVector3(realModelPoint, p);
            }
            return(true);
        }
Exemple #13
0
        public void SaveToFile(string optionalFileName = null)
        {
            // If we are in fast and imprecise mode, then detect and update again with higher precision before saving.
            if (_fastAndImprecise)
            {
                TrackingToolsHelper.FindChessboardCorners(_camTexGrayUndistortMat, _chessPatternSize, ref _chessCornersImageMat);
                _extrinsicsCalibrator.UpdateExtrinsics(_chessCornersWorldMat, _chessCornersImageMat, _intrinsics, _cameraTexture.width, _cameraTexture.height);
            }

            if (!_extrinsicsCalibrator.isValid)
            {
                Debug.LogWarning("Save extrinsics to file failed. No chessboard was found in camera image.\n");
                return;
            }

            if (!string.IsNullOrEmpty(optionalFileName))
            {
                _extrinsicsFileName = optionalFileName;
            }

            _extrinsicsCalibrator.extrinsics.SaveToFile(_extrinsicsFileName);

            Debug.Log(logPrepend + "Saved extrinsics to file.\n" + _extrinsicsFileName);
        }
Exemple #14
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);;
            }
        }
Exemple #15
0
        void Update()
        {
            if (!_cameraTexture || !_dirtyCameraTexture)
            {
                return;
            }

            if (!AdaptResources())
            {
                return;
            }

            // Update mat texture (If the textyre looks right in Unity, it needs to be flipped for OpenCV.)
            TrackingToolsHelper.TextureToMat(_cameraTexture, !_flipCameraTexture, ref _camTexMat, ref _tempTransferColors, ref _tempTransferTexture);

            // Convert to grayscale if more than one channel, else copy (and convert bit rate if necessary).
            TrackingToolsHelper.ColorMatToLumanceMat(_camTexMat, _camTexGrayMat);

            // Undistort (TODO: move undistortion to GPU as last step and work on distorted image instead).
            //Calib3d.undistort( _camTexGrayMat, _camTexGrayUndistortMat, _sensorMat, _distortionCoeffsMat );
            Imgproc.remap(_camTexGrayMat, _camTexGrayUndistortMat, _undistortMap1, _undistortMap2, Imgproc.INTER_LINEAR);

            // Find chessboard.
            bool foundBoard = TrackingToolsHelper.FindChessboardCorners(_camTexGrayUndistortMat, _chessPatternSize, ref _chessCornersImageMat, _fastAndImprecise);

            if (foundBoard)
            {
                // Draw chessboard.
                TrackingToolsHelper.DrawFoundPattern(_camTexGrayUndistortMat, _chessPatternSize, _chessCornersImageMat);

                // Update and apply extrinsics.
                bool foundExtrinsics = _extrinsicsCalibrator.UpdateExtrinsics(_chessCornersWorldMat, _chessCornersImageMat, _intrinsics, _cameraTexture.width, _cameraTexture.height);
                if (foundExtrinsics)
                {
                    if (_tranformPattern)
                    {
                        _extrinsicsCalibrator.extrinsics.ApplyToTransform(_chessPatternTransform, _applyRelative ? _mainCamera.transform : null, _tranformPattern);
                        if (!_applyRelative)
                        {
                            _mainCamera.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
                        }
                    }
                    else
                    {
                        _extrinsicsCalibrator.extrinsics.ApplyToTransform(_mainCamera.transform, _applyRelative ? _chessPatternTransform : null);
                        if (!_applyRelative)
                        {
                            _chessPatternTransform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
                        }
                    }
                }
                _arImage.gameObject.SetActive(foundExtrinsics);
            }
            else
            {
                _arImage.gameObject.SetActive(false);
            }

            // UI.
            Utils.fastMatToTexture2D(_camTexGrayUndistortMat, _processedCameraTexture);               // Flips vertically by default
            if (_precisionDotsContainerObject.activeSelf != _testPrecisionDotsEnabled)
            {
                _precisionDotsContainerObject.SetActive(_testPrecisionDotsEnabled);
            }


            _dirtyCameraTexture = false;
        }