Difference between revisions of "Example Calibrate Planar Stereo"

From BoofCV
Jump to navigationJump to search
(Created page with "= Stereo Camera Calibration with Planar Targets = <center> <gallery heights=220 widths=500 > Image:Uncalib_stereo.jpg|Image of a stereo pair before calibration. Image:Calib_s...")
 
m
(21 intermediate revisions by the same user not shown)
Line 1: Line 1:
= Stereo Camera Calibration with Planar Targets =
<center>
<center>
<gallery heights=220 widths=500 >
<gallery heights=220 widths=500 >
Line 8: Line 6:
</center>
</center>


Calibrating a stereo camera system is the process of learning its intrinsic parameters for each camera and the extrinsic parameters between the two cameras. This example demonstrates how to use multiple pictures of a planar calibration target.  Both the square grid and chessboard patterns are supported by this example.  For a full description of the calibration process and instruction on how to do it yourself see the tutorial linked to below.
This example demonstrate how to calibrate a stereo camera system using a high level interface which automatically detects calibration targets in a set of stereo images.  After calibration the intrinsic parameters of each camera is found as well as their extrinsic relationship with each other. Both the square grid and chessboard patterns are supported by this example.  For a full description of the calibration process and instruction on how to do it yourself see the tutorial linked to below.


Example File: [https://github.com/lessthanoptimal/BoofCV/blob/master/examples/src/boofcv/examples/ExampleCalibrateStereoPlanar.java ExampleCalibrateStereoPlanar.java]
Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0.35/examples/src/main/java/boofcv/examples/calibration/ExampleCalibrateStereo.java ExampleCalibrateStereo.java]


Calibration Tutorial: [[Tutorial_Camera_Calibration|Wikipage]]
Calibration Tutorial: [[Tutorial_Camera_Calibration|Wikipage]]
Line 19: Line 17:
* Intrinsic parameters
* Intrinsic parameters
* Stereo Vision
* Stereo Vision
Relevant Applets:
* [[Applet_Calibrate_Planar_Stereo| Stereo Calibration]]


Related Examples:
Related Examples:
* [[Example_Rectification_Calibrated| Calibrated Stereo Rectification]]
* [[Example_Calibrate_Planar_Mono| Monocular Camera Calibration]]
* [[Example_Calibrate_Planar_Mono| Monocular Camera Calibration]]
* [[Example_Remove_Lens_Distortion| Removing Lens Distortion]]
* [[Example_Remove_Lens_Distortion| Removing Lens Distortion]]
Line 30: Line 26:
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
/**
/**
* <p>
  * Example of how to calibrate a stereo camera system using a planar calibration grid given a set of images.
  * Example of how to calibrate a stereo camera system using a planar calibration grid.  The intrinsic camera parameters
  * Intrinsic camera parameters are estimated for both cameras individually, then extrinsic parameters
* are estimated for both cameras individually, then extrinsic parameters for the two cameras relative to each other
* for the two cameras relative to each other are found  This example does not rectify the images, which is
* are found  This example does not rectify the images, which is  required for some algorithms.
  * required for some algorithms. See {@link boofcv.examples.stereo.ExampleRectifyCalibratedStereo}. Both square grid and chessboard targets
* See {@link ExampleRectifyCalibratedStereo}. Both square grid and chessboard targets are demonstrated in this example.
* are demonstrated in this example. See calibration tutorial for a discussion of different target types and how to
* See calibration tutorial for a discussion of different target types and how to collect good calibration images.
* collect good calibration images.
* </p>
  *
  *
* <<p>
  * All the image processing and calibration is taken care of inside of {@link CalibrateStereoPlanar}.  The code below
  * All the image processing and calibration is taken care of inside of {@link CalibrateStereoPlanar}.  The code below
  * loads calibration images as inputs, calibrates, and saves results to an XML file.  See in code comments for tuning
  * loads calibration images as inputs, calibrates, and saves results to an XML file.  See in code comments for tuning
  * and implementation issues.
  * and implementation issues.
* </p>
  *
  *
  * @see ExampleRectifyCalibratedStereo
  * @see boofcv.examples.stereo.ExampleRectifyCalibratedStereo
  * @see CalibrateStereoPlanar
  * @see CalibrateStereoPlanar
  *
  *
  * @author Peter Abeles
  * @author Peter Abeles
  */
  */
public class ExampleCalibrateStereoPlanar {
public class ExampleCalibrateStereo {


// Detects the target and calibration point inside the target
// Detects the target and calibration point inside the target
PlanarCalibrationDetector detector;
DetectorFiducialCalibration detector;
 
// Description of the target's physical dimension
PlanarCalibrationTarget target;


// List of calibration images
// List of calibration images
List<String> left;
List<String> left;
List<String> right;
List<String> right;
// Most computer images are in a left handed coordinate system.  If set to true it will be changed into
// a right handed coordinate system.  This is required for stereo calibration to work correctly.
boolean isLeftHanded;


/**
/**
Line 69: Line 55:
*/
*/
public void setupBumblebeeSquare() {
public void setupBumblebeeSquare() {
// Use the wrapper below for square grid targets.
// Creates a detector and specifies its physical characteristics
detector = new WrapPlanarGridTarget(3,4);
detector = FactoryFiducialCalibration.squareGrid(null,new ConfigGridDimen(4, 3, 30, 30));
// Target physical description
target = FactoryPlanarCalibrationTarget.gridSquare(3, 4, 30,30);


String directory = "../data/evaluation/calibration/stereo/Bumblebee2_Square";
String directory = UtilIO.pathExample("calibration/stereo/Bumblebee2_Square");


left = BoofMiscOps.directoryList(directory, "left");
left = UtilIO.listByPrefix(directory, "left", null);
right = BoofMiscOps.directoryList(directory, "right");
right = UtilIO.listByPrefix(directory, "right", null);
 
isLeftHanded = true;
}
}


Line 86: Line 68:
*/
*/
public void setupBumblebeeChess() {
public void setupBumblebeeChess() {
// Use the wrapper below for chessboard targets.  The last parameter adjusts the size of the corner detection
// Creates a detector and specifies its physical characteristics
// region.  TUNE THIS PARAMETER FOR OPTIMAL ACCURACY!
detector = FactoryFiducialCalibration.chessboardX(null,new ConfigGridDimen(7, 5, 30));
detector = new WrapPlanarChessTarget(3,4,6);
// Target physical description
target = FactoryPlanarCalibrationTarget.gridChess(3, 4, 30);


String directory = "../data/evaluation/calibration/stereo/Bumblebee2_Chess";
String directory = UtilIO.pathExample("calibration/stereo/Bumblebee2_Chess");


left = BoofMiscOps.directoryList(directory, "left");
left = UtilIO.listByPrefix(directory, "left", null);
right = BoofMiscOps.directoryList(directory, "right");
right = UtilIO.listByPrefix(directory, "right", null);
 
isLeftHanded = true;
}
}


Line 105: Line 82:
public void process() {
public void process() {
// Declare and setup the calibration algorithm
// Declare and setup the calibration algorithm
CalibrateStereoPlanar calibratorAlg = new CalibrateStereoPlanar(detector,isLeftHanded);
CalibrateStereoPlanar calibratorAlg = new CalibrateStereoPlanar(detector.getLayout());
calibratorAlg.configure(target, false, 2);
calibratorAlg.configure(true, 2, false);


// ensure the lists are in the same order
// ensure the lists are in the same order
Line 116: Line 93:
BufferedImage r = UtilImageIO.loadImage(right.get(i));
BufferedImage r = UtilImageIO.loadImage(right.get(i));


ImageFloat32 imageLeft = ConvertBufferedImage.convertFrom(l,(ImageFloat32)null);
GrayF32 imageLeft = ConvertBufferedImage.convertFrom(l,(GrayF32)null);
ImageFloat32 imageRight = ConvertBufferedImage.convertFrom(r,(ImageFloat32)null);
GrayF32 imageRight = ConvertBufferedImage.convertFrom(r,(GrayF32)null);
 
CalibrationObservation calibLeft,calibRight;
if( !detector.process(imageLeft)) {
System.out.println("Failed to detect target in "+left.get(i));
continue;
}
calibLeft = detector.getDetectedPoints();
if( !detector.process(imageRight)) {
System.out.println("Failed to detect target in "+right.get(i));
continue;
}
calibRight = detector.getDetectedPoints();


calibratorAlg.addPair(imageLeft, imageRight);
calibratorAlg.addPair(calibLeft, calibRight);
}
}


// Process and compute calibration parameters
// Process and compute calibration parameters
StereoParameters stereoCalib = calibratorAlg.process();
StereoParameters stereoCalib = calibratorAlg.process();
// print out information on its accuracy and errors
calibratorAlg.printStatistics();


// save results to a file and print out
// save results to a file and print out
BoofMiscOps.saveXML(stereoCalib, "stereo.xml");
CalibrationIO.save(stereoCalib, "stereo.yaml");
stereoCalib.print();
stereoCalib.print();
// Note that the stereo baseline translation will be specified in the same units as the calibration grid.
// Which is in millimeters (mm) in this example.
}
}


public static void main( String args[] ) {
public static void main( String args[] ) {
ExampleCalibrateStereoPlanar alg = new ExampleCalibrateStereoPlanar();
ExampleCalibrateStereo alg = new ExampleCalibrateStereo();


// Select which set of targets to use
// Select which set of targets to use

Revision as of 17:57, 23 December 2019

This example demonstrate how to calibrate a stereo camera system using a high level interface which automatically detects calibration targets in a set of stereo images. After calibration the intrinsic parameters of each camera is found as well as their extrinsic relationship with each other. Both the square grid and chessboard patterns are supported by this example. For a full description of the calibration process and instruction on how to do it yourself see the tutorial linked to below.

Example File: ExampleCalibrateStereo.java

Calibration Tutorial: Wikipage

Concepts:

  • Camera calibration
  • Lens distortion
  • Intrinsic parameters
  • Stereo Vision

Related Examples:

Example Code

/**
 * Example of how to calibrate a stereo camera system using a planar calibration grid given a set of images.
 * Intrinsic camera parameters are estimated for both cameras individually, then extrinsic parameters
 * for the two cameras relative to each other are found   This example does not rectify the images, which is
 * required for some algorithms. See {@link boofcv.examples.stereo.ExampleRectifyCalibratedStereo}. Both square grid and chessboard targets
 * are demonstrated in this example. See calibration tutorial for a discussion of different target types and how to
 * collect good calibration images.
 *
 * All the image processing and calibration is taken care of inside of {@link CalibrateStereoPlanar}.  The code below
 * loads calibration images as inputs, calibrates, and saves results to an XML file.  See in code comments for tuning
 * and implementation issues.
 *
 * @see boofcv.examples.stereo.ExampleRectifyCalibratedStereo
 * @see CalibrateStereoPlanar
 *
 * @author Peter Abeles
 */
public class ExampleCalibrateStereo {

	// Detects the target and calibration point inside the target
	DetectorFiducialCalibration detector;

	// List of calibration images
	List<String> left;
	List<String> right;

	/**
	 * Square grid target taken by a PtGrey Bumblebee camera.
	 */
	public void setupBumblebeeSquare() {
		// Creates a detector and specifies its physical characteristics
		detector = FactoryFiducialCalibration.squareGrid(null,new ConfigGridDimen(4, 3, 30, 30));

		String directory = UtilIO.pathExample("calibration/stereo/Bumblebee2_Square");

		left = UtilIO.listByPrefix(directory, "left", null);
		right = UtilIO.listByPrefix(directory, "right", null);
	}

	/**
	 * Chessboard target taken by a PtGrey Bumblebee camera.
	 */
	public void setupBumblebeeChess() {
		// Creates a detector and specifies its physical characteristics
		detector = FactoryFiducialCalibration.chessboardX(null,new ConfigGridDimen(7, 5, 30));

		String directory = UtilIO.pathExample("calibration/stereo/Bumblebee2_Chess");

		left = UtilIO.listByPrefix(directory, "left", null);
		right = UtilIO.listByPrefix(directory, "right", null);
	}

	/**
	 * Process calibration images, compute intrinsic parameters, save to a file
	 */
	public void process() {
		// Declare and setup the calibration algorithm
		CalibrateStereoPlanar calibratorAlg = new CalibrateStereoPlanar(detector.getLayout());
		calibratorAlg.configure(true, 2, false);

		// ensure the lists are in the same order
		Collections.sort(left);
		Collections.sort(right);

		for( int i = 0; i < left.size(); i++ ) {
			BufferedImage l = UtilImageIO.loadImage(left.get(i));
			BufferedImage r = UtilImageIO.loadImage(right.get(i));

			GrayF32 imageLeft = ConvertBufferedImage.convertFrom(l,(GrayF32)null);
			GrayF32 imageRight = ConvertBufferedImage.convertFrom(r,(GrayF32)null);

			CalibrationObservation calibLeft,calibRight;
			if( !detector.process(imageLeft)) {
				System.out.println("Failed to detect target in "+left.get(i));
				continue;
			}
			calibLeft = detector.getDetectedPoints();
			if( !detector.process(imageRight)) {
				System.out.println("Failed to detect target in "+right.get(i));
				continue;
			}
			calibRight = detector.getDetectedPoints();

			calibratorAlg.addPair(calibLeft, calibRight);
		}

		// Process and compute calibration parameters
		StereoParameters stereoCalib = calibratorAlg.process();

		// print out information on its accuracy and errors
		calibratorAlg.printStatistics();

		// save results to a file and print out
		CalibrationIO.save(stereoCalib, "stereo.yaml");
		stereoCalib.print();

		// Note that the stereo baseline translation will be specified in the same units as the calibration grid.
		// Which is in millimeters (mm) in this example.
	}

	public static void main( String args[] ) {
		ExampleCalibrateStereo alg = new ExampleCalibrateStereo();

		// Select which set of targets to use
		alg.setupBumblebeeChess();
//		alg.setupBumblebeeSquare();

		// compute and save results
		alg.process();
	}
}