diff --git a/README.md b/README.md
index 556043437a..bd62fb6acd 100644
--- a/README.md
+++ b/README.md
@@ -82,3 +82,11 @@ Our meeting notes can be found in the wiki section of this repository.
* [2020 Meeting Notes](https://github.com/PhotonVision/photonvision/wiki/2020-Meeting-Notes)
* [2021 Meeting Notes](https://github.com/PhotonVision/photonvision/wiki/2021-Meeting-Notes)
+
+## Additional packages
+
+For now, using mrcal requires installing these additional packages on Linux systems:
+
+```
+sudo apt install libcholmod3 liblapack3 libsuitesparseconfig5
+```
diff --git a/build.gradle b/build.gradle
index f772c89e32..04860f7312 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,6 +11,7 @@ allprojects {
mavenCentral()
mavenLocal()
maven { url = "https://maven.photonvision.org/repository/internal/" }
+ maven { url = "https://maven.photonvision.org/repository/snapshots/" }
}
wpilibRepositories.addAllReleaseRepositories(it)
wpilibRepositories.addAllDevelopmentRepositories(it)
@@ -26,18 +27,21 @@ ext {
joglVersion = "2.4.0-rc-20200307"
javalinVersion = "5.6.2"
frcYear = "2024"
+ mrcalVersion = "dev-v2024.0.0-7-gc976aaa";
pubVersion = versionString
isDev = pubVersion.startsWith("dev")
// A list, for legacy reasons, with only the current platform contained
- String nativeName = wpilibTools.platformMapper.currentPlatform.platformName;
- if (nativeName == "linuxx64") nativeName = "linuxx86-64";
- if (nativeName == "winx64") nativeName = "windowsx86-64";
- if (nativeName == "macx64") nativeName = "osxx86-64";
- if (nativeName == "macarm64") nativeName = "osxarm64";
+ wpilibNativeName = wpilibTools.platformMapper.currentPlatform.platformName;
+ def nativeName = wpilibNativeName
+ if (wpilibNativeName == "linuxx64") nativeName = "linuxx86-64";
+ if (wpilibNativeName == "winx64") nativeName = "windowsx86-64";
+ if (wpilibNativeName == "macx64") nativeName = "osxx86-64";
+ if (wpilibNativeName == "macarm64") nativeName = "osxarm64";
jniPlatform = nativeName
- println("Building for platform: " + jniPlatform)
+
+ println("Building for platform " + jniPlatform + " wpilib: " + wpilibNativeName)
println("Using Wpilib: " + wpilibVersion)
println("Using OpenCV: " + openCVversion)
}
diff --git a/photon-core/build.gradle b/photon-core/build.gradle
index d5de014915..aea308cd47 100644
--- a/photon-core/build.gradle
+++ b/photon-core/build.gradle
@@ -13,6 +13,9 @@ dependencies {
implementation 'org.zeroturnaround:zt-zip:1.14'
implementation "org.xerial:sqlite-jdbc:3.41.0.0"
+
+ implementation "org.photonvision:photon-mrcal-java:$mrcalVersion"
+ implementation "org.photonvision:photon-mrcal-jni:$mrcalVersion:$wpilibNativeName"
}
task writeCurrentVersion {
diff --git a/photon-core/src/main/java/org/photonvision/common/hardware/Platform.java b/photon-core/src/main/java/org/photonvision/common/hardware/Platform.java
index 1c500ab722..00b55af584 100644
--- a/photon-core/src/main/java/org/photonvision/common/hardware/Platform.java
+++ b/photon-core/src/main/java/org/photonvision/common/hardware/Platform.java
@@ -17,6 +17,7 @@
package org.photonvision.common.hardware;
+import com.jogamp.common.os.Platform.OSType;
import edu.wpi.first.util.RuntimeDetector;
import java.io.BufferedReader;
import java.io.IOException;
@@ -27,23 +28,32 @@
@SuppressWarnings("unused")
public enum Platform {
// WPILib Supported (JNI)
- WINDOWS_64("Windows x64", false, OSType.WINDOWS, true),
- LINUX_32("Linux x86", false, OSType.LINUX, true),
- LINUX_64("Linux x64", false, OSType.LINUX, true),
+ WINDOWS_64("Windows x64", "winx64", false, OSType.WINDOWS, true),
+ LINUX_32("Linux x86", "linuxx64", false, OSType.LINUX, true),
+ LINUX_64("Linux x64", "linuxx64", false, OSType.LINUX, true),
LINUX_RASPBIAN32(
- "Linux Raspbian 32-bit", true, OSType.LINUX, true), // Raspberry Pi 3/4 with a 32-bit image
+ "Linux Raspbian 32-bit",
+ "linuxarm32",
+ true,
+ OSType.LINUX,
+ true), // Raspberry Pi 3/4 with a 32-bit image
LINUX_RASPBIAN64(
- "Linux Raspbian 64-bit", true, OSType.LINUX, true), // Raspberry Pi 3/4 with a 64-bit image
- LINUX_AARCH64("Linux AARCH64", false, OSType.LINUX, true), // Jetson Nano, Jetson TX2
+ "Linux Raspbian 64-bit",
+ "linuxarm64",
+ true,
+ OSType.LINUX,
+ true), // Raspberry Pi 3/4 with a 64-bit image
+ LINUX_AARCH64(
+ "Linux AARCH64", "linuxarm64", false, OSType.LINUX, true), // Jetson Nano, Jetson TX2
// PhotonVision Supported (Manual build/install)
- LINUX_ARM32("Linux ARM32", false, OSType.LINUX, true), // ODROID XU4, C1+
- LINUX_ARM64("Linux ARM64", false, OSType.LINUX, true), // ODROID C2, N2
+ LINUX_ARM32("Linux ARM32", "linuxarm32", false, OSType.LINUX, true), // ODROID XU4, C1+
+ LINUX_ARM64("Linux ARM64", "linuxarm64", false, OSType.LINUX, true), // ODROID C2, N2
// Completely unsupported
- WINDOWS_32("Windows x86", false, OSType.WINDOWS, false),
- MACOS("Mac OS", false, OSType.MACOS, false),
- UNKNOWN("Unsupported Platform", false, OSType.UNKNOWN, false);
+ WINDOWS_32("Windows x86", "windowsx64", false, OSType.WINDOWS, false),
+ MACOS("Mac OS", "osxuniversal", false, OSType.MACOS, false),
+ UNKNOWN("Unsupported Platform", "", false, OSType.UNKNOWN, false);
private enum OSType {
WINDOWS,
@@ -54,6 +64,7 @@ private enum OSType {
private static final ShellExec shell = new ShellExec(true, false);
public final String description;
+ public final String nativeLibraryFolderName;
public final boolean isPi;
public final OSType osType;
public final boolean isSupported;
@@ -62,11 +73,17 @@ private enum OSType {
private static final Platform currentPlatform = getCurrentPlatform();
private static final boolean isRoot = checkForRoot();
- Platform(String description, boolean isPi, OSType osType, boolean isSupported) {
+ Platform(
+ String description,
+ String nativeLibFolderName,
+ boolean isPi,
+ OSType osType,
+ boolean isSupported) {
this.description = description;
this.isPi = isPi;
this.osType = osType;
this.isSupported = isSupported;
+ this.nativeLibraryFolderName = nativeLibFolderName;
}
//////////////////////////////////////////////////////
@@ -89,6 +106,10 @@ public static String getPlatformName() {
}
}
+ public static final String getNativeLibraryFolderName() {
+ return currentPlatform.nativeLibraryFolderName;
+ }
+
public static boolean isRoot() {
return isRoot;
}
@@ -212,4 +233,9 @@ private static boolean fileHasText(String filename, String text) {
return false;
}
}
+
+ public static boolean isWindows() {
+ var p = getCurrentPlatform();
+ return (p == WINDOWS_32 || p == WINDOWS_64);
+ }
}
diff --git a/photon-core/src/main/java/org/photonvision/jni/PhotonJniCommon.java b/photon-core/src/main/java/org/photonvision/jni/PhotonJniCommon.java
new file mode 100644
index 0000000000..e099e422de
--- /dev/null
+++ b/photon-core/src/main/java/org/photonvision/jni/PhotonJniCommon.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 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.jni;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import org.photonvision.common.hardware.Platform;
+import org.photonvision.common.logging.LogGroup;
+import org.photonvision.common.logging.Logger;
+
+public abstract class PhotonJniCommon {
+ static boolean libraryLoaded = false;
+ protected static Logger logger = null;
+
+ protected static synchronized void forceLoad(Class> clazz, List libraries)
+ throws IOException {
+ if (libraryLoaded) return;
+ if (logger == null) logger = new Logger(clazz, LogGroup.Camera);
+
+ for (var libraryName : libraries) {
+ try {
+ // We always extract the shared object (we could hash each so, but that's a lot of work)
+ var arch_name = Platform.getNativeLibraryFolderName();
+ var nativeLibName = System.mapLibraryName(libraryName);
+ var in = clazz.getResourceAsStream("/nativelibraries/" + arch_name + "/" + nativeLibName);
+
+ if (in == null) {
+ libraryLoaded = false;
+ return;
+ }
+
+ // It's important that we don't mangle the names of these files on Windows at least
+ File temp = new File(System.getProperty("java.io.tmpdir"), nativeLibName);
+ FileOutputStream fos = new FileOutputStream(temp);
+
+ int read = -1;
+ byte[] buffer = new byte[1024];
+ while ((read = in.read(buffer)) != -1) {
+ fos.write(buffer, 0, read);
+ }
+ fos.close();
+ in.close();
+
+ System.load(temp.getAbsolutePath());
+
+ logger.info("Successfully loaded shared object " + temp.getName());
+
+ } catch (UnsatisfiedLinkError e) {
+ logger.error("Couldn't load shared object " + libraryName, e);
+ e.printStackTrace();
+ // logger.error(System.getProperty("java.library.path"));
+ break;
+ }
+ }
+ libraryLoaded = true;
+ }
+
+ protected static synchronized void forceLoad(Class> clazz, String libraryName)
+ throws IOException {
+ forceLoad(clazz, List.of(libraryName));
+ }
+
+ public static boolean isWorking() {
+ return libraryLoaded;
+ }
+}
diff --git a/photon-core/src/main/java/org/photonvision/mrcal/MrCal.java b/photon-core/src/main/java/org/photonvision/mrcal/MrCal.java
new file mode 100644
index 0000000000..5a61e621c3
--- /dev/null
+++ b/photon-core/src/main/java/org/photonvision/mrcal/MrCal.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 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.mrcal;
+
+import java.io.IOException;
+import java.util.List;
+import org.photonvision.common.hardware.Platform;
+import org.photonvision.common.util.TestUtils;
+import org.photonvision.jni.PhotonJniCommon;
+
+public class MrCal extends PhotonJniCommon {
+ public static synchronized void forceLoad() throws IOException {
+ // Force load opencv
+ TestUtils.loadLibraries();
+
+ // Library naming is dumb and has "lib" appended for Windows when it ought not to
+ if (Platform.isWindows()) {
+ // Order is correct to match dependencies of libraries
+ forceLoad(
+ MrCal.class,
+ List.of(
+ "libamd",
+ "libcamd",
+ "libcolamd",
+ "libccolamd",
+ "openblas",
+ "libgcc_s_seh-1",
+ "libgfortran-5",
+ "liblapack",
+ "libcholmod",
+ "mrcal_jni"));
+ } else {
+ // Nothing else to do on linux
+ forceLoad(MrCal.class, List.of("mrcal_jni"));
+ }
+
+ if (!MrCal.isWorking()) {
+ throw new IOException("Can't load mrcal?");
+ }
+ }
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ MrCal.forceLoad();
+ }
+}
diff --git a/photon-core/src/main/java/org/photonvision/vision/calibration/CameraCalibrationCoefficients.java b/photon-core/src/main/java/org/photonvision/vision/calibration/CameraCalibrationCoefficients.java
index 4b4ae5a8cc..71f6f2ff24 100644
--- a/photon-core/src/main/java/org/photonvision/vision/calibration/CameraCalibrationCoefficients.java
+++ b/photon-core/src/main/java/org/photonvision/vision/calibration/CameraCalibrationCoefficients.java
@@ -22,6 +22,7 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
+import java.util.Arrays;
import org.opencv.core.Mat;
import org.opencv.core.MatOfDouble;
import org.opencv.core.Size;
@@ -140,4 +141,23 @@ public static CameraCalibrationCoefficients parseFromCalibdbJson(JsonNode json)
return new CameraCalibrationCoefficients(
new Size(width, height), cam_jsonmat, distortion_jsonmat, new double[] {error}, 0);
}
+
+ @Override
+ public String toString() {
+ return "CameraCalibrationCoefficients [resolution="
+ + resolution
+ + ", cameraIntrinsics="
+ + cameraIntrinsics
+ + ", distCoeffs="
+ + distCoeffs
+ + ", perViewErrors="
+ + Arrays.toString(perViewErrors)
+ + ", standardDeviation="
+ + standardDeviation
+ + ", intrinsicsArr="
+ + Arrays.toString(intrinsicsArr)
+ + ", extrinsicsArr="
+ + Arrays.toString(extrinsicsArr)
+ + "]";
+ }
}
diff --git a/photon-core/src/main/java/org/photonvision/vision/calibration/JsonMat.java b/photon-core/src/main/java/org/photonvision/vision/calibration/JsonMat.java
index 15a6d0b9e0..7f0f61b27f 100644
--- a/photon-core/src/main/java/org/photonvision/vision/calibration/JsonMat.java
+++ b/photon-core/src/main/java/org/photonvision/vision/calibration/JsonMat.java
@@ -126,4 +126,23 @@ public Packet populatePacket(Packet packet) {
packet.encode(this.data);
return packet;
}
+
+ @Override
+ public String toString() {
+ return "JsonMat [rows="
+ + rows
+ + ", cols="
+ + cols
+ + ", type="
+ + type
+ + ", data="
+ + Arrays.toString(data)
+ + ", wrappedMat="
+ + wrappedMat
+ + ", wpilibMat="
+ + wpilibMat
+ + ", wrappedMatOfDouble="
+ + wrappedMatOfDouble
+ + "]";
+ }
}
diff --git a/photon-core/src/main/java/org/photonvision/vision/pipe/impl/Calibrate3dPipe.java b/photon-core/src/main/java/org/photonvision/vision/pipe/impl/Calibrate3dPipe.java
index bfca09d6fd..420829e331 100644
--- a/photon-core/src/main/java/org/photonvision/vision/pipe/impl/Calibrate3dPipe.java
+++ b/photon-core/src/main/java/org/photonvision/vision/pipe/impl/Calibrate3dPipe.java
@@ -20,15 +20,20 @@
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 java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Triple;
import org.opencv.calib3d.Calib3d;
+import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfDouble;
+import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Size;
import org.photonvision.common.logging.LogGroup;
import org.photonvision.common.logging.Logger;
+import org.photonvision.mrcal.MrCalJNI;
+import org.photonvision.mrcal.MrCalJNI.MrCalResult;
import org.photonvision.vision.calibration.CameraCalibrationCoefficients;
import org.photonvision.vision.calibration.JsonMat;
import org.photonvision.vision.pipe.CVPipe;
@@ -68,8 +73,51 @@ public class Calibrate3dPipe
* @param in Input for pipe processing. In the format (Input image, object points, image points)
* @return Result of processing.
*/
- @Override
protected CameraCalibrationCoefficients process(List> in) {
+ return process_mrcal(in);
+ }
+
+ protected CameraCalibrationCoefficients process_mrcal(List> in) {
+ List corner_locations =
+ in.stream().map(Triple::getRight).map(MatOfPoint2f::new).collect(Collectors.toList());
+
+ var start = System.nanoTime();
+ MrCalResult result = MrCalJNI.calibrateCamera(corner_locations, 7, 7, 0.0254, 640, 480, 1200);
+ var dt = System.nanoTime() - start;
+ System.out.printf("Calibrated in %f ms!\n", dt / 1e6);
+ System.out.printf("stats:\n" + result + "\n");
+
+ // intrinsics are fx fy cx cy from mrcal
+ JsonMat cameraMatrixMat =
+ new JsonMat(
+ 3,
+ 3,
+ CvType.CV_64FC1,
+ new double[] {
+ // fx 0 cx
+ result.intrinsics[0],
+ 0,
+ result.intrinsics[2],
+ // 0 fy cy
+ result.intrinsics[1],
+ 0,
+ result.intrinsics[3],
+ // 0 0 1
+ 0,
+ 0,
+ 1
+ });
+ JsonMat distortionCoefficientsMat =
+ new JsonMat(1, 8, CvType.CV_64FC1, Arrays.copyOfRange(result.intrinsics, 4, 12));
+
+ double[] perViewErrorsArray = new double[0];
+ double stdDev = 0;
+
+ return new CameraCalibrationCoefficients(
+ params.resolution, cameraMatrixMat, distortionCoefficientsMat, perViewErrorsArray, stdDev);
+ }
+
+ protected CameraCalibrationCoefficients process_opencv(List> in) {
in =
in.stream()
.filter(
diff --git a/photon-core/src/main/java/org/photonvision/vision/pipeline/Calibrate3dPipeline.java b/photon-core/src/main/java/org/photonvision/vision/pipeline/Calibrate3dPipeline.java
index e1a3bc8aae..3d8682b470 100644
--- a/photon-core/src/main/java/org/photonvision/vision/pipeline/Calibrate3dPipeline.java
+++ b/photon-core/src/main/java/org/photonvision/vision/pipeline/Calibrate3dPipeline.java
@@ -59,7 +59,7 @@ public class Calibrate3dPipeline
private boolean takeSnapshot = false;
// Output of the corners
- final List> foundCornersList;
+ public final List> foundCornersList;
/// Output of the calibration, getter method is set for this.
private CVPipeResult calibrationOutput;
diff --git a/photon-core/src/test/java/org/photonvision/mrcal/MrCalTest.java b/photon-core/src/test/java/org/photonvision/mrcal/MrCalTest.java
new file mode 100644
index 0000000000..6ecacec672
--- /dev/null
+++ b/photon-core/src/test/java/org/photonvision/mrcal/MrCalTest.java
@@ -0,0 +1,1315 @@
+/*
+ * Copyright (C) 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.mrcal;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import edu.wpi.first.math.util.Units;
+import java.io.File;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.tuple.Triple;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.opencv.core.MatOfPoint2f;
+import org.opencv.core.Size;
+import org.opencv.imgcodecs.Imgcodecs;
+import org.photonvision.common.util.TestUtils;
+import org.photonvision.vision.camera.QuirkyCamera;
+import org.photonvision.vision.frame.Frame;
+import org.photonvision.vision.frame.FrameDivisor;
+import org.photonvision.vision.frame.FrameStaticProperties;
+import org.photonvision.vision.frame.FrameThresholdType;
+import org.photonvision.vision.opencv.CVMat;
+import org.photonvision.vision.pipeline.Calibrate3dPipeTest;
+import org.photonvision.vision.pipeline.Calibrate3dPipeline;
+import org.photonvision.vision.pipeline.UICalibrationData;
+
+public class MrCalTest {
+ @BeforeAll
+ public static void load() {
+ assertDoesNotThrow(MrCal::forceLoad);
+ assertDoesNotThrow(TestUtils::loadLibraries);
+ }
+
+ @Test
+ public void smokeTest() {}
+
+ @Test
+ public void calibrateSquares640x480_pi() {
+ // Pi3 and V1.3 camera
+ String base = TestUtils.getSquaresBoardImagesPath().toAbsolutePath().toString();
+ File rootFolder = Path.of(base, "piCam", "640_480_1").toFile();
+ Size imgRes = new Size(640, 480);
+ Calibrate3dPipeTest.calibrateSquaresCommon(imgRes, rootFolder);
+ }
+
+ @Test
+ public void calibrateSquares640x480_pi_ld() {
+ // Pi3 and V1.3 camera
+ String base = TestUtils.getSquaresBoardImagesPath().toAbsolutePath().toString();
+ File rootFolder = Path.of(base, "piCam", "640_480_1").toFile();
+ Size imgRes = new Size(640, 480);
+ var boardGridSize_m = Units.inchesToMeters(1);
+ var boardDim = new Size(8, 8);
+
+ File[] directoryListing = rootFolder.listFiles();
+
+ assertTrue(directoryListing.length >= 10);
+
+ Calibrate3dPipeline calibration3dPipeline = new Calibrate3dPipeline(10);
+ calibration3dPipeline.getSettings().boardType = UICalibrationData.BoardType.CHESSBOARD;
+ calibration3dPipeline.getSettings().resolution = imgRes;
+ calibration3dPipeline.getSettings().boardHeight = (int) Math.round(boardDim.height);
+ calibration3dPipeline.getSettings().boardWidth = (int) Math.round(boardDim.width);
+ calibration3dPipeline.getSettings().gridSize = boardGridSize_m;
+ calibration3dPipeline.getSettings().streamingFrameDivisor = FrameDivisor.NONE;
+
+ for (var file : directoryListing) {
+ if (file.isFile()) {
+ calibration3dPipeline.takeSnapshot();
+ var frame =
+ new Frame(
+ new CVMat(Imgcodecs.imread(file.getAbsolutePath())),
+ new CVMat(),
+ FrameThresholdType.NONE,
+ new FrameStaticProperties((int) imgRes.width, (int) imgRes.height, 67, null));
+ var output = calibration3dPipeline.run(frame, QuirkyCamera.DefaultCamera);
+
+ // TestUtils.showImage(output.inputAndOutputFrame.processedImage.getMat(), file.getName(),
+ // 1);
+ output.release();
+ frame.release();
+ }
+ }
+
+ assertTrue(
+ calibration3dPipeline.foundCornersList.stream()
+ .map(Triple::getRight)
+ .allMatch(it -> it.width() > 0 && it.height() > 0));
+
+ // return Triple.of(inFrame.size(), objPts, outBoardCorners);
+ List corner_locations =
+ calibration3dPipeline.foundCornersList.stream()
+ .map(Triple::getRight)
+ .map(MatOfPoint2f::new)
+ .collect(Collectors.toList());
+
+ var start = System.nanoTime();
+ var result = MrCalJNI.calibrateCamera(corner_locations, 7, 7, 0.0254, 640, 480, 1200);
+ var dt = System.nanoTime() - start;
+ System.out.printf("Calibrated in %f ms!\n", dt / 1e6);
+ System.out.printf("stats:\n" + result + "\n");
+ }
+
+ @Test
+ public void calibrate_lifecam_640() {
+ // Order should be: observations[board idx, board width, board height] = (x, y, level)
+ // Not positive if I've switched width and height here, tho
+ double[] observations = {
+ 325.516,
+ 132.934,
+ 1.0,
+ 371.214,
+ 134.351,
+ 1.0,
+ 415.623,
+ 135.342,
+ 1.0,
+ 460.354,
+ 136.823,
+ 1.0,
+ 504.145,
+ 138.109,
+ 1.0,
+ 547.712,
+ 139.65,
+ 1.0,
+ 594.0,
+ 148.683,
+ 1.0,
+ 324.871,
+ 176.873,
+ 1.0,
+ 369.412,
+ 177.909,
+ 1.0,
+ 414.233,
+ 179.545,
+ 1.0,
+ 457.929,
+ 181.193,
+ 1.0,
+ 501.911,
+ 181.665,
+ 1.0,
+ 545.353,
+ 183.286,
+ 1.0,
+ 587.117,
+ 184.587,
+ 1.0,
+ 323.335,
+ 221.308,
+ 1.0,
+ 368.023,
+ 221.689,
+ 1.0,
+ 412.79,
+ 223.232,
+ 1.0,
+ 456.687,
+ 223.741,
+ 1.0,
+ 499.676,
+ 225.028,
+ 1.0,
+ 543.056,
+ 226.144,
+ 1.0,
+ 584.376,
+ 227.355,
+ 1.0,
+ 321.873,
+ 264.356,
+ 1.0,
+ 366.604,
+ 265.474,
+ 1.0,
+ 411.506,
+ 265.928,
+ 1.0,
+ 454.473,
+ 267.156,
+ 1.0,
+ 497.687,
+ 267.316,
+ 1.0,
+ 540.8,
+ 268.549,
+ 1.0,
+ 582.004,
+ 268.906,
+ 1.0,
+ 321.069,
+ 307.494,
+ 1.0,
+ 365.617,
+ 308.399,
+ 1.0,
+ 409.188,
+ 309.055,
+ 1.0,
+ 453.092,
+ 309.161,
+ 1.0,
+ 495.585,
+ 309.516,
+ 1.0,
+ 538.113,
+ 310.626,
+ 1.0,
+ 579.114,
+ 310.916,
+ 1.0,
+ 319.962,
+ 351.063,
+ 1.0,
+ 363.211,
+ 351.18,
+ 1.0,
+ 407.939,
+ 351.029,
+ 1.0,
+ 450.832,
+ 351.136,
+ 1.0,
+ 493.292,
+ 351.66,
+ 1.0,
+ 535.927,
+ 352.151,
+ 1.0,
+ 576.977,
+ 352.415,
+ 1.0,
+ 317.523,
+ 394.612,
+ 1.0,
+ 361.653,
+ 393.122,
+ 1.0,
+ 405.486,
+ 393.69,
+ 1.0,
+ 449.094,
+ 393.107,
+ 1.0,
+ 490.867,
+ 393.069,
+ 1.0,
+ 533.174,
+ 393.251,
+ 1.0,
+ 573.45,
+ 392.904,
+ 1.0,
+ 207.359,
+ 161.061,
+ 1.0,
+ 256.83,
+ 163.237,
+ 1.0,
+ 304.053,
+ 165.752,
+ 1.0,
+ 349.537,
+ 168.3,
+ 1.0,
+ 393.125,
+ 170.923,
+ 1.0,
+ 436.193,
+ 172.818,
+ 1.0,
+ 476.734,
+ 174.922,
+ 1.0,
+ 206.2,
+ 207.683,
+ 1.0,
+ 255.307,
+ 209.547,
+ 1.0,
+ 303.05,
+ 211.483,
+ 1.0,
+ 347.176,
+ 213.29,
+ 1.0,
+ 391.548,
+ 214.998,
+ 1.0,
+ 434.194,
+ 216.182,
+ 1.0,
+ 475.306,
+ 217.711,
+ 1.0,
+ 204.869,
+ 254.591,
+ 1.0,
+ 253.717,
+ 255.146,
+ 1.0,
+ 301.636,
+ 256.939,
+ 1.0,
+ 346.212,
+ 257.436,
+ 1.0,
+ 389.826,
+ 258.667,
+ 1.0,
+ 432.929,
+ 259.004,
+ 1.0,
+ 473.42,
+ 260.297,
+ 1.0,
+ 203.314,
+ 301.767,
+ 1.0,
+ 251.833,
+ 301.487,
+ 1.0,
+ 299.666,
+ 301.357,
+ 1.0,
+ 344.634,
+ 301.545,
+ 1.0,
+ 387.881,
+ 301.493,
+ 1.0,
+ 431.046,
+ 302.38,
+ 1.0,
+ 471.777,
+ 302.712,
+ 1.0,
+ 201.107,
+ 348.792,
+ 1.0,
+ 249.8,
+ 347.677,
+ 1.0,
+ 297.241,
+ 347.004,
+ 1.0,
+ 343.254,
+ 346.381,
+ 1.0,
+ 386.326,
+ 345.487,
+ 1.0,
+ 429.81,
+ 345.23,
+ 1.0,
+ 469.742,
+ 345.034,
+ 1.0,
+ 199.756,
+ 395.295,
+ 1.0,
+ 248.198,
+ 394.029,
+ 1.0,
+ 295.721,
+ 392.398,
+ 1.0,
+ 340.746,
+ 390.831,
+ 1.0,
+ 384.77,
+ 389.311,
+ 1.0,
+ 427.527,
+ 388.627,
+ 1.0,
+ 468.236,
+ 387.648,
+ 1.0,
+ 197.684,
+ 442.702,
+ 1.0,
+ 246.477,
+ 439.342,
+ 1.0,
+ 293.202,
+ 437.257,
+ 1.0,
+ 339.3,
+ 435.403,
+ 1.0,
+ 382.577,
+ 432.917,
+ 1.0,
+ 425.605,
+ 431.302,
+ 1.0,
+ 465.707,
+ 429.225,
+ 1.0,
+ 305.709,
+ 174.707,
+ 1.0,
+ 351.673,
+ 176.16,
+ 1.0,
+ 397.419,
+ 177.562,
+ 1.0,
+ 442.075,
+ 179.037,
+ 1.0,
+ 487.177,
+ 180.891,
+ 1.0,
+ 531.785,
+ 181.86,
+ 1.0,
+ 573.738,
+ 183.557,
+ 1.0,
+ 304.294,
+ 219.62,
+ 1.0,
+ 350.203,
+ 220.724,
+ 1.0,
+ 395.748,
+ 221.699,
+ 1.0,
+ 440.862,
+ 222.973,
+ 1.0,
+ 485.52,
+ 224.85,
+ 1.0,
+ 530.185,
+ 225.869,
+ 1.0,
+ 572.114,
+ 227.503,
+ 1.0,
+ 303.243,
+ 263.59,
+ 1.0,
+ 349.341,
+ 265.627,
+ 1.0,
+ 394.469,
+ 266.043,
+ 1.0,
+ 439.742,
+ 267.237,
+ 1.0,
+ 484.055,
+ 268.79,
+ 1.0,
+ 528.175,
+ 269.724,
+ 1.0,
+ 570.69,
+ 270.726,
+ 1.0,
+ 301.669,
+ 309.033,
+ 1.0,
+ 347.288,
+ 309.528,
+ 1.0,
+ 393.567,
+ 310.66,
+ 1.0,
+ 437.619,
+ 311.441,
+ 1.0,
+ 482.058,
+ 312.254,
+ 1.0,
+ 526.403,
+ 313.246,
+ 1.0,
+ 569.039,
+ 313.931,
+ 1.0,
+ 299.327,
+ 353.836,
+ 1.0,
+ 345.584,
+ 354.487,
+ 1.0,
+ 391.137,
+ 354.882,
+ 1.0,
+ 436.249,
+ 355.728,
+ 1.0,
+ 480.324,
+ 356.082,
+ 1.0,
+ 524.946,
+ 356.456,
+ 1.0,
+ 566.89,
+ 357.05,
+ 1.0,
+ 297.979,
+ 399.116,
+ 1.0,
+ 344.187,
+ 399.653,
+ 1.0,
+ 389.909,
+ 399.152,
+ 1.0,
+ 434.862,
+ 399.209,
+ 1.0,
+ 478.911,
+ 400.062,
+ 1.0,
+ 522.668,
+ 399.882,
+ 1.0,
+ 565.371,
+ 400.272,
+ 1.0,
+ 296.078,
+ 445.016,
+ 1.0,
+ 342.71,
+ 444.04,
+ 1.0,
+ 387.822,
+ 443.536,
+ 1.0,
+ 433.286,
+ 443.428,
+ 1.0,
+ 476.779,
+ 442.87,
+ 1.0,
+ 520.055,
+ 442.343,
+ 1.0,
+ 562.414,
+ 442.205,
+ 1.0,
+ 91.257764,
+ 62.341333,
+ 1.0,
+ 156.367723,
+ 66.97445,
+ 1.0,
+ 218.066065,
+ 71.650665,
+ 1.0,
+ 276.386861,
+ 76.251825,
+ 1.0,
+ 331.055492,
+ 81.147211,
+ 1.0,
+ 383.696897,
+ 84.814439,
+ 1.0,
+ 430.893194,
+ 89.012836,
+ 1.0,
+ 91.833674,
+ 123.430732,
+ 1.0,
+ 155.905789,
+ 126.34495,
+ 1.0,
+ 217.913026,
+ 129.702873,
+ 1.0,
+ 274.98218,
+ 133.31974,
+ 1.0,
+ 329.372274,
+ 135.975815,
+ 1.0,
+ 380.871511,
+ 138.540811,
+ 1.0,
+ 427.956504,
+ 141.086789,
+ 1.0,
+ 91.771236,
+ 183.897303,
+ 1.0,
+ 156.00571,
+ 185.474423,
+ 1.0,
+ 217.247203,
+ 187.258936,
+ 1.0,
+ 274.219614,
+ 188.919293,
+ 1.0,
+ 327.751591,
+ 189.691818,
+ 1.0,
+ 378.443874,
+ 191.387865,
+ 1.0,
+ 425.847568,
+ 191.85023,
+ 1.0,
+ 91.861943,
+ 243.611033,
+ 1.0,
+ 155.182405,
+ 243.511549,
+ 1.0,
+ 216.832614,
+ 243.122519,
+ 1.0,
+ 273.129283,
+ 242.355705,
+ 1.0,
+ 325.343307,
+ 241.717585,
+ 1.0,
+ 375.851167,
+ 241.553501,
+ 1.0,
+ 423.055064,
+ 241.803709,
+ 1.0,
+ 91.671178,
+ 302.440746,
+ 1.0,
+ 155.273091,
+ 300.177818,
+ 1.0,
+ 215.216509,
+ 297.399528,
+ 1.0,
+ 272.414663,
+ 294.579327,
+ 1.0,
+ 323.101889,
+ 292.983598,
+ 1.0,
+ 373.559284,
+ 291.323639,
+ 1.0,
+ 419.835057,
+ 290.277082,
+ 1.0,
+ 92.857058,
+ 359.214116,
+ 1.0,
+ 154.937554,
+ 355.849957,
+ 1.0,
+ 213.863967,
+ 351.613097,
+ 1.0,
+ 269.476977,
+ 347.721722,
+ 1.0,
+ 321.803464,
+ 344.059031,
+ 1.0,
+ 371.3437,
+ 341.393939,
+ 1.0,
+ 417.516845,
+ 338.833116,
+ 1.0,
+ 93.07796,
+ 415.613843,
+ 1.0,
+ 154.037428,
+ 409.923307,
+ 1.0,
+ 212.834834,
+ 404.066145,
+ 1.0,
+ 267.771666,
+ 398.70259,
+ 1.0,
+ 319.298246,
+ 393.980064,
+ 1.0,
+ 368.22885,
+ 389.593709,
+ 1.0,
+ 414.674171,
+ 385.356734,
+ 1.0,
+ 203.417,
+ 161.504,
+ 1.0,
+ 239.114,
+ 163.886,
+ 1.0,
+ 273.107,
+ 166.449,
+ 1.0,
+ 305.916,
+ 168.563,
+ 1.0,
+ 337.115,
+ 170.991,
+ 1.0,
+ 368.03,
+ 172.639,
+ 1.0,
+ 397.193,
+ 175.197,
+ 1.0,
+ 202.091,
+ 195.309,
+ 1.0,
+ 237.449,
+ 197.254,
+ 1.0,
+ 271.811,
+ 199.126,
+ 1.0,
+ 303.884,
+ 201.339,
+ 1.0,
+ 335.799,
+ 202.775,
+ 1.0,
+ 366.476,
+ 203.962,
+ 1.0,
+ 395.621,
+ 205.477,
+ 1.0,
+ 200.763,
+ 229.055,
+ 1.0,
+ 235.846,
+ 230.374,
+ 1.0,
+ 270.15,
+ 231.701,
+ 1.0,
+ 302.963,
+ 233.051,
+ 1.0,
+ 334.118,
+ 233.94,
+ 1.0,
+ 364.861,
+ 235.145,
+ 1.0,
+ 393.631,
+ 236.292,
+ 1.0,
+ 199.378,
+ 263.126,
+ 1.0,
+ 234.485,
+ 263.471,
+ 1.0,
+ 268.802,
+ 263.894,
+ 1.0,
+ 301.142,
+ 265.078,
+ 1.0,
+ 332.232,
+ 265.327,
+ 1.0,
+ 363.139,
+ 265.668,
+ 1.0,
+ 391.948,
+ 266.685,
+ 1.0,
+ 198.029,
+ 296.998,
+ 1.0,
+ 233.112,
+ 296.261,
+ 1.0,
+ 266.88,
+ 296.323,
+ 1.0,
+ 299.629,
+ 296.302,
+ 1.0,
+ 330.424,
+ 296.424,
+ 1.0,
+ 361.084,
+ 297.002,
+ 1.0,
+ 389.842,
+ 296.814,
+ 1.0,
+ 195.902,
+ 329.523,
+ 1.0,
+ 231.127,
+ 329.233,
+ 1.0,
+ 265.381,
+ 329.073,
+ 1.0,
+ 297.542,
+ 327.951,
+ 1.0,
+ 328.969,
+ 326.898,
+ 1.0,
+ 359.115,
+ 327.24,
+ 1.0,
+ 388.128,
+ 327.274,
+ 1.0,
+ 194.57,
+ 362.996,
+ 1.0,
+ 229.508,
+ 361.475,
+ 1.0,
+ 263.279,
+ 360.993,
+ 1.0,
+ 295.782,
+ 359.146,
+ 1.0,
+ 326.44,
+ 358.773,
+ 1.0,
+ 357.322,
+ 357.793,
+ 1.0,
+ 385.821,
+ 357.147,
+ 1.0,
+ 171.432587,
+ 62.91091,
+ 1.0,
+ 233.543966,
+ 66.989676,
+ 1.0,
+ 292.892198,
+ 71.025168,
+ 1.0,
+ 349.449118,
+ 75.488547,
+ 1.0,
+ 402.475665,
+ 78.823783,
+ 1.0,
+ 454.664044,
+ 82.293706,
+ 1.0,
+ 502.641518,
+ 85.776245,
+ 1.0,
+ 171.514734,
+ 121.993103,
+ 1.0,
+ 232.390154,
+ 125.308964,
+ 1.0,
+ 291.615192,
+ 128.775042,
+ 1.0,
+ 347.095808,
+ 131.455464,
+ 1.0,
+ 399.571916,
+ 133.920527,
+ 1.0,
+ 451.377575,
+ 136.702216,
+ 1.0,
+ 499.408046,
+ 139.005337,
+ 1.0,
+ 170.628776,
+ 181.228863,
+ 1.0,
+ 231.887269,
+ 183.495513,
+ 1.0,
+ 289.549706,
+ 184.943596,
+ 1.0,
+ 345.09963,
+ 186.724366,
+ 1.0,
+ 397.291107,
+ 187.669673,
+ 1.0,
+ 448.012251,
+ 188.937037,
+ 1.0,
+ 495.593336,
+ 189.964319,
+ 1.0,
+ 170.167998,
+ 238.958158,
+ 1.0,
+ 230.55839,
+ 239.418254,
+ 1.0,
+ 288.497209,
+ 239.644103,
+ 1.0,
+ 342.515469,
+ 239.491195,
+ 1.0,
+ 394.007115,
+ 239.553513,
+ 1.0,
+ 444.372561,
+ 240.019514,
+ 1.0,
+ 491.944262,
+ 240.14174,
+ 1.0,
+ 169.316729,
+ 295.157425,
+ 1.0,
+ 229.919699,
+ 293.84609,
+ 1.0,
+ 285.963235,
+ 292.93516,
+ 1.0,
+ 339.829832,
+ 291.170168,
+ 1.0,
+ 391.046096,
+ 291.017874,
+ 1.0,
+ 441.65549,
+ 290.262712,
+ 1.0,
+ 488.484545,
+ 289.606238,
+ 1.0,
+ 169.391253,
+ 351.146683,
+ 1.0,
+ 227.941254,
+ 348.429636,
+ 1.0,
+ 284.725293,
+ 345.328308,
+ 1.0,
+ 337.367128,
+ 343.36398,
+ 1.0,
+ 388.802075,
+ 341.231567,
+ 1.0,
+ 438.530539,
+ 340.104779,
+ 1.0,
+ 485.397165,
+ 338.584278,
+ 1.0,
+ 167.777378,
+ 405.478817,
+ 1.0,
+ 226.74825,
+ 401.012785,
+ 1.0,
+ 282.079972,
+ 397.14788,
+ 1.0,
+ 335.558834,
+ 393.843829,
+ 1.0,
+ 385.729546,
+ 390.894412,
+ 1.0,
+ 434.287148,
+ 387.675643,
+ 1.0,
+ 480.912754,
+ 385.395124,
+ 1.0,
+ 170.954619,
+ 66.207185,
+ 1.0,
+ 232.925674,
+ 70.329078,
+ 1.0,
+ 291.929905,
+ 74.309458,
+ 1.0,
+ 348.618405,
+ 78.647759,
+ 1.0,
+ 401.907159,
+ 82.127252,
+ 1.0,
+ 454.073162,
+ 85.908807,
+ 1.0,
+ 502.384304,
+ 89.612773,
+ 1.0,
+ 170.672483,
+ 125.415122,
+ 1.0,
+ 231.462866,
+ 128.773806,
+ 1.0,
+ 291.032499,
+ 132.398581,
+ 1.0,
+ 345.684337,
+ 134.915663,
+ 1.0,
+ 399.486674,
+ 137.530287,
+ 1.0,
+ 450.909032,
+ 139.320663,
+ 1.0,
+ 498.894327,
+ 142.166906,
+ 1.0,
+ 170.039566,
+ 184.623157,
+ 1.0,
+ 231.346178,
+ 186.659774,
+ 1.0,
+ 289.163911,
+ 188.055595,
+ 1.0,
+ 344.132387,
+ 189.912225,
+ 1.0,
+ 396.321555,
+ 191.204305,
+ 1.0,
+ 447.459807,
+ 192.313964,
+ 1.0,
+ 495.143206,
+ 193.384192,
+ 1.0,
+ 169.696611,
+ 241.964717,
+ 1.0,
+ 229.931254,
+ 242.875875,
+ 1.0,
+ 288.01937,
+ 243.058687,
+ 1.0,
+ 341.607179,
+ 243.256923,
+ 1.0,
+ 393.716058,
+ 243.405927,
+ 1.0,
+ 443.892988,
+ 243.204055,
+ 1.0,
+ 491.834639,
+ 243.220219,
+ 1.0,
+ 168.652822,
+ 299.444695,
+ 1.0,
+ 228.891661,
+ 297.586808,
+ 1.0,
+ 285.893939,
+ 296.780702,
+ 1.0,
+ 340.007199,
+ 294.868026,
+ 1.0,
+ 390.975809,
+ 294.235148,
+ 1.0,
+ 441.273511,
+ 293.692402,
+ 1.0,
+ 487.912647,
+ 293.046936,
+ 1.0,
+ 168.141104,
+ 354.722532,
+ 1.0,
+ 227.178901,
+ 352.045371,
+ 1.0,
+ 284.087214,
+ 349.40292,
+ 1.0,
+ 337.067904,
+ 346.926664,
+ 1.0,
+ 388.459654,
+ 345.137176,
+ 1.0,
+ 437.933373,
+ 343.278757,
+ 1.0,
+ 484.875402,
+ 342.18047,
+ 1.0,
+ 167.262818,
+ 409.231675,
+ 1.0,
+ 225.776135,
+ 404.722118,
+ 1.0,
+ 281.542602,
+ 401.181308,
+ 1.0,
+ 334.813427,
+ 397.384595,
+ 1.0,
+ 385.508089,
+ 394.555612,
+ 1.0,
+ 434.342519,
+ 391.542815,
+ 1.0,
+ 480.929907,
+ 388.713162,
+ 1.0,
+ 167.096579,
+ 75.563045,
+ 1.0,
+ 229.04439,
+ 79.769831,
+ 1.0,
+ 288.347806,
+ 83.685341,
+ 1.0,
+ 345.133847,
+ 87.745306,
+ 1.0,
+ 398.242697,
+ 91.371038,
+ 1.0,
+ 450.258727,
+ 94.791385,
+ 1.0,
+ 498.481567,
+ 98.006336,
+ 1.0,
+ 166.457718,
+ 134.764653,
+ 1.0,
+ 228.030388,
+ 137.434067,
+ 1.0,
+ 287.553592,
+ 141.303498,
+ 1.0,
+ 343.134211,
+ 143.527946,
+ 1.0,
+ 395.604435,
+ 146.123987,
+ 1.0,
+ 447.141897,
+ 148.657081,
+ 1.0,
+ 495.483977,
+ 150.93944,
+ 1.0,
+ 165.628349,
+ 193.670954,
+ 1.0,
+ 227.43617,
+ 195.5245,
+ 1.0,
+ 285.517103,
+ 197.434608,
+ 1.0,
+ 341.055025,
+ 198.983142,
+ 1.0,
+ 393.692971,
+ 199.687896,
+ 1.0,
+ 444.170013,
+ 200.967691,
+ 1.0,
+ 492.007105,
+ 201.736728,
+ 1.0,
+ 165.260826,
+ 251.970544,
+ 1.0,
+ 225.90027,
+ 251.973265,
+ 1.0,
+ 284.098946,
+ 252.060422,
+ 1.0,
+ 338.834414,
+ 251.78845,
+ 1.0,
+ 390.193044,
+ 251.929631,
+ 1.0,
+ 440.831715,
+ 251.885293,
+ 1.0,
+ 488.336721,
+ 252.191396,
+ 1.0,
+ 163.791281,
+ 309.386063,
+ 1.0,
+ 224.929397,
+ 307.232453,
+ 1.0,
+ 282.176961,
+ 305.725654,
+ 1.0,
+ 335.984449,
+ 304.607775,
+ 1.0,
+ 387.27907,
+ 303.196963,
+ 1.0,
+ 437.747368,
+ 302.540835,
+ 1.0,
+ 485.297854,
+ 301.494266,
+ 1.0,
+ 163.968029,
+ 365.050099,
+ 1.0,
+ 223.201096,
+ 362.148888,
+ 1.0,
+ 280.445895,
+ 359.3519,
+ 1.0,
+ 333.640557,
+ 356.491297,
+ 1.0,
+ 385.61138,
+ 354.094168,
+ 1.0,
+ 435.165143,
+ 352.729433,
+ 1.0,
+ 482.091338,
+ 350.966958,
+ 1.0,
+ 163.221401,
+ 419.674165,
+ 1.0,
+ 221.857647,
+ 415.074118,
+ 1.0,
+ 277.713041,
+ 411.798257,
+ 1.0,
+ 331.76678,
+ 407.068828,
+ 1.0,
+ 382.058162,
+ 404.138822,
+ 1.0,
+ 431.852815,
+ 401.145043,
+ 1.0,
+ 478.272757,
+ 398.091691,
+ 1.0
+ };
+
+ try {
+ var start = System.nanoTime();
+ var result = MrCalJNI.mrcal_calibrate_camera(observations, 7, 7, 0.0254, 640, 480, 1200);
+ var dt = System.nanoTime() - start;
+ System.out.printf("Calibrated in %f ms!\n", dt / 1e6);
+ System.out.printf("stats:\n" + result + "\n");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/photon-core/src/test/java/org/photonvision/vision/pipeline/Calibrate3dPipeTest.java b/photon-core/src/test/java/org/photonvision/vision/pipeline/Calibrate3dPipeTest.java
index 72547829f1..b3cbc1be5a 100644
--- a/photon-core/src/test/java/org/photonvision/vision/pipeline/Calibrate3dPipeTest.java
+++ b/photon-core/src/test/java/org/photonvision/vision/pipeline/Calibrate3dPipeTest.java
@@ -232,22 +232,22 @@ public void calibrateSquares_1920_1080_gloworm() {
calibrateSquaresCommon(sz, dir, boardDim, 1311, 540);
}
- public void calibrateSquaresCommon(Size imgRes, File rootFolder) {
+ public static void calibrateSquaresCommon(Size imgRes, File rootFolder) {
calibrateSquaresCommon(imgRes, rootFolder, new Size(8, 8));
}
- public void calibrateSquaresCommon(Size imgRes, File rootFolder, Size boardDim) {
+ public static void calibrateSquaresCommon(Size imgRes, File rootFolder, Size boardDim) {
calibrateSquaresCommon(
imgRes, rootFolder, boardDim, Units.inchesToMeters(1), imgRes.width / 2, imgRes.height / 2);
}
- public void calibrateSquaresCommon(
+ public static void calibrateSquaresCommon(
Size imgRes, File rootFolder, Size boardDim, double expectedXCenter, double expectedYCenter) {
calibrateSquaresCommon(
imgRes, rootFolder, boardDim, Units.inchesToMeters(1), expectedXCenter, expectedYCenter);
}
- public void calibrateSquaresCommon(
+ public static void calibrateSquaresCommon(
Size imgRes,
File rootFolder,
Size boardDim,
@@ -311,7 +311,7 @@ public void calibrateSquaresCommon(
assertTrue(centerYErrPct < 10.0);
System.out.println("Per View Errors: " + Arrays.toString(cal.perViewErrors));
- System.out.println("Camera Intrinsics: " + cal.cameraIntrinsics);
+ System.out.println("Camera Intrinsics: " + cal.cameraIntrinsics.toString());
System.out.println("Dist Coeffs: " + cal.distCoeffs.toString());
System.out.println("Standard Deviation: " + cal.standardDeviation);
System.out.println(
diff --git a/test-resources/calibrationSquaresImg/piCam/640_480_1/corners.vnl b/test-resources/calibrationSquaresImg/piCam/640_480_1/corners.vnl
new file mode 100644
index 0000000000..20703efa71
--- /dev/null
+++ b/test-resources/calibrationSquaresImg/piCam/640_480_1/corners.vnl
@@ -0,0 +1,411 @@
+## generated with mrgingham --jobs 4 --gridn 7 img10.jpg img11.jpg img12.jpg img13.jpg img14.jpg img15.jpg img16.jpg img17.jpg img18.jpg img19.jpg img1.jpg img20.jpg img21.jpg img22.jpg img23.jpg img24.jpg img25.jpg img2.jpg img3.jpg img4.jpg img5.jpg img6.jpg img7.jpg img8.jpg img9.jpg
+# filename x y level
+img10.jpg - - -
+img11.jpg - - -
+img15.jpg 305.709000 174.707000 0
+img15.jpg 351.673000 176.160000 0
+img15.jpg 397.419000 177.562000 0
+img15.jpg 442.075000 179.037000 0
+img15.jpg 487.177000 180.891000 0
+img15.jpg 531.785000 181.860000 0
+img15.jpg 573.738000 183.557000 0
+img15.jpg 304.294000 219.620000 0
+img15.jpg 350.203000 220.724000 0
+img15.jpg 395.748000 221.699000 0
+img15.jpg 440.862000 222.973000 0
+img15.jpg 485.520000 224.850000 0
+img15.jpg 530.185000 225.869000 0
+img15.jpg 572.114000 227.503000 0
+img15.jpg 303.243000 263.590000 0
+img15.jpg 349.341000 265.627000 0
+img15.jpg 394.469000 266.043000 0
+img15.jpg 439.742000 267.237000 0
+img15.jpg 484.055000 268.790000 0
+img15.jpg 528.175000 269.724000 0
+img15.jpg 570.690000 270.726000 0
+img15.jpg 301.669000 309.033000 0
+img15.jpg 347.288000 309.528000 0
+img15.jpg 393.567000 310.660000 0
+img15.jpg 437.619000 311.441000 0
+img15.jpg 482.058000 312.254000 0
+img15.jpg 526.403000 313.246000 0
+img15.jpg 569.039000 313.931000 0
+img15.jpg 299.327000 353.836000 0
+img15.jpg 345.584000 354.487000 0
+img15.jpg 391.137000 354.882000 0
+img15.jpg 436.249000 355.728000 0
+img15.jpg 480.324000 356.082000 0
+img15.jpg 524.946000 356.456000 0
+img15.jpg 566.890000 357.050000 0
+img15.jpg 297.979000 399.116000 0
+img15.jpg 344.187000 399.653000 0
+img15.jpg 389.909000 399.152000 0
+img15.jpg 434.862000 399.209000 0
+img15.jpg 478.911000 400.062000 0
+img15.jpg 522.668000 399.882000 0
+img15.jpg 565.371000 400.272000 0
+img15.jpg 296.078000 445.016000 0
+img15.jpg 342.710000 444.040000 0
+img15.jpg 387.822000 443.536000 0
+img15.jpg 433.286000 443.428000 0
+img15.jpg 476.779000 442.870000 0
+img15.jpg 520.055000 442.343000 0
+img15.jpg 562.414000 442.205000 0
+img14.jpg - - -
+img18.jpg 91.257764 62.341333 0
+img18.jpg 156.367723 66.974450 0
+img18.jpg 218.066065 71.650665 0
+img18.jpg 276.386861 76.251825 0
+img18.jpg 331.055492 81.147211 0
+img18.jpg 383.696897 84.814439 0
+img18.jpg 430.893194 89.012836 0
+img18.jpg 91.833674 123.430732 0
+img18.jpg 155.905789 126.344950 0
+img18.jpg 217.913026 129.702873 0
+img18.jpg 274.982180 133.319740 0
+img18.jpg 329.372274 135.975815 0
+img18.jpg 380.871511 138.540811 0
+img18.jpg 427.956504 141.086789 0
+img18.jpg 91.771236 183.897303 0
+img18.jpg 156.005710 185.474423 0
+img18.jpg 217.247203 187.258936 0
+img18.jpg 274.219614 188.919293 0
+img18.jpg 327.751591 189.691818 0
+img18.jpg 378.443874 191.387865 0
+img18.jpg 425.847568 191.850230 0
+img18.jpg 91.861943 243.611033 0
+img18.jpg 155.182405 243.511549 0
+img18.jpg 216.832614 243.122519 0
+img18.jpg 273.129283 242.355705 0
+img18.jpg 325.343307 241.717585 0
+img18.jpg 375.851167 241.553501 0
+img18.jpg 423.055064 241.803709 0
+img18.jpg 91.671178 302.440746 0
+img18.jpg 155.273091 300.177818 0
+img18.jpg 215.216509 297.399528 0
+img18.jpg 272.414663 294.579327 0
+img18.jpg 323.101889 292.983598 0
+img18.jpg 373.559284 291.323639 0
+img18.jpg 419.835057 290.277082 0
+img18.jpg 92.857058 359.214116 0
+img18.jpg 154.937554 355.849957 0
+img18.jpg 213.863967 351.613097 0
+img18.jpg 269.476977 347.721722 0
+img18.jpg 321.803464 344.059031 0
+img18.jpg 371.343700 341.393939 0
+img18.jpg 417.516845 338.833116 0
+img18.jpg 93.077960 415.613843 0
+img18.jpg 154.037428 409.923307 0
+img18.jpg 212.834834 404.066145 0
+img18.jpg 267.771666 398.702590 0
+img18.jpg 319.298246 393.980064 0
+img18.jpg 368.228850 389.593709 0
+img18.jpg 414.674171 385.356734 0
+img12.jpg - - -
+img13.jpg 207.359000 161.061000 0
+img13.jpg 256.830000 163.237000 0
+img13.jpg 304.053000 165.752000 0
+img13.jpg 349.537000 168.300000 0
+img13.jpg 393.125000 170.923000 0
+img13.jpg 436.193000 172.818000 0
+img13.jpg 476.734000 174.922000 0
+img13.jpg 206.200000 207.683000 0
+img13.jpg 255.307000 209.547000 0
+img13.jpg 303.050000 211.483000 0
+img13.jpg 347.176000 213.290000 0
+img13.jpg 391.548000 214.998000 0
+img13.jpg 434.194000 216.182000 0
+img13.jpg 475.306000 217.711000 0
+img13.jpg 204.869000 254.591000 0
+img13.jpg 253.717000 255.146000 0
+img13.jpg 301.636000 256.939000 0
+img13.jpg 346.212000 257.436000 0
+img13.jpg 389.826000 258.667000 0
+img13.jpg 432.929000 259.004000 0
+img13.jpg 473.420000 260.297000 0
+img13.jpg 203.314000 301.767000 0
+img13.jpg 251.833000 301.487000 0
+img13.jpg 299.666000 301.357000 0
+img13.jpg 344.634000 301.545000 0
+img13.jpg 387.881000 301.493000 0
+img13.jpg 431.046000 302.380000 0
+img13.jpg 471.777000 302.712000 0
+img13.jpg 201.107000 348.792000 0
+img13.jpg 249.800000 347.677000 0
+img13.jpg 297.241000 347.004000 0
+img13.jpg 343.254000 346.381000 0
+img13.jpg 386.326000 345.487000 0
+img13.jpg 429.810000 345.230000 0
+img13.jpg 469.742000 345.034000 0
+img13.jpg 199.756000 395.295000 0
+img13.jpg 248.198000 394.029000 0
+img13.jpg 295.721000 392.398000 0
+img13.jpg 340.746000 390.831000 0
+img13.jpg 384.770000 389.311000 0
+img13.jpg 427.527000 388.627000 0
+img13.jpg 468.236000 387.648000 0
+img13.jpg 197.684000 442.702000 0
+img13.jpg 246.477000 439.342000 0
+img13.jpg 293.202000 437.257000 0
+img13.jpg 339.300000 435.403000 0
+img13.jpg 382.577000 432.917000 0
+img13.jpg 425.605000 431.302000 0
+img13.jpg 465.707000 429.225000 0
+img19.jpg - - -
+img21.jpg 171.432587 62.910910 0
+img21.jpg 233.543966 66.989676 0
+img21.jpg 292.892198 71.025168 0
+img21.jpg 349.449118 75.488547 0
+img21.jpg 402.475665 78.823783 0
+img21.jpg 454.664044 82.293706 0
+img21.jpg 502.641518 85.776245 0
+img21.jpg 171.514734 121.993103 0
+img21.jpg 232.390154 125.308964 0
+img21.jpg 291.615192 128.775042 0
+img21.jpg 347.095808 131.455464 0
+img21.jpg 399.571916 133.920527 0
+img21.jpg 451.377575 136.702216 0
+img21.jpg 499.408046 139.005337 0
+img21.jpg 170.628776 181.228863 0
+img21.jpg 231.887269 183.495513 0
+img21.jpg 289.549706 184.943596 0
+img21.jpg 345.099630 186.724366 0
+img21.jpg 397.291107 187.669673 0
+img21.jpg 448.012251 188.937037 0
+img21.jpg 495.593336 189.964319 0
+img21.jpg 170.167998 238.958158 0
+img21.jpg 230.558390 239.418254 0
+img21.jpg 288.497209 239.644103 0
+img21.jpg 342.515469 239.491195 0
+img21.jpg 394.007115 239.553513 0
+img21.jpg 444.372561 240.019514 0
+img21.jpg 491.944262 240.141740 0
+img21.jpg 169.316729 295.157425 0
+img21.jpg 229.919699 293.846090 0
+img21.jpg 285.963235 292.935160 0
+img21.jpg 339.829832 291.170168 0
+img21.jpg 391.046096 291.017874 0
+img21.jpg 441.655490 290.262712 0
+img21.jpg 488.484545 289.606238 0
+img21.jpg 169.391253 351.146683 0
+img21.jpg 227.941254 348.429636 0
+img21.jpg 284.725293 345.328308 0
+img21.jpg 337.367128 343.363980 0
+img21.jpg 388.802075 341.231567 0
+img21.jpg 438.530539 340.104779 0
+img21.jpg 485.397165 338.584278 0
+img21.jpg 167.777378 405.478817 0
+img21.jpg 226.748250 401.012785 0
+img21.jpg 282.079972 397.147880 0
+img21.jpg 335.558834 393.843829 0
+img21.jpg 385.729546 390.894412 0
+img21.jpg 434.287148 387.675643 0
+img21.jpg 480.912754 385.395124 0
+img22.jpg 170.954619 66.207185 0
+img22.jpg 232.925674 70.329078 0
+img22.jpg 291.929905 74.309458 0
+img22.jpg 348.618405 78.647759 0
+img22.jpg 401.907159 82.127252 0
+img22.jpg 454.073162 85.908807 0
+img22.jpg 502.384304 89.612773 0
+img22.jpg 170.672483 125.415122 0
+img22.jpg 231.462866 128.773806 0
+img22.jpg 291.032499 132.398581 0
+img22.jpg 345.684337 134.915663 0
+img22.jpg 399.486674 137.530287 0
+img22.jpg 450.909032 139.320663 0
+img22.jpg 498.894327 142.166906 0
+img22.jpg 170.039566 184.623157 0
+img22.jpg 231.346178 186.659774 0
+img22.jpg 289.163911 188.055595 0
+img22.jpg 344.132387 189.912225 0
+img22.jpg 396.321555 191.204305 0
+img22.jpg 447.459807 192.313964 0
+img22.jpg 495.143206 193.384192 0
+img22.jpg 169.696611 241.964717 0
+img22.jpg 229.931254 242.875875 0
+img22.jpg 288.019370 243.058687 0
+img22.jpg 341.607179 243.256923 0
+img22.jpg 393.716058 243.405927 0
+img22.jpg 443.892988 243.204055 0
+img22.jpg 491.834639 243.220219 0
+img22.jpg 168.652822 299.444695 0
+img22.jpg 228.891661 297.586808 0
+img22.jpg 285.893939 296.780702 0
+img22.jpg 340.007199 294.868026 0
+img22.jpg 390.975809 294.235148 0
+img22.jpg 441.273511 293.692402 0
+img22.jpg 487.912647 293.046936 0
+img22.jpg 168.141104 354.722532 0
+img22.jpg 227.178901 352.045371 0
+img22.jpg 284.087214 349.402920 0
+img22.jpg 337.067904 346.926664 0
+img22.jpg 388.459654 345.137176 0
+img22.jpg 437.933373 343.278757 0
+img22.jpg 484.875402 342.180470 0
+img22.jpg 167.262818 409.231675 0
+img22.jpg 225.776135 404.722118 0
+img22.jpg 281.542602 401.181308 0
+img22.jpg 334.813427 397.384595 0
+img22.jpg 385.508089 394.555612 0
+img22.jpg 434.342519 391.542815 0
+img22.jpg 480.929907 388.713162 0
+img25.jpg - - -
+img2.jpg - - -
+img16.jpg - - -
+img17.jpg - - -
+img5.jpg - - -
+img6.jpg - - -
+img9.jpg - - -
+img1.jpg - - -
+img20.jpg 203.417000 161.504000 0
+img20.jpg 239.114000 163.886000 0
+img20.jpg 273.107000 166.449000 0
+img20.jpg 305.916000 168.563000 0
+img20.jpg 337.115000 170.991000 0
+img20.jpg 368.030000 172.639000 0
+img20.jpg 397.193000 175.197000 0
+img20.jpg 202.091000 195.309000 0
+img20.jpg 237.449000 197.254000 0
+img20.jpg 271.811000 199.126000 0
+img20.jpg 303.884000 201.339000 0
+img20.jpg 335.799000 202.775000 0
+img20.jpg 366.476000 203.962000 0
+img20.jpg 395.621000 205.477000 0
+img20.jpg 200.763000 229.055000 0
+img20.jpg 235.846000 230.374000 0
+img20.jpg 270.150000 231.701000 0
+img20.jpg 302.963000 233.051000 0
+img20.jpg 334.118000 233.940000 0
+img20.jpg 364.861000 235.145000 0
+img20.jpg 393.631000 236.292000 0
+img20.jpg 199.378000 263.126000 0
+img20.jpg 234.485000 263.471000 0
+img20.jpg 268.802000 263.894000 0
+img20.jpg 301.142000 265.078000 0
+img20.jpg 332.232000 265.327000 0
+img20.jpg 363.139000 265.668000 0
+img20.jpg 391.948000 266.685000 0
+img20.jpg 198.029000 296.998000 0
+img20.jpg 233.112000 296.261000 0
+img20.jpg 266.880000 296.323000 0
+img20.jpg 299.629000 296.302000 0
+img20.jpg 330.424000 296.424000 0
+img20.jpg 361.084000 297.002000 0
+img20.jpg 389.842000 296.814000 0
+img20.jpg 195.902000 329.523000 0
+img20.jpg 231.127000 329.233000 0
+img20.jpg 265.381000 329.073000 0
+img20.jpg 297.542000 327.951000 0
+img20.jpg 328.969000 326.898000 0
+img20.jpg 359.115000 327.240000 0
+img20.jpg 388.128000 327.274000 0
+img20.jpg 194.570000 362.996000 0
+img20.jpg 229.508000 361.475000 0
+img20.jpg 263.279000 360.993000 0
+img20.jpg 295.782000 359.146000 0
+img20.jpg 326.440000 358.773000 0
+img20.jpg 357.322000 357.793000 0
+img20.jpg 385.821000 357.147000 0
+img23.jpg 167.096579 75.563045 0
+img23.jpg 229.044390 79.769831 0
+img23.jpg 288.347806 83.685341 0
+img23.jpg 345.133847 87.745306 0
+img23.jpg 398.242697 91.371038 0
+img23.jpg 450.258727 94.791385 0
+img23.jpg 498.481567 98.006336 0
+img23.jpg 166.457718 134.764653 0
+img23.jpg 228.030388 137.434067 0
+img23.jpg 287.553592 141.303498 0
+img23.jpg 343.134211 143.527946 0
+img23.jpg 395.604435 146.123987 0
+img23.jpg 447.141897 148.657081 0
+img23.jpg 495.483977 150.939440 0
+img23.jpg 165.628349 193.670954 0
+img23.jpg 227.436170 195.524500 0
+img23.jpg 285.517103 197.434608 0
+img23.jpg 341.055025 198.983142 0
+img23.jpg 393.692971 199.687896 0
+img23.jpg 444.170013 200.967691 0
+img23.jpg 492.007105 201.736728 0
+img23.jpg 165.260826 251.970544 0
+img23.jpg 225.900270 251.973265 0
+img23.jpg 284.098946 252.060422 0
+img23.jpg 338.834414 251.788450 0
+img23.jpg 390.193044 251.929631 0
+img23.jpg 440.831715 251.885293 0
+img23.jpg 488.336721 252.191396 0
+img23.jpg 163.791281 309.386063 0
+img23.jpg 224.929397 307.232453 0
+img23.jpg 282.176961 305.725654 0
+img23.jpg 335.984449 304.607775 0
+img23.jpg 387.279070 303.196963 0
+img23.jpg 437.747368 302.540835 0
+img23.jpg 485.297854 301.494266 0
+img23.jpg 163.968029 365.050099 0
+img23.jpg 223.201096 362.148888 0
+img23.jpg 280.445895 359.351900 0
+img23.jpg 333.640557 356.491297 0
+img23.jpg 385.611380 354.094168 0
+img23.jpg 435.165143 352.729433 0
+img23.jpg 482.091338 350.966958 0
+img23.jpg 163.221401 419.674165 0
+img23.jpg 221.857647 415.074118 0
+img23.jpg 277.713041 411.798257 0
+img23.jpg 331.766780 407.068828 0
+img23.jpg 382.058162 404.138822 0
+img23.jpg 431.852815 401.145043 0
+img23.jpg 478.272757 398.091691 0
+img24.jpg - - -
+img3.jpg - - -
+img4.jpg 325.516000 132.934000 0
+img4.jpg 371.214000 134.351000 0
+img4.jpg 415.623000 135.342000 0
+img4.jpg 460.354000 136.823000 0
+img4.jpg 504.145000 138.109000 0
+img4.jpg 547.712000 139.650000 0
+img4.jpg 594.000000 148.683000 0
+img4.jpg 324.871000 176.873000 0
+img4.jpg 369.412000 177.909000 0
+img4.jpg 414.233000 179.545000 0
+img4.jpg 457.929000 181.193000 0
+img4.jpg 501.911000 181.665000 0
+img4.jpg 545.353000 183.286000 0
+img4.jpg 587.117000 184.587000 0
+img4.jpg 323.335000 221.308000 0
+img4.jpg 368.023000 221.689000 0
+img4.jpg 412.790000 223.232000 0
+img4.jpg 456.687000 223.741000 0
+img4.jpg 499.676000 225.028000 0
+img4.jpg 543.056000 226.144000 0
+img4.jpg 584.376000 227.355000 0
+img4.jpg 321.873000 264.356000 0
+img4.jpg 366.604000 265.474000 0
+img4.jpg 411.506000 265.928000 0
+img4.jpg 454.473000 267.156000 0
+img4.jpg 497.687000 267.316000 0
+img4.jpg 540.800000 268.549000 0
+img4.jpg 582.004000 268.906000 0
+img4.jpg 321.069000 307.494000 0
+img4.jpg 365.617000 308.399000 0
+img4.jpg 409.188000 309.055000 0
+img4.jpg 453.092000 309.161000 0
+img4.jpg 495.585000 309.516000 0
+img4.jpg 538.113000 310.626000 0
+img4.jpg 579.114000 310.916000 0
+img4.jpg 319.962000 351.063000 0
+img4.jpg 363.211000 351.180000 0
+img4.jpg 407.939000 351.029000 0
+img4.jpg 450.832000 351.136000 0
+img4.jpg 493.292000 351.660000 0
+img4.jpg 535.927000 352.151000 0
+img4.jpg 576.977000 352.415000 0
+img4.jpg 317.523000 394.612000 0
+img4.jpg 361.653000 393.122000 0
+img4.jpg 405.486000 393.690000 0
+img4.jpg 449.094000 393.107000 0
+img4.jpg 490.867000 393.069000 0
+img4.jpg 533.174000 393.251000 0
+img4.jpg 573.450000 392.904000 0
+img7.jpg - - -
+img8.jpg - - -
diff --git a/test-resources/calibrationSquaresImg/piCam/960_720_1/corners.vnl b/test-resources/calibrationSquaresImg/piCam/960_720_1/corners.vnl
new file mode 100644
index 0000000000..45e0187a61
--- /dev/null
+++ b/test-resources/calibrationSquaresImg/piCam/960_720_1/corners.vnl
@@ -0,0 +1,171 @@
+## generated with mrgingham --jobs 4 --gridn 7 img10.jpg img11.jpg img12.jpg img13.jpg img14.jpg img15.jpg img16.jpg img17.jpg img18.jpg img19.jpg img1.jpg img20.jpg img21.jpg img22.jpg img23.jpg img24.jpg img25.jpg img2.jpg img3.jpg img4.jpg img5.jpg img6.jpg img7.jpg img8.jpg img9.jpg
+# filename x y level
+img10.jpg - - -
+img12.jpg - - -
+img13.jpg - - -
+img11.jpg - - -
+img14.jpg - - -
+img16.jpg 230.852688 45.677636 0
+img16.jpg 290.588419 43.637631 0
+img16.jpg 353.551532 40.791532 0
+img16.jpg 416.562335 37.824245 0
+img16.jpg 482.521266 35.024665 0
+img16.jpg 550.680595 31.314791 0
+img16.jpg 620.486435 27.662542 0
+img16.jpg 228.101210 107.169967 0
+img16.jpg 287.668764 105.636131 0
+img16.jpg 350.608677 104.196417 0
+img16.jpg 413.726046 102.876996 0
+img16.jpg 479.587961 100.961492 0
+img16.jpg 548.288420 98.337218 0
+img16.jpg 617.491433 96.202379 0
+img16.jpg 227.317580 170.380526 0
+img16.jpg 286.573678 169.723367 0
+img16.jpg 348.871750 169.077797 0
+img16.jpg 412.298791 168.400691 0
+img16.jpg 476.736521 167.424006 0
+img16.jpg 545.646695 166.382103 0
+img16.jpg 615.060574 164.978558 0
+img16.jpg 224.988291 232.652880 0
+img16.jpg 284.444268 233.052725 0
+img16.jpg 347.369088 233.269971 0
+img16.jpg 410.603748 233.382944 0
+img16.jpg 474.877702 233.449657 0
+img16.jpg 542.719183 233.403859 0
+img16.jpg 612.559443 233.450298 0
+img16.jpg 224.176494 293.917407 0
+img16.jpg 283.560852 295.883657 0
+img16.jpg 344.909937 296.351158 0
+img16.jpg 407.748291 297.773360 0
+img16.jpg 473.420095 299.484169 0
+img16.jpg 540.155696 299.594645 0
+img16.jpg 610.001831 302.013660 0
+img16.jpg 222.765937 356.286965 0
+img16.jpg 281.624273 358.045270 0
+img16.jpg 344.401747 359.708573 0
+img16.jpg 407.178146 362.510875 0
+img16.jpg 470.802112 364.398990 0
+img16.jpg 538.976097 366.428889 0
+img16.jpg 608.179152 368.768331 0
+img16.jpg 221.298532 417.483438 0
+img16.jpg 280.640228 420.040118 0
+img16.jpg 341.602139 422.765487 0
+img16.jpg 404.672431 425.770751 0
+img16.jpg 470.190240 428.866733 0
+img16.jpg 536.654210 431.757569 0
+img16.jpg 605.530880 434.718486 0
+img17.jpg - - -
+img15.jpg - - -
+img18.jpg - - -
+img1.jpg - - -
+img20.jpg - - -
+img19.jpg - - -
+img21.jpg - - -
+img23.jpg - - -
+img22.jpg 94.983538 191.554631 0
+img22.jpg 153.614577 190.963557 0
+img22.jpg 214.504831 189.801771 0
+img22.jpg 275.163494 188.729227 0
+img22.jpg 335.692361 188.261850 0
+img22.jpg 398.653076 187.468366 0
+img22.jpg 461.538759 185.425839 0
+img22.jpg 90.898174 249.378532 0
+img22.jpg 149.890629 248.474019 0
+img22.jpg 212.238288 248.464675 0
+img22.jpg 272.692903 248.378072 0
+img22.jpg 335.315339 248.340460 0
+img22.jpg 397.425010 247.241587 0
+img22.jpg 460.113872 246.273172 0
+img22.jpg 88.271128 308.883542 0
+img22.jpg 148.111111 308.903030 0
+img22.jpg 209.528269 308.368223 0
+img22.jpg 272.122948 308.566463 0
+img22.jpg 333.255342 308.516094 0
+img22.jpg 396.217537 308.400373 0
+img22.jpg 458.998879 308.298711 0
+img22.jpg 85.549180 369.109836 0
+img22.jpg 145.604505 368.636110 0
+img22.jpg 207.843879 368.708637 0
+img22.jpg 269.426938 368.718688 0
+img22.jpg 332.511083 368.696887 0
+img22.jpg 395.694279 368.662189 0
+img22.jpg 458.724238 368.692204 0
+img22.jpg 83.324617 430.237009 0
+img22.jpg 143.464362 430.395213 0
+img22.jpg 205.934830 430.915077 0
+img22.jpg 268.120193 431.258451 0
+img22.jpg 331.145142 431.202329 0
+img22.jpg 395.505179 431.334136 0
+img22.jpg 458.594962 431.563843 0
+img22.jpg 80.427088 491.525255 0
+img22.jpg 140.407319 491.866495 0
+img22.jpg 203.493586 492.298204 0
+img22.jpg 266.502687 493.153395 0
+img22.jpg 329.540655 493.438226 0
+img22.jpg 394.060910 493.977069 0
+img22.jpg 458.576923 494.657254 0
+img22.jpg 78.230002 554.336896 0
+img22.jpg 138.799033 555.027797 0
+img22.jpg 201.690901 555.788772 0
+img22.jpg 265.045455 556.634769 0
+img22.jpg 329.438927 557.467018 0
+img22.jpg 392.902428 557.683931 0
+img22.jpg 458.234614 557.851508 0
+img24.jpg - - -
+img3.jpg 375.342835 136.998277 0
+img3.jpg 434.057516 131.808345 0
+img3.jpg 495.305888 126.738275 0
+img3.jpg 560.364821 120.983028 0
+img3.jpg 626.983524 114.899674 0
+img3.jpg 698.646341 108.293485 0
+img3.jpg 773.638004 101.614613 0
+img3.jpg 373.353018 197.423392 0
+img3.jpg 431.352319 193.725590 0
+img3.jpg 493.723975 189.762005 0
+img3.jpg 557.749077 185.410162 0
+img3.jpg 626.204480 181.344086 0
+img3.jpg 698.555333 176.339163 0
+img3.jpg 773.225717 171.736577 0
+img3.jpg 371.364100 257.700753 0
+img3.jpg 428.934194 255.808344 0
+img3.jpg 491.401929 254.033762 0
+img3.jpg 556.084802 251.522082 0
+img3.jpg 623.939787 248.292497 0
+img3.jpg 697.030951 245.615081 0
+img3.jpg 773.206566 242.407319 0
+img3.jpg 369.222475 319.052254 0
+img3.jpg 428.045774 317.745414 0
+img3.jpg 489.579236 317.512243 0
+img3.jpg 554.593832 317.152788 0
+img3.jpg 623.120840 315.677892 0
+img3.jpg 695.965810 314.573428 0
+img3.jpg 772.324664 314.552466 0
+img3.jpg 368.363534 380.504822 0
+img3.jpg 425.651057 380.679758 0
+img3.jpg 488.723907 381.062698 0
+img3.jpg 552.911222 382.782819 0
+img3.jpg 621.428571 383.677943 0
+img3.jpg 695.473001 383.910764 0
+img3.jpg 771.833725 385.933615 0
+img3.jpg 365.431290 441.297896 0
+img3.jpg 424.516816 443.794381 0
+img3.jpg 486.589463 446.591610 0
+img3.jpg 551.710297 449.411885 0
+img3.jpg 620.795019 452.041878 0
+img3.jpg 695.052279 455.202786 0
+img3.jpg 770.902807 457.918805 0
+img3.jpg 364.619850 504.218022 0
+img3.jpg 422.691676 508.208675 0
+img3.jpg 485.547412 512.388199 0
+img3.jpg 551.785073 516.002626 0
+img3.jpg 620.657118 521.103367 0
+img3.jpg 694.273407 525.069776 0
+img3.jpg 770.430863 529.703696 0
+img25.jpg - - -
+img2.jpg - - -
+img4.jpg - - -
+img7.jpg - - -
+img5.jpg - - -
+img6.jpg - - -
+img8.jpg - - -
+img9.jpg - - -