Difference between revisions of "Example Rectification Calibrated"

From BoofCV
m
m
 
(10 intermediate revisions by the same user not shown)
Line 6: Line 6:
 
</center>
 
</center>
  
Stereo rectification is the process of distorting an image such that the epipoles of both images are at infinity. If the epipoles are at infinity along the x-axis, then corresponding features must lie along the same y-coordinates. Using knowledge that correspondence feature's have the same y-coordinate allows for quick searches. Many stereo vision algorithm rely on rectification.  The example below demonstrates rectification for a calibrated stereo pair. Note that after calibration the new camera view has a different set of intrinsic parameters.
+
Stereo rectification is the process of distorting an image such that the epipoles of both images are at infinity. If the epipoles are at infinity along the x-axis, then corresponding features must lie along the same y-coordinates. Using knowledge that correspondence feature's have the same y-coordinate allows for quick searches. Many stereo vision algorithm rely on rectification.  The example below demonstrates rectification for a calibrated stereo pair. Note that after calibration the new camera view has a different set of intrinsic parameters.
  
Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0.19/examples/src/boofcv/examples/stereo/ExampleRectifyCalibratedStereo.java ExampleRectifyCalibratedStereo.java]
+
Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0.36/examples/src/main/java/boofcv/examples/stereo/ExampleRectifyCalibratedStereo.java ExampleRectifyCalibratedStereo.java]
  
 
Concepts:
 
Concepts:
 
* Stereo Rectification
 
* Stereo Rectification
 
* Stereo Vision
 
* Stereo Vision
 
Relevant Applets:
 
* [[Applet_Rectification_Calibrated| Calibrated Stereo Rectification]]
 
  
 
Related Examples:
 
Related Examples:
* [[Example_Rectification_Uncalibrated| Uncalibrated Stereo Rectification]]
 
 
* [[Example_Calibrate_Planar_Stereo| Stereo Camera Calibration]]
 
* [[Example_Calibrate_Planar_Stereo| Stereo Camera Calibration]]
 
* [[Example_Remove_Lens_Distortion| Removing Lens Distortion]]
 
* [[Example_Remove_Lens_Distortion| Removing Lens Distortion]]
Line 45: Line 41:
  
 
public static void main( String args[] ) {
 
public static void main( String args[] ) {
String dir = "../data/applet/calibration/stereo/Bumblebee2_Chess/";
+
String dir = UtilIO.pathExample("calibration/stereo/Bumblebee2_Chess/");
  
StereoParameters param = UtilIO.loadXML(dir + "stereo.xml");
+
StereoParameters param = CalibrationIO.load(new File(dir , "stereo.yaml"));
  
 
// load images
 
// load images
BufferedImage origLeft = UtilImageIO.loadImage(dir+"left05.jpg");
+
BufferedImage origLeft = UtilImageIO.loadImage(dir,"left05.jpg");
BufferedImage origRight = UtilImageIO.loadImage(dir+"right05.jpg");
+
BufferedImage origRight = UtilImageIO.loadImage(dir,"right05.jpg");
  
 
// distorted images
 
// distorted images
MultiSpectral<ImageFloat32> distLeft =
+
Planar<GrayF32> distLeft =
ConvertBufferedImage.convertFromMulti(origLeft, null,true, ImageFloat32.class);
+
ConvertBufferedImage.convertFromPlanar(origLeft, null,true, GrayF32.class);
MultiSpectral<ImageFloat32> distRight =
+
Planar<GrayF32> distRight =
ConvertBufferedImage.convertFromMulti(origRight, null,true, ImageFloat32.class);
+
ConvertBufferedImage.convertFromPlanar(origRight, null,true, GrayF32.class);
  
 
// storage for undistorted + rectified images
 
// storage for undistorted + rectified images
MultiSpectral<ImageFloat32> rectLeft = distLeft.createSameShape();
+
Planar<GrayF32> rectLeft = distLeft.createSameShape();
MultiSpectral<ImageFloat32> rectRight = distRight.createSameShape();
+
Planar<GrayF32> rectRight = distRight.createSameShape();
  
 
// Compute rectification
 
// Compute rectification
Line 68: Line 64:
  
 
// original camera calibration matrices
 
// original camera calibration matrices
DenseMatrix64F K1 = PerspectiveOps.calibrationMatrix(param.getLeft(), null);
+
DMatrixRMaj K1 = PerspectiveOps.pinholeToMatrix(param.getLeft(), (DMatrixRMaj)null);
DenseMatrix64F K2 = PerspectiveOps.calibrationMatrix(param.getRight(), null);
+
DMatrixRMaj K2 = PerspectiveOps.pinholeToMatrix(param.getRight(), (DMatrixRMaj)null);
  
 
rectifyAlg.process(K1,new Se3_F64(),K2,leftToRight);
 
rectifyAlg.process(K1,new Se3_F64(),K2,leftToRight);
  
 
// rectification matrix for each image
 
// rectification matrix for each image
DenseMatrix64F rect1 = rectifyAlg.getRect1();
+
DMatrixRMaj rect1 = rectifyAlg.getRect1();
DenseMatrix64F rect2 = rectifyAlg.getRect2();
+
DMatrixRMaj rect2 = rectifyAlg.getRect2();
 
// New calibration matrix,
 
// New calibration matrix,
 
// Both cameras have the same one after rectification.
 
// Both cameras have the same one after rectification.
DenseMatrix64F rectK = rectifyAlg.getCalibrationMatrix();
+
DMatrixRMaj rectK = rectifyAlg.getCalibrationMatrix();
  
 
// Adjust the rectification to make the view area more useful
 
// Adjust the rectification to make the view area more useful
RectifyImageOps.fullViewLeft(param.left, rect1, rect2, rectK);
+
RectifyImageOps.fullViewLeft(param.left, rect1, rect2, rectK, null);
// RectifyImageOps.allInsideLeft(param.left, leftHanded, rect1, rect2, rectK);
+
// RectifyImageOps.allInsideLeft(param.left, rect1, rect2, rectK, null);
  
 
// undistorted and rectify images
 
// undistorted and rectify images
ImageDistort<ImageFloat32,ImageFloat32> imageDistortLeft =
+
FMatrixRMaj rect1_F32 = new FMatrixRMaj(3,3); // TODO simplify code some how
RectifyImageOps.rectifyImage(param.getLeft(), rect1, BorderType.SKIP, ImageFloat32.class);
+
FMatrixRMaj rect2_F32 = new FMatrixRMaj(3,3);
ImageDistort<ImageFloat32,ImageFloat32> imageDistortRight =
+
ConvertMatrixData.convert(rect1, rect1_F32);
RectifyImageOps.rectifyImage(param.getRight(), rect2, BorderType.SKIP, ImageFloat32.class);
+
ConvertMatrixData.convert(rect2, rect2_F32);
 +
 
 +
ImageDistort rectifyImageLeft =
 +
RectifyImageOps.rectifyImage(param.getLeft(), rect1_F32, BorderType.SKIP, distLeft.getImageType());
 +
ImageDistort rectifyImageRight =
 +
RectifyImageOps.rectifyImage(param.getRight(), rect2_F32, BorderType.SKIP, distRight.getImageType());
  
DistortImageOps.distortMS(distLeft, rectLeft, imageDistortLeft);
+
rectifyImageLeft.apply(distLeft,rectLeft);
DistortImageOps.distortMS(distRight, rectRight, imageDistortRight);
+
rectifyImageRight.apply(distRight,rectRight);
  
 
// convert for output
 
// convert for output

Latest revision as of 22:32, 17 May 2020

Stereo rectification is the process of distorting an image such that the epipoles of both images are at infinity. If the epipoles are at infinity along the x-axis, then corresponding features must lie along the same y-coordinates. Using knowledge that correspondence feature's have the same y-coordinate allows for quick searches. Many stereo vision algorithm rely on rectification. The example below demonstrates rectification for a calibrated stereo pair. Note that after calibration the new camera view has a different set of intrinsic parameters.

Example File: ExampleRectifyCalibratedStereo.java

Concepts:

  • Stereo Rectification
  • Stereo Vision

Related Examples:

Example Code

/**
 * <p>
 * Shows how to rectify a pair of stereo images with known intrinsic parameters and stereo baseline.
 * The example code does the following:<br>
 * 1) Load stereo parameters from XML file with a pair of images.<br>
 * 2) Undistort and rectify images..  This provides one rectification matrix
 * for each image along with a new camera calibration matrix.<br>
 * 3) The original rectification does not try to maximize view area, however it can be adjusted.
 * 4)After rectification is finished the results are displayed.<br>
 * </p>
 *
 * <p>
 * Note that the y-axis in left and right images align after rectification.  The curved image edge
 * is an artifact of lens distortion being removed.
 * </p>
 *
 * @author Peter Abeles
 */
public class ExampleRectifyCalibratedStereo {

	public static void main( String args[] ) {
		String dir = UtilIO.pathExample("calibration/stereo/Bumblebee2_Chess/");

		StereoParameters param = CalibrationIO.load(new File(dir , "stereo.yaml"));

		// load images
		BufferedImage origLeft = UtilImageIO.loadImage(dir,"left05.jpg");
		BufferedImage origRight = UtilImageIO.loadImage(dir,"right05.jpg");

		// distorted images
		Planar<GrayF32> distLeft =
				ConvertBufferedImage.convertFromPlanar(origLeft, null,true, GrayF32.class);
		Planar<GrayF32> distRight =
				ConvertBufferedImage.convertFromPlanar(origRight, null,true, GrayF32.class);

		// storage for undistorted + rectified images
		Planar<GrayF32> rectLeft = distLeft.createSameShape();
		Planar<GrayF32> rectRight = distRight.createSameShape();

		// Compute rectification
		RectifyCalibrated rectifyAlg = RectifyImageOps.createCalibrated();
		Se3_F64 leftToRight = param.getRightToLeft().invert(null);

		// original camera calibration matrices
		DMatrixRMaj K1 = PerspectiveOps.pinholeToMatrix(param.getLeft(), (DMatrixRMaj)null);
		DMatrixRMaj K2 = PerspectiveOps.pinholeToMatrix(param.getRight(), (DMatrixRMaj)null);

		rectifyAlg.process(K1,new Se3_F64(),K2,leftToRight);

		// rectification matrix for each image
		DMatrixRMaj rect1 = rectifyAlg.getRect1();
		DMatrixRMaj rect2 = rectifyAlg.getRect2();
		// New calibration matrix,
		// Both cameras have the same one after rectification.
		DMatrixRMaj rectK = rectifyAlg.getCalibrationMatrix();

		// Adjust the rectification to make the view area more useful
		RectifyImageOps.fullViewLeft(param.left, rect1, rect2, rectK, null);
//		RectifyImageOps.allInsideLeft(param.left, rect1, rect2, rectK, null);

		// undistorted and rectify images
		FMatrixRMaj rect1_F32 = new FMatrixRMaj(3,3); // TODO simplify code some how
		FMatrixRMaj rect2_F32 = new FMatrixRMaj(3,3);
		ConvertMatrixData.convert(rect1, rect1_F32);
		ConvertMatrixData.convert(rect2, rect2_F32);

		ImageDistort rectifyImageLeft =
				RectifyImageOps.rectifyImage(param.getLeft(), rect1_F32, BorderType.SKIP, distLeft.getImageType());
		ImageDistort rectifyImageRight =
				RectifyImageOps.rectifyImage(param.getRight(), rect2_F32, BorderType.SKIP, distRight.getImageType());

		rectifyImageLeft.apply(distLeft,rectLeft);
		rectifyImageRight.apply(distRight,rectRight);

		// convert for output
		BufferedImage outLeft = ConvertBufferedImage.convertTo(rectLeft,null,true);
		BufferedImage outRight = ConvertBufferedImage.convertTo(rectRight, null,true);

		// show results and draw a horizontal line where the user clicks to see rectification easier
		ListDisplayPanel panel = new ListDisplayPanel();
		panel.addItem(new RectifiedPairPanel(true, origLeft, origRight), "Original");
		panel.addItem(new RectifiedPairPanel(true, outLeft, outRight), "Rectified");

		ShowImages.showWindow(panel,"Stereo Rectification Calibrated",true);
	}
}