/// <summary> /// Add a pair of real space + image space points. /// Beware that calibration can fail if pattern is not rotated to fade forward, so that z is zero. /// Also ensure that the point order in the the two point sets are matching. /// </summary> /// <param name="patternRealModelSample">Must be measured in millimeters</param> /// <param name="patternImageSample"></param> public void AddSample(MatOfPoint3f patternRealModelSample, MatOfPoint2f patternImageSample) { //Debug.Log( "patternRealModelSample\n" + patternRealModelSample.dump() ); //Debug.Log( "patternImageSample\n" + patternImageSample.dump() ); _patternRealSamples.Add(patternRealModelSample.clone()); _patternImageSamples.Add(patternImageSample.clone()); }
// Update is called once per frame void Update() { if (webCamTextureToMatHelper.isPlaying() && webCamTextureToMatHelper.didUpdateThisFrame()) { Mat rgbaMat = webCamTextureToMatHelper.GetMat(); if (AppControl.control.calibrationComplete) { Mat rgbaMatUndistorted = rgbaMat.clone(); Size SizeCm = AppControl.control.cameraMatrix.size(); Size SizeDc = AppControl.control.distCoeffs.size(); Imgproc.undistort(rgbaMat, rgbaMatUndistorted, AppControl.control.cameraMatrix, AppControl.control.distCoeffs); rgbaMat = rgbaMatUndistorted; } Imgproc.cvtColor(rgbaMat, hsvMat, Imgproc.COLOR_RGBA2RGB); Imgproc.cvtColor(hsvMat, hsvMat, Imgproc.COLOR_RGB2HSV); // IMAGE PROCESSING STARTS (rgbaMat is the captured image) // Convert the current rgba frame (rgbaMat) to a gray image (grayMat) Imgproc.cvtColor(rgbaMat, grayMat, Imgproc.COLOR_RGBA2GRAY); //CALIB_CB_FAST_CHECK saves a lot of time on images //that do not contain any chessboard corners bool patternfound = Calib3d.findChessboardCorners(grayMat, patternsize, pointbuf, Calib3d.CALIB_CB_ADAPTIVE_THRESH + Calib3d.CALIB_CB_NORMALIZE_IMAGE + Calib3d.CALIB_CB_FAST_CHECK); if (patternfound) { Imgproc.cornerSubPix(grayMat, pointbuf, new Size(11, 11), new Size(-1, -1), new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 30, 0.1)); float timeNow = Time.realtimeSinceStartup; if ((timeNow > lastInterval + updateInterval)) { imagePoints.Add(pointbuf.clone()); calcChessboardCorners(patternsize, squaresize, objectpointbuf); objectPoints.Add(objectpointbuf.clone()); ++numCalibImages; lastInterval = timeNow; } } if (numCalibImages > numCalibrationTakes && !calibrationComplete) { // Do calibration int flags = 0; calibrationComplete = true; Calib3d.calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, flags); // Calibration is complete List <float> perViewErrors = new List <float>(); float error; error = computeReprojectionErrors(objectPoints, imagePoints, rvecs, tvecs, cameraMatrix, distCoeffs, perViewErrors); // Debug statements Debug.Log("Calibration complete!"); Debug.Log("Camera Matrix:"); Debug.Log(cameraMatrix.dump()); Debug.Log("Distortion Coefficients:"); Debug.Log(distCoeffs.dump()); // Debug.Log("fx: " + cameraMatrix.get(0,0)[0]); Debug.Log("Reprojection error average: " + error); // Error should be in units of pixels Debug.Log(perViewErrors.ToString()); // Save the calibration variables in AppControl AppControl.control.calibrationComplete = calibrationComplete; AppControl.control.cameraMatrix = cameraMatrix; AppControl.control.distCoeffs = distCoeffs; AppControl.control.reprojectionError = error; AppControl.control.fx = (float)cameraMatrix.get(0, 0)[0]; AppControl.control.fy = (float)cameraMatrix.get(1, 1)[0]; AppControl.control.cx = (float)cameraMatrix.get(0, 2)[0]; AppControl.control.cy = (float)cameraMatrix.get(1, 2)[0]; // Store the calibration parameters in player preferences text file PlayerPrefs.SetInt("Calibrated", 1); PlayerPrefs.SetFloat("Error", error); float k1 = (float)distCoeffs.get(0, 1)[0]; float k2 = (float)distCoeffs.get(0, 1)[0]; PlayerPrefs.SetFloat("k1", (float)distCoeffs.get(0, 0)[0]); PlayerPrefs.SetFloat("k2", (float)distCoeffs.get(0, 1)[0]); PlayerPrefs.SetFloat("p1", (float)distCoeffs.get(0, 2)[0]); PlayerPrefs.SetFloat("p2", (float)distCoeffs.get(0, 3)[0]); PlayerPrefs.SetFloat("k3", (float)distCoeffs.get(0, 4)[0]); PlayerPrefs.SetFloat("fx", (float)cameraMatrix.get(0, 0)[0]); PlayerPrefs.SetFloat("fy", (float)cameraMatrix.get(1, 1)[0]); PlayerPrefs.SetFloat("cx", (float)cameraMatrix.get(0, 2)[0]); PlayerPrefs.SetFloat("cy", (float)cameraMatrix.get(1, 2)[0]); } // SHOW IMAGE ON THE DISPLAY // Draw the chessboard corners so it's obvious that the app is working Calib3d.drawChessboardCorners(rgbaMat, patternsize, pointbuf, patternfound); // Notify the user when the calibration is finished if (!calibrationComplete) { Core.putText(rgbaMat, "Number of images collected: " + numCalibImages, new Point(5, rgbaMat.rows() - 10), Core.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(255, 255, 255, 255), 2, Core.LINE_AA, false); } else { // Mat rgbaMatUndistorted = new Mat(); Core.putText(rgbaMat, "Calibration complete", new Point(5, rgbaMat.rows() - 10), Core.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(255, 255, 255, 255), 2, Core.LINE_AA, false); } Utils.matToTexture2D(rgbaMat, texture); // Default display // Utils.matToTexture2D (rgbaMat, texture, colors) } }
/// <summary> /// Add a pair of real space + image space points. Points must be undistorted. /// </summary> /// <param name="patternRealSample">Must be measured in millimeters</param> /// <param name="patternImageSample"></param> public void AddSample(MatOfPoint3f patternWorldSample, MatOfPoint2f cameraPatternImageSample, MatOfPoint2f projectorPatternImageSample) { _patternWorldSamples.Add(patternWorldSample.clone()); _cameraPatternImageSamples.Add(cameraPatternImageSample.clone()); _projectorPatternImageSamples.Add(projectorPatternImageSample.clone()); }