diff --git a/photon-server/src/main/java/org/photonvision/common/util/TestUtils.java b/photon-server/src/main/java/org/photonvision/common/util/TestUtils.java
index 19c0bf973..bd5920758 100644
--- a/photon-server/src/main/java/org/photonvision/common/util/TestUtils.java
+++ b/photon-server/src/main/java/org/photonvision/common/util/TestUtils.java
@@ -161,6 +161,10 @@ public class TestUtils {
return getPowercellPath().resolve(image.path);
}
+ public static Path getDotBoardImagesPath() {
+ return getResourcesFolderPath().resolve("calibrationBoardImages");
+ }
+
public static void loadLibraries() {
try {
CameraServerCvJNI.forceLoad();
diff --git a/photon-server/src/main/java/org/photonvision/vision/calibration/CameraCalibrationCoefficients.java b/photon-server/src/main/java/org/photonvision/vision/calibration/CameraCalibrationCoefficients.java
index 628fc7788..8dd6b5b03 100644
--- a/photon-server/src/main/java/org/photonvision/vision/calibration/CameraCalibrationCoefficients.java
+++ b/photon-server/src/main/java/org/photonvision/vision/calibration/CameraCalibrationCoefficients.java
@@ -35,14 +35,19 @@ public class CameraCalibrationCoefficients implements Releasable {
@JsonProperty("cameraExtrinsics")
public final JsonMat cameraExtrinsics;
+ @JsonProperty("perViewErrors")
+ public final double[] perViewErrors;
+
@JsonCreator
public CameraCalibrationCoefficients(
@JsonProperty("resolution") Size resolution,
@JsonProperty("cameraIntrinsics") JsonMat cameraIntrinsics,
- @JsonProperty("cameraExtrinsics") JsonMat cameraExtrinsics) {
+ @JsonProperty("cameraExtrinsics") JsonMat cameraExtrinsics,
+ @JsonProperty("perViewErrors") double[] perViewErrors) {
this.resolution = resolution;
this.cameraIntrinsics = cameraIntrinsics;
this.cameraExtrinsics = cameraExtrinsics;
+ this.perViewErrors = perViewErrors;
}
@JsonIgnore
@@ -55,6 +60,11 @@ public class CameraCalibrationCoefficients implements Releasable {
return cameraExtrinsics.getAsMatOfDouble();
}
+ @JsonIgnore
+ public double[] getPerViewErrors() {
+ return perViewErrors;
+ }
+
@Override
public void release() {
cameraIntrinsics.release();
diff --git a/photon-server/src/main/java/org/photonvision/vision/pipe/impl/Calibrate3dPipe.java b/photon-server/src/main/java/org/photonvision/vision/pipe/impl/Calibrate3dPipe.java
new file mode 100644
index 000000000..b0f705e9c
--- /dev/null
+++ b/photon-server/src/main/java/org/photonvision/vision/pipe/impl/Calibrate3dPipe.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2020 Photon Vision.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.photonvision.vision.pipe.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.opencv.calib3d.Calib3d;
+import org.opencv.core.*;
+import org.photonvision.common.logging.LogGroup;
+import org.photonvision.common.logging.Logger;
+import org.photonvision.vision.calibration.CameraCalibrationCoefficients;
+import org.photonvision.vision.calibration.JsonMat;
+import org.photonvision.vision.pipe.CVPipe;
+
+public class Calibrate3dPipe
+ extends CVPipe<
+ List>, CameraCalibrationCoefficients, Calibrate3dPipe.CalibratePipeParams> {
+
+ // Camera matrix stores the center of the image and focal length across the x and y-axis in a 3x3
+ // matrix
+ private Mat cameraMatrix = new Mat();
+ // Stores the radical and tangential distortion in a 5x1 matrix
+ private MatOfDouble distortionCoefficients = new MatOfDouble();
+
+ // For loggging
+ private static final Logger logger = new Logger(Calibrate3dPipe.class, LogGroup.General);
+
+ // Translational and rotational matrices
+ private List rvecs = new ArrayList<>();
+ private List tvecs = new ArrayList<>();
+
+ // The Standard deviation of the estimated parameters
+ private Mat stdDeviationsIntrinsics = new Mat();
+ private Mat stdDeviationsExtrinsics = new Mat();
+
+ // Contains the re projection error of each snapshot by re projecting the corners we found and
+ // finding the euclidean distance between the actual corners.
+ private Mat perViewErrors = new Mat();
+
+ // RMS of the calibration
+ private double calibrationAccuracy;
+
+ /**
+ * Runs the process for the pipe.
+ *
+ * @param in Input for pipe processing.
+ * @return Result of processing.
+ */
+ @Override
+ protected CameraCalibrationCoefficients process(List> in) {
+ try {
+ // FindBoardCorners pipe outputs all the image points, object points, and frames to calculate
+ // imageSize from, other parameters are output Mats
+ calibrationAccuracy =
+ Calib3d.calibrateCameraExtended(
+ in.get(1),
+ in.get(2),
+ new Size(in.get(0).get(0).width(), in.get(0).get(0).height()),
+ cameraMatrix,
+ distortionCoefficients,
+ rvecs,
+ tvecs,
+ stdDeviationsIntrinsics,
+ stdDeviationsExtrinsics,
+ perViewErrors);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ JsonMat cameraMatrixMat = JsonMat.fromMat(cameraMatrix);
+ JsonMat distortionCoefficientsMat = JsonMat.fromMat(distortionCoefficients);
+ try {
+ // Print calibration successful
+ logger.info(
+ "CALIBRATION SUCCESS (with accuracy "
+ + calibrationAccuracy
+ + ")! camMatrix: \n"
+ + new ObjectMapper().writeValueAsString(cameraMatrixMat)
+ + "\ndistortionCoeffs:\n"
+ + new ObjectMapper().writeValueAsString(distortionCoefficientsMat)
+ + "\n");
+ } catch (JsonProcessingException e) {
+ logger.error(Arrays.toString(e.getStackTrace()));
+ }
+ // Create a new CameraCalibrationCoefficients object to pass onto SolvePnP
+ double[] perViewErrorsArray =
+ new double[(int) perViewErrors.total() * perViewErrors.channels()];
+ perViewErrors.get(0, 0, perViewErrorsArray);
+ return new CameraCalibrationCoefficients(
+ params.resolution, cameraMatrixMat, distortionCoefficientsMat, perViewErrorsArray);
+ }
+
+ public static class CalibratePipeParams {
+ // Only needs resolution to pass onto CameraCalibrationCoefficients object.
+ private final Size resolution;
+
+ public CalibratePipeParams(Size resolution) {
+ this.resolution = resolution;
+ }
+ }
+}
diff --git a/photon-server/src/main/java/org/photonvision/vision/pipe/impl/FindBoardCornersPipe.java b/photon-server/src/main/java/org/photonvision/vision/pipe/impl/FindBoardCornersPipe.java
new file mode 100644
index 000000000..e72c6b00a
--- /dev/null
+++ b/photon-server/src/main/java/org/photonvision/vision/pipe/impl/FindBoardCornersPipe.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2020 Photon Vision.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.photonvision.vision.pipe.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opencv.calib3d.Calib3d;
+import org.opencv.core.*;
+import org.opencv.imgproc.Imgproc;
+import org.photonvision.vision.pipe.CVPipe;
+
+public class FindBoardCornersPipe
+ extends CVPipe, List>, FindBoardCornersPipe.FindCornersPipeParams> {
+ MatOfPoint3f objectPoints = new MatOfPoint3f();
+ private List listOfObjectPoints = new ArrayList<>();
+ private List listOfImagePoints = new ArrayList<>();
+
+ Size imageSize;
+ Size patternSize;
+
+ private MatOfPoint2f boardCorners = new MatOfPoint2f();
+
+ // SubCornerPix params
+ private final Size windowSize = new Size(11, 11);
+ private final Size zeroZone = new Size(-1, -1);
+ private final TermCriteria criteria = new TermCriteria(3, 30, 0.001);
+
+ private boolean objectPointsCreated = false;
+
+ public void createObjectPoints() {
+ if (objectPointsCreated) return;
+
+ /*If using a chessboard, then the pattern size if the inner corners of the board. For example, the pattern size of a 9x9 chessboard would be 8x8
+ If using a dot board, then the pattern size width is the sum of the bottom 2 rows and the height is the left or right most column
+ For example, a 5x4 dot board would have a pattern size of 11x4
+ * */
+ this.patternSize = new Size(params.boardWidth, params.boardHeight);
+
+ // Chessboard and dot board have different 3D points to project as a dot board has alternating
+ // dots per column
+ if (params.isUsingChessboard) {
+ // Here we can create an NxN grid since a chessboard is rectangular
+ for (int i = 0; i < patternSize.height * patternSize.width; i++) {
+ objectPoints.push_back(
+ new MatOfPoint3f(
+ new Point3((double) i / patternSize.width, i % patternSize.width, 0.0f)));
+ }
+ } else {
+ // Here we need to alternate the amount of dots per column since a dot board is not
+ // rectangular and also by taking in account the grid size which should be in mm
+ for (int i = 0; i < patternSize.height; i++) {
+ for (int j = 0; j < patternSize.width; j++) {
+ objectPoints.push_back(
+ new MatOfPoint3f(
+ new Point3((2 * j + i % 2) * params.gridSize, i * params.gridSize, 0.0d)));
+ }
+ }
+ }
+ objectPointsCreated = true;
+ }
+
+ /**
+ * Runs the process for the pipe.
+ *
+ * @param in Input for pipe processing.
+ * @return All valid Mats for camera calibration
+ */
+ @Override
+ protected List> process(List in) {
+ // If we have less than 20 snapshots we need to return null
+ if (in.size() < 20) return null;
+ // Contains all valid Mats where a chessboard or dot board have been found
+ List outputMats = new ArrayList<>();
+
+ // Create the object points
+ createObjectPoints();
+
+ for (Mat board : in) {
+ if (findBoardCorners(board).getLeft()) {
+ outputMats.add(board);
+ }
+ }
+ // Contains the list of valid Mats, object points and images points where objectPoints.size() =
+ // imagePoints.size()
+ return List.of(outputMats, listOfObjectPoints, listOfImagePoints);
+ }
+
+ public Pair findBoardCorners(Mat frame) {
+ createObjectPoints();
+
+ // Convert the frame to grayscale to increase contrast
+ Imgproc.cvtColor(frame, frame, Imgproc.COLOR_BGR2GRAY);
+ boolean boardFound;
+
+ if (params.isUsingChessboard) {
+ // This is for chessboards
+ boardFound = Calib3d.findChessboardCorners(frame, patternSize, boardCorners);
+ } else {
+ // For dot boards
+ boardFound =
+ Calib3d.findCirclesGrid(
+ frame, patternSize, boardCorners, Calib3d.CALIB_CB_ASYMMETRIC_GRID);
+ }
+
+ if (!boardFound) {
+ // If we can't find a chessboard/dot board, convert the frame back to BGR and return false.
+ Imgproc.cvtColor(frame, frame, Imgproc.COLOR_GRAY2BGR);
+
+ return Pair.of(false, null);
+ }
+ // Get the size of the frame
+ this.imageSize = new Size(frame.width(), frame.height());
+
+ // Add the 3D points and the points of the corners found
+ this.listOfObjectPoints.add(objectPoints);
+ this.listOfImagePoints.add(boardCorners);
+
+ // Do sub corner pix for drawing chessboard
+ Imgproc.cornerSubPix(frame, boardCorners, windowSize, zeroZone, criteria);
+
+ // convert back to BGR
+ Imgproc.cvtColor(frame, frame, Imgproc.COLOR_GRAY2BGR);
+ // draw the chessboard, doesn't have to be different for a dot board since it just re projects
+ // the corners we found
+ Mat chessboardDrawn = new Mat();
+ frame.copyTo(chessboardDrawn);
+ Calib3d.drawChessboardCorners(chessboardDrawn, patternSize, boardCorners, true);
+ boardCorners = new MatOfPoint2f();
+ return Pair.of(true, chessboardDrawn);
+ }
+
+ public static class FindCornersPipeParams {
+
+ private final int boardHeight;
+ private final int boardWidth;
+ private final boolean isUsingChessboard;
+ private final double gridSize;
+
+ public FindCornersPipeParams(
+ int boardHeight, int boardWidth, boolean isUsingChessboard, double gridSize) {
+ this.boardHeight = boardHeight;
+ this.boardWidth = boardWidth;
+ this.isUsingChessboard = isUsingChessboard;
+ this.gridSize = gridSize; // mm
+ }
+ }
+}
diff --git a/photon-server/src/main/java/org/photonvision/vision/pipeline/Calibration3dPipeline.java b/photon-server/src/main/java/org/photonvision/vision/pipeline/Calibration3dPipeline.java
index d71595546..19f7f6373 100644
--- a/photon-server/src/main/java/org/photonvision/vision/pipeline/Calibration3dPipeline.java
+++ b/photon-server/src/main/java/org/photonvision/vision/pipeline/Calibration3dPipeline.java
@@ -17,26 +17,124 @@
package org.photonvision.vision.pipeline;
+import java.util.ArrayList;
+import java.util.List;
+import org.opencv.core.Mat;
+import org.photonvision.common.util.math.MathUtils;
+import org.photonvision.vision.calibration.CameraCalibrationCoefficients;
import org.photonvision.vision.frame.Frame;
import org.photonvision.vision.frame.FrameStaticProperties;
+import org.photonvision.vision.opencv.CVMat;
+import org.photonvision.vision.pipe.CVPipeResult;
+import org.photonvision.vision.pipe.impl.Calibrate3dPipe;
+import org.photonvision.vision.pipe.impl.FindBoardCornersPipe;
import org.photonvision.vision.pipeline.result.CVPipelineResult;
-import org.photonvision.vision.processes.PipelineManager;
-public class Calibration3dPipeline extends CVPipeline {
+public class Calibration3dPipeline
+ extends CVPipeline {
- // TODO: Everything here
+ // Only 2 pipes needed, one for finding the board corners and one for actually calibrating
+ private final FindBoardCornersPipe findBoardCornersPipe = new FindBoardCornersPipe();
+ private final Calibrate3dPipe calibrate3dPipe = new Calibrate3dPipe();
+
+ // Getter methods have been set for calibrate and takeSnapshot
+ private int numSnapshots = 0;
+ private boolean calibrate = false;
+ private boolean takeSnapshot = false;
+
+ // BoardSnapshots is a list of all valid snapshots taken
+ private ArrayList boardSnapshots;
+
+ // Output of the corners
+ private CVPipeResult>> findCornersPipeOutput;
+
+ /// Output of the calibration, getter method is set for this.
+ private CVPipeResult calibrationOutput;
public Calibration3dPipeline() {
- settings = new CVPipelineSettings();
- settings.pipelineIndex = PipelineManager.CAL_3D_INDEX;
+ this.settings = new Calibration3dPipelineSettings();
+ this.boardSnapshots = new ArrayList<>();
}
@Override
protected void setPipeParams(
- FrameStaticProperties frameStaticProperties, CVPipelineSettings settings) {}
+ FrameStaticProperties frameStaticProperties, Calibration3dPipelineSettings settings) {
+ FindBoardCornersPipe.FindCornersPipeParams findCornersPipeParams =
+ new FindBoardCornersPipe.FindCornersPipeParams(
+ settings.boardHeight,
+ settings.boardWidth,
+ settings.isUsingChessboard,
+ settings.gridSize);
+ findBoardCornersPipe.setParams(findCornersPipeParams);
+
+ Calibrate3dPipe.CalibratePipeParams calibratePipeParams =
+ new Calibrate3dPipe.CalibratePipeParams(settings.resolution);
+ calibrate3dPipe.setParams(calibratePipeParams);
+ }
@Override
- protected CVPipelineResult process(Frame frame, CVPipelineSettings settings) {
- return null;
+ protected CVPipelineResult process(Frame frame, Calibration3dPipelineSettings settings) {
+ // Set the pipe parameters
+ setPipeParams(frame.frameStaticProperties, settings);
+
+ long sumPipeNanosElapsed = 0L;
+
+ // hasEnough() is a getter method for numSnapshots that checks if there are more than 25
+ // snapshots
+ // calibrate will be true when it is get by it's putter method
+ if (hasEnough() && calibrate) {
+
+ /*Pass the board corners to the pipe, which will check again to see if all boards are valid
+ and returns the corresponding image and object points*/
+ findCornersPipeOutput = findBoardCornersPipe.apply(boardSnapshots);
+ // Increment the time it took to process all board pics to total elapsed time
+ sumPipeNanosElapsed += findCornersPipeOutput.nanosElapsed;
+
+ calibrationOutput = calibrate3dPipe.apply(findCornersPipeOutput.result);
+ sumPipeNanosElapsed += calibrationOutput.nanosElapsed;
+
+ calibrate = false;
+ numSnapshots = 0;
+ boardSnapshots.clear();
+
+ } else if (takeSnapshot) {
+ var hasBoard = findBoardCornersPipe.findBoardCorners(frame.image.getMat());
+ if (hasBoard.getLeft()) {
+ Mat board = new Mat();
+ frame.image.getMat().copyTo(board);
+ // See if mat is empty
+ boardSnapshots.add(board);
+
+ // Set snapshot to false and increment number of snapshots taken
+ takeSnapshot = false;
+ numSnapshots++;
+ return new CVPipelineResult(
+ MathUtils.nanosToMillis(sumPipeNanosElapsed),
+ null,
+ new Frame(new CVMat(hasBoard.getRight()), frame.frameStaticProperties));
+ }
+ }
+
+ return new CVPipelineResult(MathUtils.nanosToMillis(sumPipeNanosElapsed), null, frame);
+ }
+
+ public boolean hasEnough() {
+ return numSnapshots >= 25;
+ }
+
+ public void startCalibration() {
+ calibrate = true;
+ }
+
+ public void takeSnapshot() {
+ takeSnapshot = true;
+ }
+
+ public double[] perViewErrors() {
+ return calibrationOutput.result.perViewErrors;
+ }
+
+ public CameraCalibrationCoefficients cameraCalibrationCoefficients() {
+ return calibrationOutput.result;
}
}
diff --git a/photon-server/src/main/java/org/photonvision/vision/pipeline/Calibration3dPipelineSettings.java b/photon-server/src/main/java/org/photonvision/vision/pipeline/Calibration3dPipelineSettings.java
new file mode 100644
index 000000000..7feace93f
--- /dev/null
+++ b/photon-server/src/main/java/org/photonvision/vision/pipeline/Calibration3dPipelineSettings.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 Photon Vision.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.photonvision.vision.pipeline;
+
+import org.opencv.core.Size;
+
+public class Calibration3dPipelineSettings extends AdvancedPipelineSettings {
+ public int boardHeight = 0;
+ public int boardWidth = 0;
+ public boolean isUsingChessboard = true;
+ public double gridSize = 0;
+
+ public Size resolution = new Size(640, 480);
+}
diff --git a/photon-server/src/test/java/org/photonvision/vision/pipeline/Calibrate3dPipeTest.java b/photon-server/src/test/java/org/photonvision/vision/pipeline/Calibrate3dPipeTest.java
new file mode 100644
index 000000000..159f2d1bb
--- /dev/null
+++ b/photon-server/src/test/java/org/photonvision/vision/pipeline/Calibrate3dPipeTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 Photon Vision.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.photonvision.vision.pipeline;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opencv.core.Mat;
+import org.opencv.core.Size;
+import org.opencv.highgui.HighGui;
+import org.opencv.imgcodecs.Imgcodecs;
+import org.photonvision.common.util.TestUtils;
+import org.photonvision.vision.calibration.CameraCalibrationCoefficients;
+import org.photonvision.vision.frame.Frame;
+import org.photonvision.vision.frame.FrameStaticProperties;
+import org.photonvision.vision.opencv.CVMat;
+import org.photonvision.vision.pipe.CVPipeResult;
+import org.photonvision.vision.pipe.impl.Calibrate3dPipe;
+import org.photonvision.vision.pipe.impl.FindBoardCornersPipe;
+
+public class Calibrate3dPipeTest {
+ @BeforeEach
+ public void Init() {
+ TestUtils.loadLibraries();
+ }
+
+ @Test
+ public void perViewErrorsTest() {
+ List frames = new ArrayList<>();
+
+ File dir = new File(TestUtils.getDotBoardImagesPath().toAbsolutePath().toString());
+ File[] directoryListing = dir.listFiles();
+ for (var file : directoryListing) {
+ frames.add(Imgcodecs.imread(file.getAbsolutePath()));
+ }
+
+ FindBoardCornersPipe findBoardCornersPipe = new FindBoardCornersPipe();
+ findBoardCornersPipe.setParams(
+ new FindBoardCornersPipe.FindCornersPipeParams(11, 4, false, 15));
+ CVPipeResult>> findBoardCornersPipeOutput = findBoardCornersPipe.apply(frames);
+
+ Calibrate3dPipe calibrate3dPipe = new Calibrate3dPipe();
+ calibrate3dPipe.setParams(new Calibrate3dPipe.CalibratePipeParams(new Size(640, 480)));
+
+ CVPipeResult calibrate3dPipeOutput =
+ calibrate3dPipe.apply(findBoardCornersPipeOutput.result);
+ assertTrue(calibrate3dPipeOutput.result.perViewErrors.length > 0);
+ System.out.println(
+ "Per View Errors: " + Arrays.toString(calibrate3dPipeOutput.result.perViewErrors));
+ }
+
+ @Test
+ public void calibrationPipelineTest() {
+
+ File dir = new File(TestUtils.getDotBoardImagesPath().toAbsolutePath().toString());
+ File[] directoryListing = dir.listFiles();
+
+ Calibration3dPipeline calibration3dPipeline = new Calibration3dPipeline();
+ calibration3dPipeline.getSettings().boardHeight = 11;
+ calibration3dPipeline.getSettings().boardWidth = 4;
+ calibration3dPipeline.getSettings().isUsingChessboard = false;
+ calibration3dPipeline.getSettings().gridSize = 15;
+ calibration3dPipeline.getSettings().resolution = new Size(640, 480);
+
+ for (var file : directoryListing) {
+ calibration3dPipeline.takeSnapshot();
+ var output =
+ calibration3dPipeline.run(
+ new Frame(
+ new CVMat(Imgcodecs.imread(file.getAbsolutePath())),
+ new FrameStaticProperties(640, 480, 60)));
+ HighGui.imshow("Calibration Output Frame", output.outputFrame.image.getMat());
+ }
+
+ calibration3dPipeline.startCalibration();
+ calibration3dPipeline.run(
+ new Frame(
+ new CVMat(Imgcodecs.imread(directoryListing[0].getAbsolutePath())),
+ new FrameStaticProperties(640, 480, 60)));
+ System.out.println(
+ "Per View Errors: " + Arrays.toString(calibration3dPipeline.perViewErrors()));
+ System.out.println(
+ "Camera Intrinsics : "
+ + calibration3dPipeline.cameraCalibrationCoefficients().cameraIntrinsics.toString());
+ System.out.println(
+ "Camera Extrinsics : "
+ + calibration3dPipeline.cameraCalibrationCoefficients().cameraExtrinsics.toString());
+ }
+}
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_1.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_1.jpg
new file mode 100644
index 000000000..2f764f951
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_1.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_10.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_10.jpg
new file mode 100644
index 000000000..67600eab9
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_10.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_11.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_11.jpg
new file mode 100644
index 000000000..33818c2a0
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_11.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_12.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_12.jpg
new file mode 100644
index 000000000..f734032c2
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_12.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_13.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_13.jpg
new file mode 100644
index 000000000..f25c4c412
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_13.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_14.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_14.jpg
new file mode 100644
index 000000000..c3ed0f0a5
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_14.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_15.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_15.jpg
new file mode 100644
index 000000000..07a7e5545
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_15.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_16.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_16.jpg
new file mode 100644
index 000000000..bd116482a
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_16.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_17.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_17.jpg
new file mode 100644
index 000000000..db1314a56
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_17.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_18.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_18.jpg
new file mode 100644
index 000000000..9a4e3a8d8
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_18.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_19.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_19.jpg
new file mode 100644
index 000000000..6706d162b
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_19.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_2.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_2.jpg
new file mode 100644
index 000000000..06fa8772f
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_2.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_20.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_20.jpg
new file mode 100644
index 000000000..9d049d6d2
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_20.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_21.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_21.jpg
new file mode 100644
index 000000000..a894079ce
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_21.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_22.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_22.jpg
new file mode 100644
index 000000000..878cbdac7
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_22.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_23.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_23.jpg
new file mode 100644
index 000000000..0577aacb3
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_23.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_24.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_24.jpg
new file mode 100644
index 000000000..9581e84c3
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_24.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_25.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_25.jpg
new file mode 100644
index 000000000..14b00c5b4
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_25.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_26.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_26.jpg
new file mode 100644
index 000000000..cc4f6b886
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_26.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_3.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_3.jpg
new file mode 100644
index 000000000..60814f814
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_3.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_4.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_4.jpg
new file mode 100644
index 000000000..7f38b1040
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_4.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_5.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_5.jpg
new file mode 100644
index 000000000..fe59dcc9e
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_5.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_6.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_6.jpg
new file mode 100644
index 000000000..e1aae209b
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_6.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_8.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_8.jpg
new file mode 100644
index 000000000..0eb9452f5
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_8.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_9.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_9.jpg
new file mode 100644
index 000000000..86ce71f70
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_close_9.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_1.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_1.jpg
new file mode 100644
index 000000000..ed76c2c22
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_1.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_10.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_10.jpg
new file mode 100644
index 000000000..82f335bae
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_10.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_2.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_2.jpg
new file mode 100644
index 000000000..8434ad6a0
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_2.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_3.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_3.jpg
new file mode 100644
index 000000000..24d954547
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_3.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_4.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_4.jpg
new file mode 100644
index 000000000..35238eacd
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_4.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_5.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_5.jpg
new file mode 100644
index 000000000..da1b55574
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_5.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_6.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_6.jpg
new file mode 100644
index 000000000..f54341bda
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_6.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_7.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_7.jpg
new file mode 100644
index 000000000..d11248903
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_7.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_8.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_8.jpg
new file mode 100644
index 000000000..613cdada5
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_8.jpg differ
diff --git a/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_9.jpg b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_9.jpg
new file mode 100644
index 000000000..f0fcf2355
Binary files /dev/null and b/photon-server/src/test/resources/calibrationBoardImages/dotboard_far_9.jpg differ