mirror of
https://github.com/PhotonVision/photonvision
synced 2026-07-03 03:01:40 +00:00
Opencv cal: CALIB_USE_LU and use camera focal length guess (#1268)
This commit is contained in:
@@ -38,13 +38,26 @@ import org.photonvision.vision.calibration.CameraCalibrationCoefficients;
|
|||||||
import org.photonvision.vision.calibration.CameraLensModel;
|
import org.photonvision.vision.calibration.CameraLensModel;
|
||||||
import org.photonvision.vision.calibration.JsonImageMat;
|
import org.photonvision.vision.calibration.JsonImageMat;
|
||||||
import org.photonvision.vision.calibration.JsonMatOfDouble;
|
import org.photonvision.vision.calibration.JsonMatOfDouble;
|
||||||
|
import org.photonvision.vision.frame.FrameStaticProperties;
|
||||||
import org.photonvision.vision.pipe.CVPipe;
|
import org.photonvision.vision.pipe.CVPipe;
|
||||||
|
import org.photonvision.vision.pipe.impl.FindBoardCornersPipe.FindBoardCornersPipeResult;
|
||||||
|
|
||||||
public class Calibrate3dPipe
|
public class Calibrate3dPipe
|
||||||
extends CVPipe<
|
extends CVPipe<
|
||||||
List<FindBoardCornersPipe.FindBoardCornersPipeResult>,
|
Calibrate3dPipe.CalibrationInput,
|
||||||
CameraCalibrationCoefficients,
|
CameraCalibrationCoefficients,
|
||||||
Calibrate3dPipe.CalibratePipeParams> {
|
Calibrate3dPipe.CalibratePipeParams> {
|
||||||
|
public static class CalibrationInput {
|
||||||
|
final List<FindBoardCornersPipe.FindBoardCornersPipeResult> observations;
|
||||||
|
final FrameStaticProperties imageProps;
|
||||||
|
|
||||||
|
public CalibrationInput(
|
||||||
|
List<FindBoardCornersPipeResult> observations, FrameStaticProperties imageProps) {
|
||||||
|
this.observations = observations;
|
||||||
|
this.imageProps = imageProps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For logging
|
// For logging
|
||||||
private static final Logger logger = new Logger(Calibrate3dPipe.class, LogGroup.General);
|
private static final Logger logger = new Logger(Calibrate3dPipe.class, LogGroup.General);
|
||||||
|
|
||||||
@@ -63,10 +76,9 @@ public class Calibrate3dPipe
|
|||||||
* @return Result of processing.
|
* @return Result of processing.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected CameraCalibrationCoefficients process(
|
protected CameraCalibrationCoefficients process(CalibrationInput in) {
|
||||||
List<FindBoardCornersPipe.FindBoardCornersPipeResult> in) {
|
var filteredIn =
|
||||||
in =
|
in.observations.stream()
|
||||||
in.stream()
|
|
||||||
.filter(
|
.filter(
|
||||||
it ->
|
it ->
|
||||||
it != null
|
it != null
|
||||||
@@ -79,17 +91,21 @@ public class Calibrate3dPipe
|
|||||||
var start = System.nanoTime();
|
var start = System.nanoTime();
|
||||||
if (MrCalJNILoader.getInstance().isLoaded() && params.useMrCal) {
|
if (MrCalJNILoader.getInstance().isLoaded() && params.useMrCal) {
|
||||||
logger.debug("Calibrating with mrcal!");
|
logger.debug("Calibrating with mrcal!");
|
||||||
ret = calibrateMrcal(in);
|
ret =
|
||||||
|
calibrateMrcal(
|
||||||
|
filteredIn, in.imageProps.horizontalFocalLength, in.imageProps.verticalFocalLength);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Calibrating with opencv!");
|
logger.debug("Calibrating with opencv!");
|
||||||
ret = calibrateOpenCV(in);
|
ret =
|
||||||
|
calibrateOpenCV(
|
||||||
|
filteredIn, in.imageProps.horizontalFocalLength, in.imageProps.verticalFocalLength);
|
||||||
}
|
}
|
||||||
var dt = System.nanoTime() - start;
|
var dt = System.nanoTime() - start;
|
||||||
|
|
||||||
if (ret != null)
|
if (ret != null)
|
||||||
logger.info(
|
logger.info(
|
||||||
"CALIBRATION SUCCESS for res "
|
"CALIBRATION SUCCESS for res "
|
||||||
+ in.get(0).size
|
+ in.observations.get(0).size
|
||||||
+ " in "
|
+ " in "
|
||||||
+ dt / 1e6
|
+ dt / 1e6
|
||||||
+ "ms! camMatrix: \n"
|
+ "ms! camMatrix: \n"
|
||||||
@@ -103,7 +119,7 @@ public class Calibrate3dPipe
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected CameraCalibrationCoefficients calibrateOpenCV(
|
protected CameraCalibrationCoefficients calibrateOpenCV(
|
||||||
List<FindBoardCornersPipe.FindBoardCornersPipeResult> in) {
|
List<FindBoardCornersPipe.FindBoardCornersPipeResult> in, double fxGuess, double fyGuess) {
|
||||||
List<Mat> objPoints = in.stream().map(it -> it.objectPoints).collect(Collectors.toList());
|
List<Mat> objPoints = in.stream().map(it -> it.objectPoints).collect(Collectors.toList());
|
||||||
List<Mat> imgPts = in.stream().map(it -> it.imagePoints).collect(Collectors.toList());
|
List<Mat> imgPts = in.stream().map(it -> it.imagePoints).collect(Collectors.toList());
|
||||||
if (objPoints.size() != imgPts.size()) {
|
if (objPoints.size() != imgPts.size()) {
|
||||||
@@ -111,30 +127,32 @@ public class Calibrate3dPipe
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat cameraMatrix = new Mat();
|
Mat cameraMatrix = new Mat(3, 3, CvType.CV_64F);
|
||||||
MatOfDouble distortionCoefficients = new MatOfDouble();
|
MatOfDouble distortionCoefficients = new MatOfDouble();
|
||||||
List<Mat> rvecs = new ArrayList<>();
|
List<Mat> rvecs = new ArrayList<>();
|
||||||
List<Mat> tvecs = new ArrayList<>();
|
List<Mat> tvecs = new ArrayList<>();
|
||||||
|
|
||||||
// RMS of the calibration
|
// initial camera matrix guess
|
||||||
double calibrationAccuracy;
|
double cx = (in.get(0).size.width / 2.0) - 0.5;
|
||||||
|
double cy = (in.get(0).size.width / 2.0) - 0.5;
|
||||||
|
cameraMatrix.put(0, 0, new double[] {fxGuess, 0, cx, 0, fyGuess, cy, 0, 0, 1});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// FindBoardCorners pipe outputs all the image points, object points, and frames to calculate
|
// FindBoardCorners pipe outputs all the image points, object points, and frames to calculate
|
||||||
// imageSize from, other parameters are output Mats
|
// imageSize from, other parameters are output Mats
|
||||||
|
|
||||||
calibrationAccuracy =
|
Calib3d.calibrateCameraExtended(
|
||||||
Calib3d.calibrateCameraExtended(
|
objPoints,
|
||||||
objPoints,
|
imgPts,
|
||||||
imgPts,
|
new Size(in.get(0).size.width, in.get(0).size.height),
|
||||||
new Size(in.get(0).size.width, in.get(0).size.height),
|
cameraMatrix,
|
||||||
cameraMatrix,
|
distortionCoefficients,
|
||||||
distortionCoefficients,
|
rvecs,
|
||||||
rvecs,
|
tvecs,
|
||||||
tvecs,
|
stdDeviationsIntrinsics,
|
||||||
stdDeviationsIntrinsics,
|
stdDeviationsExtrinsics,
|
||||||
stdDeviationsExtrinsics,
|
perViewErrors,
|
||||||
perViewErrors);
|
Calib3d.CALIB_USE_LU + Calib3d.CALIB_USE_INTRINSIC_GUESS);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Calibration failed!", e);
|
logger.error("Calibration failed!", e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -164,13 +182,12 @@ public class Calibrate3dPipe
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected CameraCalibrationCoefficients calibrateMrcal(
|
protected CameraCalibrationCoefficients calibrateMrcal(
|
||||||
List<FindBoardCornersPipe.FindBoardCornersPipeResult> in) {
|
List<FindBoardCornersPipe.FindBoardCornersPipeResult> in, double fxGuess, double fyGuess) {
|
||||||
List<MatOfPoint2f> corner_locations =
|
List<MatOfPoint2f> corner_locations =
|
||||||
in.stream().map(it -> it.imagePoints).map(MatOfPoint2f::new).collect(Collectors.toList());
|
in.stream().map(it -> it.imagePoints).map(MatOfPoint2f::new).collect(Collectors.toList());
|
||||||
|
|
||||||
int imageWidth = (int) in.get(0).size.width;
|
int imageWidth = (int) in.get(0).size.width;
|
||||||
int imageHeight = (int) in.get(0).size.height;
|
int imageHeight = (int) in.get(0).size.height;
|
||||||
final double FOCAL_LENGTH_GUESS = 1200;
|
|
||||||
|
|
||||||
MrCalResult result =
|
MrCalResult result =
|
||||||
MrCalJNI.calibrateCamera(
|
MrCalJNI.calibrateCamera(
|
||||||
@@ -180,7 +197,7 @@ public class Calibrate3dPipe
|
|||||||
params.squareSize,
|
params.squareSize,
|
||||||
imageWidth,
|
imageWidth,
|
||||||
imageHeight,
|
imageHeight,
|
||||||
FOCAL_LENGTH_GUESS);
|
(fxGuess + fyGuess) / 2.0);
|
||||||
|
|
||||||
// intrinsics are fx fy cx cy from mrcal
|
// intrinsics are fx fy cx cy from mrcal
|
||||||
JsonMatOfDouble cameraMatrixMat =
|
JsonMatOfDouble cameraMatrixMat =
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.photonvision.vision.frame.FrameThresholdType;
|
|||||||
import org.photonvision.vision.opencv.CVMat;
|
import org.photonvision.vision.opencv.CVMat;
|
||||||
import org.photonvision.vision.opencv.ImageRotationMode;
|
import org.photonvision.vision.opencv.ImageRotationMode;
|
||||||
import org.photonvision.vision.pipe.CVPipe.CVPipeResult;
|
import org.photonvision.vision.pipe.CVPipe.CVPipeResult;
|
||||||
|
import org.photonvision.vision.pipe.impl.Calibrate3dPipe.CalibrationInput;
|
||||||
import org.photonvision.vision.pipe.impl.FindBoardCornersPipe.FindBoardCornersPipeResult;
|
import org.photonvision.vision.pipe.impl.FindBoardCornersPipe.FindBoardCornersPipeResult;
|
||||||
import org.photonvision.vision.pipeline.CVPipeline;
|
import org.photonvision.vision.pipeline.CVPipeline;
|
||||||
import org.photonvision.vision.pipeline.Calibration3dPipelineSettings;
|
import org.photonvision.vision.pipeline.Calibration3dPipelineSettings;
|
||||||
@@ -176,7 +177,8 @@ public class Calibrate3dPipeline
|
|||||||
|
|
||||||
/*Pass the board corners to the pipe, which will check again to see if all boards are valid
|
/*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*/
|
and returns the corresponding image and object points*/
|
||||||
calibrationOutput = calibrate3dPipe.run(foundCornersList);
|
calibrationOutput =
|
||||||
|
calibrate3dPipe.run(new CalibrationInput(foundCornersList, frameStaticProperties));
|
||||||
|
|
||||||
this.calibrating = false;
|
this.calibrating = false;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user