Example Stereo Disparity 3D

From BoofCV
Revision as of 06:12, 15 April 2013 by Peter (talk | contribs) (Created page with "<center> <gallery widths=320px heights=240px> file:Example_stereo_disparity3d_pointcloud.jpg | 3D point cloud generated from disparity image. </gallery> </center> An addition...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

An additional example for stereo disparity. This one shows you how to properly resize input images and convert the disparity image into a 3D point cloud.

Example Code:

Concepts:

  • Stereo disparity
  • Point clouds

Relevant Applets:

Related Examples:

Example Code

/**
 * Expanding upon ExampleStereoDisparity, this example demonstrates how to rescale an image for stereo processing and
 * then compute its 3D point cloud.  Images are often rescaled to improve speed and some times quality.  Creating
 * 3D point clouds from disparity images is easy and well documented in the literature, but there are some nuances
 * to it.
 *
 * @author Peter Abeles
 */
public class ExampleStereoDisparity3D {

	// Specifies what size input images are scaled to
	public static final double scale = 0.5;

	// Specifies what range of disparity is considered
	public static final int minDisparity = 0;
	public static final int maxDisparity = 40;
	public static final int rangeDisparity = maxDisparity-minDisparity;

	public static void main( String args[] ) {
		// ------------- Compute Stereo Correspondence

		// Load camera images and stereo camera parameters
		String calibDir = "../data/applet/calibration/stereo/Bumblebee2_Chess/";
		String imageDir = "../data/applet/stereo/";

		StereoParameters param = BoofMiscOps.loadXML(calibDir + "stereo.xml");

		// load and convert images into a BoofCV format
		BufferedImage origLeft = UtilImageIO.loadImage(imageDir + "chair01_left.jpg");
		BufferedImage origRight = UtilImageIO.loadImage(imageDir + "chair01_right.jpg");

		ImageUInt8 distLeft = ConvertBufferedImage.convertFrom(origLeft, (ImageUInt8) null);
		ImageUInt8 distRight = ConvertBufferedImage.convertFrom(origRight,(ImageUInt8)null);

		// re-scale input images
		ImageUInt8 scaledLeft = new ImageUInt8((int)(distLeft.width*scale),(int)(distLeft.height*scale));
		ImageUInt8 scaledRight = new ImageUInt8((int)(distRight.width*scale),(int)(distRight.height*scale));

		DistortImageOps.scale(distLeft,scaledLeft, TypeInterpolate.BILINEAR);
		DistortImageOps.scale(distRight,scaledRight, TypeInterpolate.BILINEAR);

		// Don't forget to adjust camera parameters for the change in scale!
		PerspectiveOps.scaleIntrinsic(param.left, scale);
		PerspectiveOps.scaleIntrinsic(param.right,scale);

		// rectify images and compute disparity
		ImageUInt8 rectLeft = new ImageUInt8(scaledLeft.width,scaledLeft.height);
		ImageUInt8 rectRight = new ImageUInt8(scaledRight.width,scaledRight.height);

		RectifyCalibrated rectAlg = ExampleStereoDisparity.rectify(scaledLeft,scaledRight,param,rectLeft,rectRight);

//		ImageUInt8 disparity = ExampleStereoDisparity.denseDisparity(rectLeft, rectRight, 3,minDisparity, maxDisparity);
		ImageFloat32 disparity = ExampleStereoDisparity.denseDisparitySubpixel(rectLeft, rectRight, 3, minDisparity, maxDisparity);

		// ------------- Convert disparity image into a 3D point cloud

		// The point cloud will be in the left cameras reference frame
		DenseMatrix64F rectK = rectAlg.getCalibrationMatrix();
		DenseMatrix64F rectR = rectAlg.getRectifiedRotation();

		// used to display the point cloud
		PointCloudViewer viewer = new PointCloudViewer(rectK,1);
		viewer.setPreferredSize(new Dimension(rectLeft.width,rectLeft.height));

		// extract intrinsic parameters from rectified camera
		double baseline = param.getBaseline();
		double fx = rectK.get(0,0);
		double fy = rectK.get(1,1);
		double cx = rectK.get(0,2);
		double cy = rectK.get(1,2);

		// Iterate through each pixel in disparity image and compute its 3D coordinate
		Point3D_F64 pointRect = new Point3D_F64();
		Point3D_F64 pointLeft = new Point3D_F64();
		for( int y = 0; y < disparity.height; y++ ) {
			for( int x = 0; x < disparity.width; x++ ) {
				double d = disparity.unsafe_get(x,y) + minDisparity;

				// skip over pixels were no correspondence was found
				if( d >= rangeDisparity )
					continue;

				// Coordinate in rectified camera frame
				pointRect.z = baseline*fx/d;
				pointRect.x = pointRect.z*(x - cx)/fx;
				pointRect.y = pointRect.z*(y - cy)/fy;

				// rotate into the original left camera frame
				GeometryMath_F64.multTran(rectR, pointRect, pointLeft);

				// add pixel to the view for display purposes and sets its gray scale value
				int v = rectLeft.unsafe_get(x, y);
				viewer.addPoint(pointLeft.x, pointLeft.y, pointLeft.z, v << 16 | v << 8 | v);
			}
		}

		// display the results.  Click and drag to change point cloud camera
		BufferedImage visualized = VisualizeImageData.disparity(disparity, null,minDisparity, maxDisparity,0);
		ShowImages.showWindow(visualized,"Disparity");
		ShowImages.showWindow(viewer,"Point Cloud");
	}
}