Example Calibration Target Pose

From BoofCV
Revision as of 10:27, 19 June 2014 by Peter (talk | contribs)
Jump to navigationJump to search
Left: Last image in video sequence. Right: Side view in 3D. Green dots is the target's trajectory and black dots are calibration points in the last frame.

In addition to calibration, calibration targets can be used to estimate the pose of objects in the scene to a high degree of accuracy. The location of calibration points can be estimated to a high degree of accuracy in the image making this approach more accurate than more generate purpose fidicuals. How accurate is a function of distance and orientation.


Example Code:

Concepts:

  • Calibration target
  • Pose estimation

Related Examples:

Example Code

/**
 * The 6-DOF pose of calibration targets relative to the camera can be estimated very accurately once a camera
 * has been calibrated.  This example demonstrates how detect a calibration target and convert it into a rigid body
 * transformation from target's frame into the camera's frame.  Orientation can be uniquely estimated for some
 * calibration grid patterns.  If the pattern is symmetric then the pose can only be estimated up to the symmetry.
 *
 * @author Peter Abeles
 */
public class ExamplePoseOfCalibrationTarget {

	public static void main( String args[] ) {

		// Load camera calibration
		IntrinsicParameters intrinsic =
				UtilIO.loadXML("../data/applet/calibration/mono/Sony_DSC-HX5V_Chess/intrinsic.xml");

		int width = intrinsic.width; int height = intrinsic.height;

		// load the video file
		String fileName = "../data/applet/tracking/chessboard_SonyDSC_01.mjpeg";
		SimpleImageSequence<ImageFloat32> video =
				DefaultMediaManager.INSTANCE.openVideo(fileName, ImageType.single(ImageFloat32.class));

		// Detects the target and calibration point inside the target
		PlanarCalibrationDetector detector = FactoryPlanarCalibrationTarget.detectorChessboard(new ConfigChessboard(5, 4));
		// Specifies the location of calibration points in the target's coordinate system.  Note that z=0
		double sizeOfSquareInMeters = 0.03;
		PlanarCalibrationTarget target = FactoryPlanarCalibrationTarget.gridChess(5, 4, sizeOfSquareInMeters);
		// Computes the homography
		Zhang99ComputeTargetHomography computeH = new Zhang99ComputeTargetHomography(target);
		// decomposes the homography
		Zhang99DecomposeHomography decomposeH = new Zhang99DecomposeHomography();

		// Need to remove lens distortion for accurate pose estimation
		PointTransform_F64 distortToUndistorted = LensDistortionOps.transformRadialToPixel_F64(intrinsic);

		// convert the intrinsic into matrix format
		DenseMatrix64F K = PerspectiveOps.calibrationMatrix(intrinsic,null);

		// Set up visualization
		JPanel gui = new JPanel();
		PointCloudViewer viewer = new PointCloudViewer(intrinsic, 0.01);
		// make the view more interest.  From the side.
		DenseMatrix64F rotY = RotationMatrixGenerator.rotY(-Math.PI/2.0,null);
		viewer.setWorldToCamera(new Se3_F64(rotY,new Vector3D_F64(0.75,0,1.25)));
		ImagePanel imagePanel = new ImagePanel(width, height);
		gui.add(BorderLayout.WEST, imagePanel); gui.add(BorderLayout.CENTER, viewer);
		ShowImages.showWindow(gui,"Calibration Target Pose");

		// Allows the user to click on the image and pause
		MousePauseHelper pauseHelper = new MousePauseHelper(gui);

		// saves the target's center location
		List<Point3D_F64> path = new ArrayList<Point3D_F64>();

		// Process each frame in the video sequence
		while( video.hasNext() ) {

			// detect calibration points
			if( !detector.process(video.next()) )
				throw new RuntimeException("Failed to detect target");

			// Remove lens distortion from detected calibration points
			List<Point2D_F64> points = detector.getPoints();
			for( Point2D_F64 p : points ) {
				distortToUndistorted.compute(p.x,p.y,p);
			}

			// Compute the homography
			if( !computeH.computeHomography(points) )
				throw new RuntimeException("Can't compute homography");

			DenseMatrix64F H = computeH.getHomography();

			// compute camera pose from the homography matrix
			decomposeH.setCalibrationMatrix(K);
			Se3_F64 targetToCamera = decomposeH.decompose(H);

			// Visualization.  Show a path with green points and the calibration points in black
			viewer.reset();

			Point3D_F64 center = new Point3D_F64();
			SePointOps_F64.transform(targetToCamera,center,center);
			path.add(center);

			for( Point3D_F64 p : path ) {
				viewer.addPoint(p.x,p.y,p.z,0x00FF00);
			}

			for( int j = 0; j < target.points.size(); j++ ) {
				Point2D_F64 p = target.points.get(j);
				Point3D_F64 p3 = new Point3D_F64(p.x,p.y,0);
				SePointOps_F64.transform(targetToCamera,p3,p3);
				viewer.addPoint(p3.x,p3.y,p3.z,0);
			}

			imagePanel.setBufferedImage((BufferedImage) video.getGuiImage());
			viewer.repaint();
			imagePanel.repaint();

			BoofMiscOps.pause(30);
			while( pauseHelper.isPaused() ) {
				BoofMiscOps.pause(30);
			}
		}
	}
}