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); } }
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; }
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; }
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); } }
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; } }
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); }
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); }
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); }
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); }
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; }
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(); }
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); }
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); }
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);; } }
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; }