1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516 |
- using UnityEngine;
- using UnityEngine.UI;
- using UnityEngine.SceneManagement;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Xml.Serialization;
- using System.IO;
- using System.Linq;
- using OpenCVForUnity.CoreModule;
- using OpenCVForUnity.ImgprocModule;
- using OpenCVForUnity.Calib3dModule;
- using OpenCVForUnity.UnityUtils;
- using OpenCVForUnity.ImgcodecsModule;
- using OpenCVForUnity.UnityUtils.Helper;
- using OpenCVForUnity.ObjdetectModule;
- using OpenCVForUnity.ArucoModule;
- namespace OpenCVForUnityExample
- {
- /// <summary>
- /// ArUco Camera Calibration Example
- /// An example of camera calibration using the objdetect module. (ChessBoard, CirclesGlid, AsymmetricCirclesGlid and ChArUcoBoard)
- /// Referring to https://docs.opencv.org/master/d4/d94/tutorial_camera_calibration.html.
- /// https://github.com/opencv/opencv/blob/master/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp
- /// https://docs.opencv.org/3.4.0/d7/d21/tutorial_interactive_calibration.html
- /// https://github.com/opencv/opencv/tree/master/apps/interactive-calibration
- /// https://docs.opencv.org/3.2.0/da/d13/tutorial_aruco_calibration.html
- /// https://github.com/opencv/opencv_contrib/blob/master/modules/aruco/samples/calibrate_camera_charuco.cpp
- /// </summary>
- [RequireComponent(typeof(WebCamTextureToMatHelper))]
- public class ArUcoCameraCalibrationExample : MonoBehaviour
- {
- /// <summary>
- /// The marker type used for calibration.
- /// </summary>
- [Tooltip("The marker type used for calibration.")]
- public MarkerType markerType = MarkerType.ChessBoard;
- /// <summary>
- /// The marker type dropdown.
- /// </summary>
- public Dropdown markerTypeDropdown;
- /// <summary>
- /// Number of inner corners per a item column. (square, circle)
- /// </summary>
- [Tooltip("Number of inner corners per a item column. (square, circle)")]
- public NumberOfBoardSizeWidth boardSizeW = NumberOfBoardSizeWidth.W_9;
- /// <summary>
- /// The board size W dropdown.
- /// </summary>
- public Dropdown boardSizeWDropdown;
- /// <summary>
- /// Number of inner corners per a item row. (square, circle)
- /// </summary>
- [Tooltip("Number of inner corners per a item row. (square, circle)")]
- public NumberOfBoardSizeHeight boardSizeH = NumberOfBoardSizeHeight.H_6;
- /// <summary>
- /// The board size H dropdown.
- /// </summary>
- public Dropdown boardSizeHDropdown;
- /// <summary>
- /// The save path input field.
- /// </summary>
- public InputField savePathInputField;
- /// <summary>
- /// The show undistort image.
- /// </summary>
- public bool showUndistortImage = true;
- /// <summary>
- /// The show undistort image toggle.
- /// </summary>
- public Toggle showUndistortImageToggle;
- [Header("Normal Calibration Option")]
- /// <summary>
- /// The normal calibration options group.
- /// </summary>
- public GameObject normalCalibrationOptionsGroup;
- /// <summary>
- /// The size of a square in some user defined metric system (pixel, millimeter)
- /// </summary>
- [Tooltip("The size of a square in some user defined metric system (pixel, millimeter)")]
- public float squareSize = 50f;
- /// <summary>
- /// The square size input field.
- /// </summary>
- public InputField squareSizeInputField;
- /// <summary>
- /// If your calibration board is inaccurate, unmeasured, roughly planar targets
- /// (Checkerboard patterns on paper using off-the-shelf printers are the most convenient calibration targets and most of them are not accurate enough.),
- /// a method from [219] can be utilized to dramatically improve the accuracies of the estimated camera intrinsic parameters.
- /// Need to set the measured values from the actual chess board to "squareSize" and "gridWidth".
- /// https://docs.opencv.org/4.2.0/d9/d0c/group__calib3d.html#ga11eeb16e5a458e1ed382fb27f585b753
- /// </summary>
- [Tooltip("If your calibration board is inaccurate, unmeasured, roughly planar targets (Checkerboard patterns on paper using off-the-shelf printers are the most convenient calibration targets and most of them are not accurate enough.), a method from [219] can be utilized to dramatically improve the accuracies of the estimated camera intrinsic parameters. Need to set the measured values from the actual chess board to \"squareSize\" and \"gridWidth\".")]
- public bool useNewCalibrationMethod = true;
- /// <summary>
- /// The use new calibration method toggle.
- /// </summary>
- public Toggle useNewCalibrationMethodToggle;
- /// <summary>
- /// The measured distance between top-left (0, 0, 0) and top-right (squareSize*(boardSizeW - 1), 0, 0) corners of the pattern grid points.
- /// </summary>
- [Tooltip("The measured distance between top-left (0, 0, 0) and top-right (squareSize*(boardSizeW - 1), 0, 0) corners of the pattern grid points.")]
- public float gridWidth = 400f;
- /// <summary>
- /// The glid width input field.
- /// </summary>
- public InputField gridWidthInputField;
- /// <summary>
- /// Determines if use findChessboardCornersSB method. (More accurate than the findChessboardCorners and cornerSubPix methods)
- /// https://docs.opencv.org/4.2.0/d9/d0c/group__calib3d.html#gad0e88e13cd3d410870a99927510d7f91
- /// </summary>
- [Tooltip("Determines if use findChessboardCornersSB method. (More accurate than the findChessboardCorners and cornerSubPix methods)")]
- public bool useFindChessboardCornersSBMethod = true;
- /// <summary>
- /// Determines if enable CornerSubPix method. (Improve the found corners' coordinate accuracy for chessboard)
- /// </summary>
- [Tooltip("Determines if enable CornerSubPix method. (Improve the found corners' coordinate accuracy for chessboard)")]
- public bool enableCornerSubPix = true;
- [Header("ArUco Calibration Option")]
- /// <summary>
- /// The arUco calibration options group.
- /// </summary>
- public GameObject arUcoCalibrationOptionsGroup;
- /// <summary>
- /// The dictionary identifier used for ArUco marker detection.
- /// </summary>
- [Tooltip("The dictionary identifier used for ArUco marker detection.")]
- public ArUcoDictionary dictionaryId = ArUcoDictionary.DICT_6X6_250;
- /// <summary>
- /// The dictionary id dropdown.
- /// </summary>
- public Dropdown dictionaryIdDropdown;
- /// <summary>
- /// Determines if refine marker detection. (only valid for ArUco boards)
- /// </summary>
- [Tooltip("Determines if refine marker detection. (only valid for ArUco boards)")]
- public bool refineMarkerDetection = true;
- [Header("Image Input Option")]
- /// <summary>
- /// Determines if calibrates camera using the list of calibration images.
- /// </summary>
- [Tooltip("Determines if calibrates camera using the list of calibration images.")]
- public bool isImagesInputMode = false;
- /// <summary>
- /// The calibration images directory path.
- /// Set a relative directory path from the starting point of the "StreamingAssets" folder. e.g. "objdetect/calibration_images/".
- /// </summary>
- [Tooltip("Set a relative directory path from the starting point of the \"StreamingAssets\" folder. e.g. \"OpenCVForUnity/objdetect/calibration_images\"")]
- public string calibrationImagesDirectory = "OpenCVForUnity/objdetect/calibration_images";
- /// <summary>
- /// The texture.
- /// </summary>
- Texture2D texture;
- /// <summary>
- /// The webcam texture to mat helper.
- /// </summary>
- WebCamTextureToMatHelper webCamTextureToMatHelper;
- /// <summary>
- /// The gray mat.
- /// </summary>
- Mat grayMat;
- /// <summary>
- /// The bgr mat.
- /// </summary>
- Mat bgrMat;
- /// <summary>
- /// The undistorted bgr mat.
- /// </summary>
- Mat undistortedBgrMat;
- /// <summary>
- /// The rgba mat.
- /// </summary>
- Mat rgbaMat;
- /// <summary>
- /// The cameraparam matrix.
- /// </summary>
- Mat camMatrix;
- /// <summary>
- /// The distortion coeffs.
- /// </summary>
- MatOfDouble distCoeffs;
- /// <summary>
- /// The rvecs.
- /// </summary>
- List<Mat> rvecs;
- /// <summary>
- /// The tvecs.
- /// </summary>
- List<Mat> tvecs;
- List<Mat> imagePoints;
- List<Mat> allImgs;
- bool isInitialized = false;
- bool isCalibrating = false;
- double repErr = 0;
- bool shouldCaptureFrame = false;
- const int findChessboardCornersFlags =
- Calib3d.CALIB_CB_ADAPTIVE_THRESH |
- Calib3d.CALIB_CB_NORMALIZE_IMAGE |
- //Calib3d.CALIB_CB_FILTER_QUADS |
- Calib3d.CALIB_CB_FAST_CHECK |
- 0;
- const int findChessboardCornersSBFlags =
- Calib3d.CALIB_CB_NORMALIZE_IMAGE |
- Calib3d.CALIB_CB_EXHAUSTIVE |
- Calib3d.CALIB_CB_ACCURACY |
- 0;
- const int findCirclesGridFlags =
- //Calib3d.CALIB_CB_CLUSTERING |
- 0;
- const int calibrationFlags =
- //Calib3d.CALIB_USE_INTRINSIC_GUESS |
- //Calib3d.CALIB_FIX_PRINCIPAL_POINT |
- //Calib3d.CALIB_FIX_ASPECT_RATIO |
- //Calib3d.CALIB_ZERO_TANGENT_DIST |
- //Calib3d.CALIB_FIX_K1 |
- //Calib3d.CALIB_FIX_K2 |
- //Calib3d.CALIB_FIX_K3 |
- //Calib3d.CALIB_FIX_K4 |
- //Calib3d.CALIB_FIX_K5 |
- Calib3d.CALIB_USE_LU |
- 0;
- /*
- // for ChArUcoBoard.
- // chessboard square side length (normally in meters)
- const float chArUcoBoradSquareLength = 0.04f;
- // marker side length (same unit than squareLength)
- const float chArUcoBoradMarkerLength = 0.02f;
- const int charucoMinMarkers = 2;
- Mat ids;
- List<Mat> corners;
- List<Mat> rejectedCorners;
- Mat recoveredIdxs;
- Mat charucoCorners;
- Mat charucoIds;
- CharucoBoard charucoBoard;
- ArucoDetector arucoDetector;
- CharucoDetector charucoDetector;
- */
- Dictionary dictionary;
- List<List<Mat>> allCorners;
- List<Mat> allIds;
- // Use this for initialization
- IEnumerator Start()
- {
- //if true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console.
- Utils.setDebugMode(true);
- webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper>();
- // fix the screen orientation.
- Screen.orientation = ScreenOrientation.LandscapeLeft;
- // wait for the screen orientation to change.
- yield return null;
- markerTypeDropdown.value = (int)markerType;
- boardSizeWDropdown.value = (int)boardSizeW - 1;
- boardSizeHDropdown.value = (int)boardSizeH - 1;
- showUndistortImageToggle.isOn = showUndistortImage;
- squareSizeInputField.text = squareSize.ToString();
- useNewCalibrationMethodToggle.isOn = useNewCalibrationMethod;
- gridWidthInputField.text = gridWidth.ToString();
- dictionaryIdDropdown.value = (int)dictionaryId;
- bool arUcoCalibMode = markerType == MarkerType.ChArUcoBoard;
- normalCalibrationOptionsGroup.gameObject.SetActive(!arUcoCalibMode);
- arUcoCalibrationOptionsGroup.gameObject.SetActive(arUcoCalibMode);
- #if UNITY_WEBGL && !UNITY_EDITOR
- isImagesInputMode = false;
- #endif
- if (isImagesInputMode)
- {
- isImagesInputMode = InitializeImagesInputMode();
- }
- if (!isImagesInputMode)
- {
- #if UNITY_ANDROID && !UNITY_EDITOR
- // Avoids the front camera low light issue that occurs in only some Android devices (e.g. Google Pixel, Pixel2).
- webCamTextureToMatHelper.avoidAndroidFrontCameraLowLightIssue = true;
- #endif
- webCamTextureToMatHelper.Initialize();
- }
- }
- /// <summary>
- /// Raises the webcam texture to mat helper initialized event.
- /// </summary>
- public void OnWebCamTextureToMatHelperInitialized()
- {
- Debug.Log("OnWebCamTextureToMatHelperInitialized");
- Mat webCamTextureMat = webCamTextureToMatHelper.GetMat();
- InitializeCalibraton(webCamTextureMat);
- // If the WebCam is front facing, flip the Mat horizontally. Required for successful detection of AR markers.
- if (webCamTextureToMatHelper.IsFrontFacing() && !webCamTextureToMatHelper.flipHorizontal)
- {
- webCamTextureToMatHelper.flipHorizontal = true;
- }
- else if (!webCamTextureToMatHelper.IsFrontFacing() && webCamTextureToMatHelper.flipHorizontal)
- {
- webCamTextureToMatHelper.flipHorizontal = false;
- }
- }
- /// <summary>
- /// Raises the webcam texture to mat helper disposed event.
- /// </summary>
- public void OnWebCamTextureToMatHelperDisposed()
- {
- Debug.Log("OnWebCamTextureToMatHelperDisposed");
- DisposeCalibraton();
- }
- /// <summary>
- /// Raises the webcam texture to mat helper error occurred event.
- /// </summary>
- /// <param name="errorCode">Error code.</param>
- public void OnWebCamTextureToMatHelperErrorOccurred(WebCamTextureToMatHelper.ErrorCode errorCode)
- {
- Debug.Log("OnWebCamTextureToMatHelperErrorOccurred " + errorCode);
- }
- // Update is called once per frame
- void Update()
- {
- if (isImagesInputMode)
- return;
- if (webCamTextureToMatHelper.IsPlaying() && webCamTextureToMatHelper.DidUpdateThisFrame())
- {
- Mat rgbaMat = webCamTextureToMatHelper.GetMat();
- Imgproc.cvtColor(rgbaMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
- if (shouldCaptureFrame)
- {
- shouldCaptureFrame = false;
- Mat frameMat = grayMat.clone();
- double e = CaptureFrame(frameMat);
- if (e > 0)
- repErr = e;
- }
- DrawFrame(grayMat, bgrMat);
- if (showUndistortImage)
- {
- Calib3d.undistort(bgrMat, undistortedBgrMat, camMatrix, distCoeffs);
- DrawCalibrationResult(undistortedBgrMat);
- Imgproc.cvtColor(undistortedBgrMat, rgbaMat, Imgproc.COLOR_BGR2RGBA);
- }
- else
- {
- DrawCalibrationResult(bgrMat);
- Imgproc.cvtColor(bgrMat, rgbaMat, Imgproc.COLOR_BGR2RGBA);
- }
- Utils.matToTexture2D(rgbaMat, texture);
- }
- }
- private void InitializeCalibraton(Mat frameMat)
- {
- texture = new Texture2D(frameMat.cols(), frameMat.rows(), TextureFormat.RGBA32, false);
- Utils.matToTexture2D(frameMat, texture);
- gameObject.GetComponent<Renderer>().material.mainTexture = texture;
- gameObject.transform.localScale = new Vector3(frameMat.cols(), frameMat.rows(), 1);
- Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
- float width = frameMat.width();
- float height = frameMat.height();
- float imageSizeScale = 1.0f;
- float widthScale = (float)Screen.width / width;
- float heightScale = (float)Screen.height / height;
- if (widthScale < heightScale)
- {
- Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
- imageSizeScale = (float)Screen.height / (float)Screen.width;
- }
- else
- {
- Camera.main.orthographicSize = height / 2;
- }
- // set cameraparam.
- camMatrix = CreateCameraMatrix(width, height);
- Debug.Log("camMatrix " + camMatrix.dump());
- distCoeffs = new MatOfDouble(0, 0, 0, 0, 0);
- Debug.Log("distCoeffs " + distCoeffs.dump());
- // calibration camera.
- Size imageSize = new Size(width * imageSizeScale, height * imageSizeScale);
- double apertureWidth = 0;
- double apertureHeight = 0;
- double[] fovx = new double[1];
- double[] fovy = new double[1];
- double[] focalLength = new double[1];
- Point principalPoint = new Point(0, 0);
- double[] aspectratio = new double[1];
- Calib3d.calibrationMatrixValues(camMatrix, imageSize, apertureWidth, apertureHeight, fovx, fovy, focalLength, principalPoint, aspectratio);
- Debug.Log("imageSize " + imageSize.ToString());
- Debug.Log("apertureWidth " + apertureWidth);
- Debug.Log("apertureHeight " + apertureHeight);
- Debug.Log("fovx " + fovx[0]);
- Debug.Log("fovy " + fovy[0]);
- Debug.Log("focalLength " + focalLength[0]);
- Debug.Log("principalPoint " + principalPoint.ToString());
- Debug.Log("aspectratio " + aspectratio[0]);
- grayMat = new Mat(frameMat.rows(), frameMat.cols(), CvType.CV_8UC1);
- bgrMat = new Mat(frameMat.rows(), frameMat.cols(), CvType.CV_8UC3);
- undistortedBgrMat = new Mat();
- rgbaMat = new Mat(frameMat.rows(), frameMat.cols(), CvType.CV_8UC4);
- rvecs = new List<Mat>();
- tvecs = new List<Mat>();
- imagePoints = new List<Mat>();
- allImgs = new List<Mat>();
- /*
- ids = new Mat();
- corners = new List<Mat>();
- rejectedCorners = new List<Mat>();
- recoveredIdxs = new Mat();
- DetectorParameters detectorParams = new DetectorParameters();
- detectorParams.set_minDistanceToBorder(3);
- detectorParams.set_useAruco3Detection(true);
- detectorParams.set_cornerRefinementMethod(Objdetect.CORNER_REFINE_SUBPIX);
- detectorParams.set_minSideLengthCanonicalImg(16);
- detectorParams.set_errorCorrectionRate(0.8);
- dictionary = Objdetect.getPredefinedDictionary((int)dictionaryId);
- RefineParameters refineParameters = new RefineParameters(10f, 3f, true);
- arucoDetector = new ArucoDetector(dictionary, detectorParams, refineParameters);
- charucoCorners = new Mat();
- charucoIds = new Mat();
- charucoBoard = new CharucoBoard( new Size((int)boardSizeW, (int)boardSizeH), chArUcoBoradSquareLength, chArUcoBoradMarkerLength, dictionary);
- charucoDetector = new CharucoDetector(charucoBoard);
- CharucoParameters charucoParameters = charucoDetector.getCharucoParameters();
- charucoParameters.set_cameraMatrix(camMatrix);
- charucoParameters.set_distCoeffs(distCoeffs);
- charucoParameters.set_minMarkers(charucoMinMarkers);
- charucoDetector.setCharucoParameters(charucoParameters);
- charucoDetector.setDetectorParameters(detectorParams);
- charucoDetector.setRefineParameters(refineParameters);
- */
- allIds = new List<Mat>();
- allCorners = new List<List<Mat>>();
- isInitialized = true;
- }
- private void DisposeCalibraton()
- {
- ResetCalibration();
- if (grayMat != null)
- grayMat.Dispose();
- if (bgrMat != null)
- bgrMat.Dispose();
- if (undistortedBgrMat != null)
- undistortedBgrMat.Dispose();
- if (rgbaMat != null)
- rgbaMat.Dispose();
- if (texture != null)
- {
- Texture2D.Destroy(texture);
- texture = null;
- }
- foreach (var item in rvecs)
- {
- item.Dispose();
- }
- rvecs.Clear();
- foreach (var item in tvecs)
- {
- item.Dispose();
- }
- tvecs.Clear();
- /*
- if (ids != null)
- ids.Dispose();
- foreach (var item in corners)
- {
- item.Dispose();
- }
- corners.Clear();
- foreach (var item in rejectedCorners)
- {
- item.Dispose();
- }
- rejectedCorners.Clear();
- if (recoveredIdxs != null)
- recoveredIdxs.Dispose();
- if (charucoCorners != null)
- charucoCorners.Dispose();
- if (charucoIds != null)
- charucoIds.Dispose();
- if (charucoBoard != null)
- charucoBoard.Dispose();
- if (arucoDetector != null)
- arucoDetector.Dispose();
- if (charucoDetector != null)
- charucoDetector.Dispose();
- */
- isInitialized = false;
- }
- private void DrawFrame(Mat grayMat, Mat bgrMat)
- {
- Imgproc.cvtColor(grayMat, bgrMat, Imgproc.COLOR_GRAY2BGR);
- switch (markerType)
- {
- default:
- case MarkerType.ChessBoard:
- case MarkerType.CirclesGlid:
- case MarkerType.AsymmetricCirclesGlid:
- // detect markers.
- MatOfPoint2f points = new MatOfPoint2f();
- bool found = false;
- switch (markerType)
- {
- default:
- case MarkerType.ChessBoard:
- if (useFindChessboardCornersSBMethod)
- {
- found = Calib3d.findChessboardCornersSB(grayMat, new Size((int)boardSizeW, (int)boardSizeH), points, findChessboardCornersSBFlags);
- }
- else
- {
- found = Calib3d.findChessboardCorners(grayMat, new Size((int)boardSizeW, (int)boardSizeH), points, findChessboardCornersFlags);
- }
- break;
- case MarkerType.CirclesGlid:
- found = Calib3d.findCirclesGrid(grayMat, new Size((int)boardSizeW, (int)boardSizeH), points, findCirclesGridFlags | Calib3d.CALIB_CB_SYMMETRIC_GRID);
- break;
- case MarkerType.AsymmetricCirclesGlid:
- found = Calib3d.findCirclesGrid(grayMat, new Size((int)boardSizeW, (int)boardSizeH), points, findCirclesGridFlags | Calib3d.CALIB_CB_ASYMMETRIC_GRID);
- break;
- }
- if (found)
- {
- // draw markers.
- Calib3d.drawChessboardCorners(bgrMat, new Size((int)boardSizeW, (int)boardSizeH), points, found);
- }
- break;
- case MarkerType.ChArUcoBoard:
- /*
- // detect markers.
- arucoDetector.detectMarkers(grayMat, corners, ids, rejectedCorners);
- // refine marker detection.
- if (refineMarkerDetection)
- {
- // https://github.com/opencv/opencv/blob/377be68d923e40900ac5526242bcf221e3f355e5/modules/objdetect/src/aruco/charuco_detector.cpp#L310
- arucoDetector.refineDetectedMarkers(grayMat, charucoBoard, corners, ids, rejectedCorners);
- }
- // if at least one marker detected
- if (ids.total() > 0)
- {
- charucoDetector.detectBoard(grayMat, charucoCorners, charucoIds, corners, ids);
- // draw markers.
- if (corners.Count == ids.total() || ids.total() == 0)
- Objdetect.drawDetectedMarkers(bgrMat, corners, ids, new Scalar(0, 255, 0, 255));
- // if at least one charuco corner detected
- if (charucoCorners.total() == charucoIds.total() || charucoIds.total() == 0)
- {
- Objdetect.drawDetectedCornersCharuco(bgrMat, charucoCorners, charucoIds, new Scalar(0, 0, 255, 255));
- }
- }
- */
- break;
- }
- }
- private void DrawCalibrationResult(Mat bgrMat)
- {
- double[] camMatrixArr = new double[(int)camMatrix.total()];
- camMatrix.get(0, 0, camMatrixArr);
- double[] distCoeffsArr = new double[(int)distCoeffs.total()];
- distCoeffs.get(0, 0, distCoeffsArr);
- int textLeft = 320;
- int ff = Imgproc.FONT_HERSHEY_SIMPLEX;
- double fs = 0.4;
- Scalar c = new Scalar(255, 255, 255, 255);
- int t = 0;
- int lt = Imgproc.LINE_AA;
- bool blo = false;
- int frameCount = (markerType == MarkerType.ChArUcoBoard) ? allCorners.Count : imagePoints.Count;
- Imgproc.putText(bgrMat, frameCount + " FRAME CAPTURED", new Point(bgrMat.cols() - textLeft, 20), ff, fs, c, t, lt, blo);
- Imgproc.putText(bgrMat, "IMAGE_WIDTH: " + bgrMat.width(), new Point(bgrMat.cols() - textLeft, 40), ff, fs, c, t, lt, blo);
- Imgproc.putText(bgrMat, "IMAGE_HEIGHT: " + bgrMat.height(), new Point(bgrMat.cols() - textLeft, 60), ff, fs, c, t, lt, blo);
- Imgproc.putText(bgrMat, "CALIBRATION_FLAGS: " + calibrationFlags, new Point(bgrMat.cols() - textLeft, 80), ff, fs, c, t, lt, blo);
- Imgproc.putText(bgrMat, "CAMERA_MATRIX: ", new Point(bgrMat.cols() - 310, 100), ff, fs, c, t, lt, blo);
- for (int i = 0; i < camMatrixArr.Length; i = i + 3)
- {
- Imgproc.putText(bgrMat, " " + camMatrixArr[i] + ", " + camMatrixArr[i + 1] + ", " + camMatrixArr[i + 2] + ",", new Point(bgrMat.cols() - textLeft, 120 + 20 * i / 3), ff, fs, c, t, lt, blo);
- }
- Imgproc.putText(bgrMat, "DISTORTION_COEFFICIENTS: ", new Point(bgrMat.cols() - textLeft, 180), ff, fs, c, t, lt, blo);
- for (int i = 0; i < distCoeffsArr.Length; ++i)
- {
- Imgproc.putText(bgrMat, " " + distCoeffsArr[i] + ",", new Point(bgrMat.cols() - textLeft, 200 + 20 * i), ff, fs, c, t, lt, blo);
- }
- Imgproc.putText(bgrMat, "AVG_REPROJECTION_ERROR: " + repErr, new Point(bgrMat.cols() - textLeft, 300), ff, fs, c, t, lt, blo);
- if (frameCount == 0)
- Imgproc.putText(bgrMat, "Please press the capture button to start!", new Point(5, bgrMat.rows() - 10), Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(255, 255, 255, 255), 1, Imgproc.LINE_AA, false);
- }
- private double CaptureFrame(Mat frameMat)
- {
- double repErr = -1;
- switch (markerType)
- {
- default:
- case MarkerType.ChessBoard:
- case MarkerType.CirclesGlid:
- case MarkerType.AsymmetricCirclesGlid:
- MatOfPoint2f points = new MatOfPoint2f();
- Size patternSize = new Size((int)boardSizeW, (int)boardSizeH);
- bool found = false;
- switch (markerType)
- {
- default:
- case MarkerType.ChessBoard:
- if (useFindChessboardCornersSBMethod)
- {
- found = Calib3d.findChessboardCornersSB(frameMat, patternSize, points, findChessboardCornersSBFlags);
- }
- else
- {
- found = Calib3d.findChessboardCorners(frameMat, patternSize, points, findChessboardCornersFlags);
- }
- break;
- case MarkerType.CirclesGlid:
- found = Calib3d.findCirclesGrid(frameMat, patternSize, points, findCirclesGridFlags | Calib3d.CALIB_CB_SYMMETRIC_GRID);
- break;
- case MarkerType.AsymmetricCirclesGlid:
- found = Calib3d.findCirclesGrid(frameMat, patternSize, points, findCirclesGridFlags | Calib3d.CALIB_CB_ASYMMETRIC_GRID);
- break;
- }
- if (found)
- {
- if (markerType == MarkerType.ChessBoard && !useFindChessboardCornersSBMethod && enableCornerSubPix)
- {
- int winSize = 11;
- Imgproc.cornerSubPix(frameMat, points, new Size(winSize, winSize), new Size(-1, -1), new TermCriteria(TermCriteria.EPS + TermCriteria.COUNT, 30, 0.0001));
- }
- imagePoints.Add(points);
- allImgs.Add(frameMat);
- Debug.Log(imagePoints.Count + " Frame captured.");
- }
- else
- {
- Debug.Log("Invalid frame.");
- frameMat.Dispose();
- if (points != null)
- points.Dispose();
- return -1;
- }
- if (imagePoints.Count < 1)
- {
- Debug.Log("Not enough points for calibration.");
- repErr = -1;
- }
- else
- {
- MatOfPoint3f objectPoint = new MatOfPoint3f(new Mat(imagePoints[0].rows(), 1, CvType.CV_32FC3));
- CalcChessboardCorners(patternSize, squareSize, objectPoint, markerType);
- float grid_width = squareSize * ((int)patternSize.width - 1);
- bool release_object = false;
- if (useNewCalibrationMethod)
- {
- grid_width = gridWidth;
- release_object = true;
- }
- float[] tlPt = new float[3]; // top-left point
- objectPoint.get(0, 0, tlPt);
- float[] trPt = new float[3]; // top-right point
- objectPoint.get((int)patternSize.width - 1, 0, trPt);
- trPt[0] = tlPt[0] + grid_width;
- objectPoint.put((int)patternSize.width - 1, 0, trPt);
- Mat newObjPoints = objectPoint.clone();
- List<Mat> objectPoints = new List<Mat>();
- for (int i = 0; i < imagePoints.Count; ++i)
- {
- objectPoints.Add(objectPoint.clone());
- }
- int iFixedPoint = -1;
- if (release_object)
- iFixedPoint = (int)patternSize.width - 1;
- repErr = Calib3d.calibrateCameraRO(
- objectPoints,
- imagePoints,
- frameMat.size(),
- iFixedPoint,
- camMatrix,
- distCoeffs,
- rvecs,
- tvecs,
- newObjPoints,
- calibrationFlags
- );
- //if (release_object)
- //{
- // Debug.Log("New board corners: ");
- // Point3[] newPoints = new MatOfPoint3f(newObjPoints).toArray();
- // Debug.Log(newPoints[0]);
- // Debug.Log(newPoints[(int)patternSize.width - 1]);
- // Debug.Log(newPoints[(int)patternSize.width * ((int)patternSize.height - 1)]);
- // Debug.Log(newPoints[newPoints.Length - 1]);
- //}
- objectPoint.Dispose();
- }
- break;
- case MarkerType.ChArUcoBoard:
- /*
- List<Mat> corners = new List<Mat>();
- Mat ids = new Mat();
-
- arucoDetector.detectMarkers(frameMat, corners, ids, rejectedCorners);
- if (refineMarkerDetection)
- {
- // https://github.com/opencv/opencv/blob/377be68d923e40900ac5526242bcf221e3f355e5/modules/objdetect/src/aruco/charuco_detector.cpp#L310
- arucoDetector.refineDetectedMarkers(frameMat, charucoBoard, corners, ids, rejectedCorners);
- }
- if (ids.total() > 0)
- {
- allCorners.Add(corners);
- allIds.Add(ids);
- allImgs.Add(frameMat);
- Debug.Log(allCorners.Count + " Frame captured.");
- }
- else
- {
- Debug.Log("Invalid frame.");
- frameMat.Dispose();
- if (ids != null)
- ids.Dispose();
- foreach (var item in corners)
- {
- item.Dispose();
- }
- corners.Clear();
- return -1;
- }
- // calibrate camera using charuco boards
- repErr = CalibrateCameraCharuco(allCorners, allIds, charucoBoard, frameMat.size(), camMatrix, distCoeffs, rvecs, tvecs, calibrationFlags, calibrationFlags);
- */
- break;
- }
- Debug.Log("repErr: " + repErr);
- Debug.Log("camMatrix: " + camMatrix.dump());
- Debug.Log("distCoeffs: " + distCoeffs.dump());
- return repErr;
- }
- /*
- private double CalibrateCameraCharuco(List<List<Mat>> allCorners, List<Mat> allIds, CharucoBoard board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List<Mat> rvecs = null, List<Mat> tvecs = null, int calibrationFlags = 0, int minMarkers = 2)
- {
- // prepare data for charuco calibration
- int nFrames = allCorners.Count;
- List<Mat> allCharucoCorners = new List<Mat>();
- List<Mat> allCharucoIds = new List<Mat>();
- List<Mat> filteredImages = new List<Mat>();
- for (int i = 0; i < nFrames; ++i)
- {
- // interpolate using camera parameters
- Mat currentCharucoCorners = new Mat();
- Mat currentCharucoIds = new Mat();
- charucoDetector.detectBoard(allImgs[i], currentCharucoCorners, currentCharucoIds, allCorners[i], allIds[i]);
- //if (currentCharucoIds.total() > 0)
- if (currentCharucoIds.total() > 0 && currentCharucoCorners.total() == currentCharucoIds.total())
- {
- allCharucoCorners.Add(currentCharucoCorners);
- allCharucoIds.Add(currentCharucoIds);
- filteredImages.Add(allImgs[i]);
- }
- else
- {
- currentCharucoCorners.Dispose();
- currentCharucoIds.Dispose();
- }
- }
- if (allCharucoCorners.Count < 1)
- {
- Debug.Log("Not enough corners for calibration.");
- return -1;
- }
- if (rvecs == null)
- rvecs = new List<Mat>();
- if (tvecs == null)
- tvecs = new List<Mat>();
- return Aruco.calibrateCameraCharuco(allCharucoCorners, allCharucoIds, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, calibrationFlags); // error
- }
- */
- private void ResetCalibration()
- {
- foreach (var item in allImgs)
- {
- item.Dispose();
- }
- allImgs.Clear();
- repErr = 0;
- camMatrix = CreateCameraMatrix(bgrMat.width(), bgrMat.height());
- distCoeffs = new MatOfDouble(0, 0, 0, 0, 0);
- foreach (var item in imagePoints)
- {
- item.Dispose();
- }
- imagePoints.Clear();
- foreach (var corners in allCorners)
- {
- foreach (var item in corners)
- {
- item.Dispose();
- }
- }
- allCorners.Clear();
-
- foreach (var item in allIds)
- {
- item.Dispose();
- }
- allIds.Clear();
-
- }
- private Mat CreateCameraMatrix(float width, float height)
- {
- int max_d = (int)Mathf.Max(width, height);
- double fx = max_d;
- double fy = max_d;
- double cx = width / 2.0f;
- double cy = height / 2.0f;
- Mat camMatrix = new Mat(3, 3, CvType.CV_64FC1);
- camMatrix.put(0, 0, fx);
- camMatrix.put(0, 1, 0);
- camMatrix.put(0, 2, cx);
- camMatrix.put(1, 0, 0);
- camMatrix.put(1, 1, fy);
- camMatrix.put(1, 2, cy);
- camMatrix.put(2, 0, 0);
- camMatrix.put(2, 1, 0);
- camMatrix.put(2, 2, 1.0f);
- return camMatrix;
- }
- private void CalcChessboardCorners(Size patternSize, float squareSize, MatOfPoint3f corners, MarkerType markerType)
- {
- if ((int)(patternSize.width * patternSize.height) != corners.rows())
- {
- Debug.Log("Invalid corners size.");
- corners.create((int)(patternSize.width * patternSize.height), 1, CvType.CV_32FC3);
- }
- int width = (int)patternSize.width;
- int height = (int)patternSize.height;
- switch (markerType)
- {
- default:
- case MarkerType.ChessBoard:
- case MarkerType.CirclesGlid:
- for (int i = 0; i < height; ++i)
- {
- for (int j = 0; j < width; ++j)
- {
- corners.put(width * i + j, 0, new float[] { j * squareSize, i * squareSize, 0f });
- }
- }
- break;
- case MarkerType.AsymmetricCirclesGlid:
- for (int i = 0; i < height; ++i)
- {
- for (int j = 0; j < width; ++j)
- {
- corners.put(width * i + j, 0, new float[] { (2 * j + i % 2) * squareSize, i * squareSize, 0f });
- }
- }
- break;
- }
- }
- private bool InitializeImagesInputMode()
- {
- if (isInitialized)
- DisposeCalibraton();
- if (String.IsNullOrEmpty(calibrationImagesDirectory))
- {
- Debug.LogWarning("When using the images input mode, please set a calibration images directory path.");
- return false;
- }
- string dirPath = Path.Combine(Application.streamingAssetsPath, calibrationImagesDirectory);
- if (!Directory.Exists(dirPath))
- {
- Debug.LogWarning("The directory does not exist.");
- return false;
- }
- string[] imageFiles = GetImageFilesInDirectory(dirPath);
- if (imageFiles.Length < 1)
- {
- Debug.LogWarning("The image file does not exist.");
- return false;
- }
- Uri rootPath = new Uri(Application.streamingAssetsPath + System.IO.Path.AltDirectorySeparatorChar);
- Uri fullPath = new Uri(imageFiles[0]);
- string relativePath = rootPath.MakeRelativeUri(fullPath).ToString();
- using (Mat gray = Imgcodecs.imread(Utils.getFilePath(relativePath), Imgcodecs.IMREAD_GRAYSCALE))
- {
- if (gray.total() == 0)
- {
- Debug.LogWarning("Invalid image file.");
- return false;
- }
- using (Mat bgr = new Mat(gray.size(), CvType.CV_8UC3))
- using (Mat rgba = new Mat(gray.size(), CvType.CV_8UC4))
- {
- Imgproc.cvtColor(gray, rgba, Imgproc.COLOR_GRAY2RGBA);
- InitializeCalibraton(rgba);
- DrawFrame(gray, bgr);
- DrawCalibrationResult(bgr);
- Imgproc.cvtColor(bgr, rgba, Imgproc.COLOR_BGR2RGBA);
- Utils.matToTexture2D(rgba, texture);
- }
- }
- return true;
- }
- private IEnumerator CalibrateCameraUsingImages()
- {
- string dirPath = Path.Combine(Application.streamingAssetsPath, calibrationImagesDirectory);
- string[] imageFiles = GetImageFilesInDirectory(dirPath);
- if (imageFiles.Length < 1)
- yield break;
- isCalibrating = true;
- markerTypeDropdown.interactable = boardSizeWDropdown.interactable = boardSizeHDropdown.interactable = false;
- normalCalibrationOptionsGroup.gameObject.SetActive(false);
- arUcoCalibrationOptionsGroup.gameObject.SetActive(false);
- Uri rootPath = new Uri(Application.streamingAssetsPath + System.IO.Path.AltDirectorySeparatorChar);
- foreach (var path in imageFiles)
- {
- Uri fullPath = new Uri(path);
- string relativePath = rootPath.MakeRelativeUri(fullPath).ToString();
- using (Mat gray = Imgcodecs.imread(Utils.getFilePath(relativePath), Imgcodecs.IMREAD_GRAYSCALE))
- {
- if (gray.width() != bgrMat.width() || gray.height() != bgrMat.height())
- continue;
- Mat frameMat = gray.clone();
- double e = CaptureFrame(frameMat);
- if (e > 0)
- repErr = e;
- DrawFrame(gray, bgrMat);
- DrawCalibrationResult(bgrMat);
- Imgproc.cvtColor(bgrMat, rgbaMat, Imgproc.COLOR_BGR2RGBA);
- Utils.matToTexture2D(rgbaMat, texture);
- }
- yield return new WaitForSeconds(0.5f);
- }
- isCalibrating = false;
- markerTypeDropdown.interactable = boardSizeWDropdown.interactable = boardSizeHDropdown.interactable = true;
- bool arUcoCalibMode = markerType == MarkerType.ChArUcoBoard;
- normalCalibrationOptionsGroup.gameObject.SetActive(!arUcoCalibMode);
- arUcoCalibrationOptionsGroup.gameObject.SetActive(arUcoCalibMode);
- }
- private string[] GetImageFilesInDirectory(string dirPath)
- {
- if (Directory.Exists(dirPath))
- {
- string[] files = Directory.GetFiles(dirPath, "*.jpg");
- files = files.Concat(Directory.GetFiles(dirPath, "*.jpeg")).ToArray();
- files = files.Concat(Directory.GetFiles(dirPath, "*.png")).ToArray();
- files = files.Concat(Directory.GetFiles(dirPath, "*.tiff")).ToArray();
- files = files.Concat(Directory.GetFiles(dirPath, "*.tif")).ToArray();
- return files;
- }
- return new string[0];
- }
- /// <summary>
- /// Raises the destroy event.
- /// </summary>
- void OnDestroy()
- {
- if (isImagesInputMode)
- {
- DisposeCalibraton();
- }
- else
- {
- webCamTextureToMatHelper.Dispose();
- }
- Screen.orientation = ScreenOrientation.AutoRotation;
- Utils.setDebugMode(false);
- }
- /// <summary>
- /// Raises the back button click event.
- /// </summary>
- public void OnBackButtonClick()
- {
- SceneManager.LoadScene("OpenCVForUnityExample");
- }
- /// <summary>
- /// Raises the play button click event.
- /// </summary>
- public void OnPlayButtonClick()
- {
- if (isImagesInputMode)
- return;
- webCamTextureToMatHelper.Play();
- }
- /// <summary>
- /// Raises the pause button click event.
- /// </summary>
- public void OnPauseButtonClick()
- {
- if (isImagesInputMode)
- return;
- webCamTextureToMatHelper.Pause();
- }
- /// <summary>
- /// Raises the stop button click event.
- /// </summary>
- public void OnStopButtonClick()
- {
- if (isImagesInputMode)
- return;
- webCamTextureToMatHelper.Stop();
- }
- /// <summary>
- /// Raises the change camera button click event.
- /// </summary>
- public void OnChangeCameraButtonClick()
- {
- if (isImagesInputMode)
- return;
- webCamTextureToMatHelper.requestedIsFrontFacing = !webCamTextureToMatHelper.requestedIsFrontFacing;
- }
- /// <summary>
- /// Raises the marker type dropdown value changed event.
- /// </summary>
- public void OnMarkerTypeDropdownValueChanged(int result)
- {
- if ((int)markerType != result)
- {
- markerType = (MarkerType)result;
- bool arUcoCalibMode = markerType == MarkerType.ChArUcoBoard;
- normalCalibrationOptionsGroup.gameObject.SetActive(!arUcoCalibMode);
- arUcoCalibrationOptionsGroup.gameObject.SetActive(arUcoCalibMode);
- if (isImagesInputMode)
- {
- InitializeImagesInputMode();
- }
- else
- {
- if (webCamTextureToMatHelper.IsInitialized())
- webCamTextureToMatHelper.Initialize();
- }
- }
- }
- /// <summary>
- /// Raises the board size W dropdown value changed event.
- /// </summary>
- public void OnBoardSizeWDropdownValueChanged(int result)
- {
- if ((int)boardSizeW != result + 1)
- {
- boardSizeW = (NumberOfBoardSizeWidth)(result + 1);
- gridWidth = squareSize * ((int)boardSizeW - 1);
- gridWidthInputField.text = gridWidth.ToString();
- if (isImagesInputMode)
- {
- InitializeImagesInputMode();
- }
- else
- {
- if (webCamTextureToMatHelper.IsInitialized())
- webCamTextureToMatHelper.Initialize();
- }
- }
- }
- /// <summary>
- /// Raises the board size H dropdown value changed event.
- /// </summary>
- public void OnBoardSizeHDropdownValueChanged(int result)
- {
- if ((int)boardSizeH != result + 1)
- {
- boardSizeH = (NumberOfBoardSizeHeight)(result + 1);
- if (isImagesInputMode)
- {
- InitializeImagesInputMode();
- }
- else
- {
- if (webCamTextureToMatHelper.IsInitialized())
- webCamTextureToMatHelper.Initialize();
- }
- }
- }
- /// <summary>
- /// Raises the show undistort image toggle value changed event.
- /// </summary>
- public void OnShowUndistortImageToggleValueChanged()
- {
- if (showUndistortImage != showUndistortImageToggle.isOn)
- {
- showUndistortImage = showUndistortImageToggle.isOn;
- }
- }
- /// <summary>
- /// Raises the square size input field end edit event.
- /// </summary>
- public void OnSquareSizeInputFieldEndEdit()
- {
- float f;
- bool result = float.TryParse(squareSizeInputField.text, out f);
- if (result)
- {
- squareSize = f;
- squareSizeInputField.text = f.ToString();
- }
- else
- {
- squareSize = 1f;
- squareSizeInputField.text = squareSize.ToString();
- }
- }
- /// <summary>
- /// Raises the use new calibration method toggle value changed event.
- /// </summary>
- public void OnUseNewCalibrationMethodToggleValueChanged()
- {
- if (useNewCalibrationMethod != useNewCalibrationMethodToggle.isOn)
- {
- useNewCalibrationMethod = useNewCalibrationMethodToggle.isOn;
- }
- }
- /// <summary>
- /// Raises the grid width input field end edit event.
- /// </summary>
- public void OnGridWidthInputFieldEndEdit()
- {
- float f;
- bool result = float.TryParse(gridWidthInputField.text, out f);
- if (result)
- {
- gridWidth = f;
- gridWidthInputField.text = f.ToString();
- }
- else
- {
- gridWidth = squareSize * ((int)boardSizeW - 1);
- gridWidthInputField.text = gridWidth.ToString();
- }
- }
- /// <summary>
- /// Raises the dictionary id dropdown value changed event.
- /// </summary>
- public void OnDictionaryIdDropdownValueChanged(int result)
- {
- if ((int)dictionaryId != result)
- {
- dictionaryId = (ArUcoDictionary)result;
- dictionary = Objdetect.getPredefinedDictionary((int)dictionaryId);
- if (isImagesInputMode)
- {
- InitializeImagesInputMode();
- }
- else
- {
- if (webCamTextureToMatHelper.IsInitialized())
- webCamTextureToMatHelper.Initialize();
- }
- }
- }
- /// <summary>
- /// Raises the capture button click event.
- /// </summary>
- public void OnCaptureButtonClick()
- {
- if (isImagesInputMode)
- {
- if (!isCalibrating)
- InitializeImagesInputMode();
- StartCoroutine("CalibrateCameraUsingImages");
- }
- else
- {
- shouldCaptureFrame = true;
- }
- }
- /// <summary>
- /// Raises the reset button click event.
- /// </summary>
- public void OnResetButtonClick()
- {
- if (isImagesInputMode)
- {
- if (!isCalibrating)
- InitializeImagesInputMode();
- }
- else
- {
- ResetCalibration();
- }
- }
- /// <summary>
- /// Raises the save button click event.
- /// </summary>
- public void OnSaveButtonClick()
- {
- string saveDirectoryPath = Path.Combine(Application.persistentDataPath, "ArUcoCameraCalibrationExample");
- if (!Directory.Exists(saveDirectoryPath))
- {
- Directory.CreateDirectory(saveDirectoryPath);
- }
- string calibratonDirectoryName = "camera_parameters" + bgrMat.width() + "x" + bgrMat.height();
- string saveCalibratonFileDirectoryPath = Path.Combine(saveDirectoryPath, calibratonDirectoryName);
- // Clean up old files.
- if (Directory.Exists(saveCalibratonFileDirectoryPath))
- {
- DirectoryInfo directoryInfo = new DirectoryInfo(saveCalibratonFileDirectoryPath);
- foreach (FileInfo fileInfo in directoryInfo.GetFiles())
- {
- if ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
- {
- fileInfo.Attributes = FileAttributes.Normal;
- }
- }
- if ((directoryInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
- {
- directoryInfo.Attributes = FileAttributes.Directory;
- }
- directoryInfo.Delete(true);
- }
- Directory.CreateDirectory(saveCalibratonFileDirectoryPath);
- // save the calibraton file.
- string savePath = Path.Combine(saveCalibratonFileDirectoryPath, calibratonDirectoryName + ".xml");
- int frameCount = (markerType == MarkerType.ChArUcoBoard) ? allCorners.Count : imagePoints.Count;
- CameraParameters param = new CameraParameters(frameCount, bgrMat.width(), bgrMat.height(), calibrationFlags, camMatrix, distCoeffs, repErr);
- XmlSerializer serializer = new XmlSerializer(typeof(CameraParameters));
- using (var stream = new FileStream(savePath, FileMode.Create))
- {
- serializer.Serialize(stream, param);
- }
- // save the calibration images.
- #if UNITY_WEBGL && !UNITY_EDITOR
- string format = "jpg";
- MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 100);
- #else
- string format = "png";
- MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_PNG_COMPRESSION, 0);
- #endif
- for (int i = 0; i < allImgs.Count; ++i)
- {
- Imgcodecs.imwrite(Path.Combine(saveCalibratonFileDirectoryPath, calibratonDirectoryName + "_" + i.ToString("00") + "." + format), allImgs[i], compressionParams);
- }
- savePathInputField.text = savePath;
- Debug.Log("Saved the CameraParameters to disk in XML file format.");
- Debug.Log("savePath: " + savePath);
- }
- public enum MarkerType
- {
- ChessBoard,
- CirclesGlid,
- AsymmetricCirclesGlid,
- ChArUcoBoard,
- }
- public enum NumberOfBoardSizeWidth
- {
- W_1 = 1,
- W_2,
- W_3,
- W_4,
- W_5,
- W_6,
- W_7,
- W_8,
- W_9,
- W_10,
- W_11,
- W_12,
- W_13,
- W_14,
- W_15,
- }
- public enum NumberOfBoardSizeHeight
- {
- H_1 = 1,
- H_2,
- H_3,
- H_4,
- H_5,
- H_6,
- H_7,
- H_8,
- H_9,
- H_10,
- H_11,
- H_12,
- H_13,
- H_14,
- H_15,
- }
- public enum ArUcoDictionary
- {
- DICT_4X4_50 = Objdetect.DICT_4X4_50,
- DICT_4X4_100 = Objdetect.DICT_4X4_100,
- DICT_4X4_250 = Objdetect.DICT_4X4_250,
- DICT_4X4_1000 = Objdetect.DICT_4X4_1000,
- DICT_5X5_50 = Objdetect.DICT_5X5_50,
- DICT_5X5_100 = Objdetect.DICT_5X5_100,
- DICT_5X5_250 = Objdetect.DICT_5X5_250,
- DICT_5X5_1000 = Objdetect.DICT_5X5_1000,
- DICT_6X6_50 = Objdetect.DICT_6X6_50,
- DICT_6X6_100 = Objdetect.DICT_6X6_100,
- DICT_6X6_250 = Objdetect.DICT_6X6_250,
- DICT_6X6_1000 = Objdetect.DICT_6X6_1000,
- DICT_7X7_50 = Objdetect.DICT_7X7_50,
- DICT_7X7_100 = Objdetect.DICT_7X7_100,
- DICT_7X7_250 = Objdetect.DICT_7X7_250,
- DICT_7X7_1000 = Objdetect.DICT_7X7_1000,
- DICT_ARUCO_ORIGINAL = Objdetect.DICT_ARUCO_ORIGINAL,
- }
- }
- }
|