Difference between revisions of "Example Calibrate Planar Fisheye"
From BoofCV
Jump to navigationJump to searchm |
m |
||
(9 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
<center> | <center> | ||
<gallery heights=400 widths= | <gallery heights=400 widths=400 > | ||
Image:Calib_fisheye_chessboard.jpg|Detected Calibration Target in a Fisheye Camera. | Image:Calib_fisheye_chessboard.jpg|Detected Calibration Target in a Fisheye Camera. | ||
</gallery> | </gallery> | ||
Line 7: | Line 7: | ||
This example demonstrates how to compute the intrinsic camera parameters for a fisheye camera lens. Fisheye lenses exhibit significantly more distortion than regular lenses with a more narrow field of view. Its not unusual for a fisheye lens to have a FOV of 185 degrees. The calibration process is very similar to regular cameras. A planar calibration target is shown at different angles across the entire field of view. The main difference is the camera model. | This example demonstrates how to compute the intrinsic camera parameters for a fisheye camera lens. Fisheye lenses exhibit significantly more distortion than regular lenses with a more narrow field of view. Its not unusual for a fisheye lens to have a FOV of 185 degrees. The calibration process is very similar to regular cameras. A planar calibration target is shown at different angles across the entire field of view. The main difference is the camera model. | ||
Example File: [https://github.com/lessthanoptimal/BoofCV/blob/ | Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v1.1.0/examples/src/main/java/boofcv/examples/calibration/ExampleCalibrateFisheye.java ExampleCalibrateFisheye.java] | ||
Calibration Tutorial: [[Tutorial_Camera_Calibration|Wikipage]] | Calibration Tutorial: [[Tutorial_Camera_Calibration|Wikipage]] | ||
Line 15: | Line 15: | ||
* Fisheye Lens distortion | * Fisheye Lens distortion | ||
* Intrinsic parameters | * Intrinsic parameters | ||
Relevant Videos: | |||
* [https://youtu.be/TGg-xgTyaU8?t=69 YouTube Video] | |||
Related Examples: | Related Examples: | ||
Line 27: | Line 30: | ||
* see at a distance and cover more of the fisheye's camera large FOV. | * see at a distance and cover more of the fisheye's camera large FOV. | ||
* | * | ||
* @author Peter Abeles | |||
* @see CalibrateMonoPlanar | * @see CalibrateMonoPlanar | ||
*/ | */ | ||
public class ExampleCalibrateFisheye { | public class ExampleCalibrateFisheye { | ||
public static void main( String | public static void main( String[] args ) { | ||
DetectSingleFiducialCalibration detector; | |||
// Circle based calibration targets | // Circle based calibration targets are not recommended because the sever lens distortion will change | ||
// the apparent location of tangent points. | // the apparent location of tangent points. | ||
// Square Grid example | // Square Grid example | ||
// detector = FactoryFiducialCalibration.squareGrid(new | // detector = FactoryFiducialCalibration.squareGrid(null, new ConfigGridDimen(/*rows*/ 4, /*cols*/ 3, /*size*/ 30, /*space*/ 30)); | ||
// images = UtilIO.listAll(UtilIO.pathExample("calibration/fisheye/square_grid")); | // images = UtilIO.listAll(UtilIO.pathExample("calibration/fisheye/square_grid")); | ||
// Chessboard Example | // Chessboard Example | ||
detector = FactoryFiducialCalibration. | detector = FactoryFiducialCalibration.chessboardX(null, new ConfigGridDimen(/*rows*/7, /*cols*/5, /*size*/30)); | ||
images = UtilIO.listAll(UtilIO.pathExample("calibration/fisheye/chessboard")); | List<String> images = UtilIO.listAll(UtilIO.pathExample("calibration/fisheye/chessboard")); | ||
// Declare and setup the calibration algorithm | // Declare and setup the calibration algorithm | ||
var calibrator = new CalibrateMonoPlanar(); | |||
// Specify the camera model to use. Here are a few examples. | |||
// | |||
calibrator.configureUniversalOmni( /*zeroSkew*/ true, /*radial*/ 2, /*tangential*/ false); | |||
// it's also possible to fix the mirror offset parameter | // it's also possible to fix the mirror offset parameter | ||
// 0 = pinhole camera. 1 = fisheye | // 0 = pinhole camera. 1 = fisheye | ||
// calibrationAlg.configureUniversalOmni( true, 2, false,1.0); | // calibrationAlg.configureUniversalOmni( /*zeroSkew*/ true, /*radial*/ 2, /*tangential*/ false, /*offset*/ 1.0); | ||
// Another popular model is Kannala-Brandt. Most people just use the symmetric terms. | |||
// calibrationAlg.configureKannalaBrandt( /*zeroSkew*/ true, /*symmetric*/ 5, /*asymmetric*/ 0); | |||
for( String n : images ) { | var usedImages = new ArrayList<String>(); | ||
for (String n : images) { | |||
BufferedImage input = UtilImageIO.loadImage(n); | BufferedImage input = UtilImageIO.loadImage(n); | ||
if( input | if (input == null) | ||
GrayF32 image = ConvertBufferedImage.convertFrom(input,(GrayF32)null); | continue; | ||
if( | GrayF32 image = ConvertBufferedImage.convertFrom(input, (GrayF32)null); | ||
if (detector.process(image)) { | |||
// Need to tell it the image shape and the layout once | |||
if (usedImages.isEmpty()) | |||
calibrator.initialize(image.getWidth(), image.getHeight(), List.of(detector.getLayout())); | |||
calibrator.addImage(detector.getDetectedPoints().copy()); | |||
usedImages.add(n); | |||
} else { | |||
System.err.println("Failed to detect target in " + n); | |||
} | } | ||
} | } | ||
// process and compute intrinsic parameters | // process and compute intrinsic parameters | ||
CameraModel intrinsic = calibrator.process(); | |||
// save results to a file and print out | // save results to a file and print out | ||
CalibrationIO.save(intrinsic, "fisheye.yaml"); | CalibrationIO.save(intrinsic, "fisheye.yaml"); | ||
System.out.println(calibrator.computeQualityText(usedImages)); | |||
System.out.println(); | System.out.println(); | ||
System.out.println("--- Intrinsic Parameters ---"); | System.out.println("--- Intrinsic Parameters ---"); | ||
Line 78: | Line 89: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Latest revision as of 18:04, 9 September 2023
This example demonstrates how to compute the intrinsic camera parameters for a fisheye camera lens. Fisheye lenses exhibit significantly more distortion than regular lenses with a more narrow field of view. Its not unusual for a fisheye lens to have a FOV of 185 degrees. The calibration process is very similar to regular cameras. A planar calibration target is shown at different angles across the entire field of view. The main difference is the camera model.
Example File: ExampleCalibrateFisheye.java
Calibration Tutorial: Wikipage
Concepts:
- Camera calibration
- Fisheye Lens distortion
- Intrinsic parameters
Relevant Videos:
Related Examples:
Example Code
/**
* Example of how to calibrate a single (monocular) fisheye camera using a high level interface. This example
* for the most part follows the same routine as {@link ExampleCalibrateMonocular}. Fisheye cameras tend to require
* more images to properly calibrate. Often people will use larger calibration targets too that are easier to
* see at a distance and cover more of the fisheye's camera large FOV.
*
* @author Peter Abeles
* @see CalibrateMonoPlanar
*/
public class ExampleCalibrateFisheye {
public static void main( String[] args ) {
DetectSingleFiducialCalibration detector;
// Circle based calibration targets are not recommended because the sever lens distortion will change
// the apparent location of tangent points.
// Square Grid example
// detector = FactoryFiducialCalibration.squareGrid(null, new ConfigGridDimen(/*rows*/ 4, /*cols*/ 3, /*size*/ 30, /*space*/ 30));
// images = UtilIO.listAll(UtilIO.pathExample("calibration/fisheye/square_grid"));
// Chessboard Example
detector = FactoryFiducialCalibration.chessboardX(null, new ConfigGridDimen(/*rows*/7, /*cols*/5, /*size*/30));
List<String> images = UtilIO.listAll(UtilIO.pathExample("calibration/fisheye/chessboard"));
// Declare and setup the calibration algorithm
var calibrator = new CalibrateMonoPlanar();
// Specify the camera model to use. Here are a few examples.
//
calibrator.configureUniversalOmni( /*zeroSkew*/ true, /*radial*/ 2, /*tangential*/ false);
// it's also possible to fix the mirror offset parameter
// 0 = pinhole camera. 1 = fisheye
// calibrationAlg.configureUniversalOmni( /*zeroSkew*/ true, /*radial*/ 2, /*tangential*/ false, /*offset*/ 1.0);
// Another popular model is Kannala-Brandt. Most people just use the symmetric terms.
// calibrationAlg.configureKannalaBrandt( /*zeroSkew*/ true, /*symmetric*/ 5, /*asymmetric*/ 0);
var usedImages = new ArrayList<String>();
for (String n : images) {
BufferedImage input = UtilImageIO.loadImage(n);
if (input == null)
continue;
GrayF32 image = ConvertBufferedImage.convertFrom(input, (GrayF32)null);
if (detector.process(image)) {
// Need to tell it the image shape and the layout once
if (usedImages.isEmpty())
calibrator.initialize(image.getWidth(), image.getHeight(), List.of(detector.getLayout()));
calibrator.addImage(detector.getDetectedPoints().copy());
usedImages.add(n);
} else {
System.err.println("Failed to detect target in " + n);
}
}
// process and compute intrinsic parameters
CameraModel intrinsic = calibrator.process();
// save results to a file and print out
CalibrationIO.save(intrinsic, "fisheye.yaml");
System.out.println(calibrator.computeQualityText(usedImages));
System.out.println();
System.out.println("--- Intrinsic Parameters ---");
System.out.println();
intrinsic.print();
}
}