Example Calibration Target Pose

From BoofCV
Revision as of 15:45, 17 January 2022 by Peter (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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 fiducials. How accurate is a function of distance and orientation.

Example Code:

Concepts:

  • Calibration target
  • Pose estimation

Related Examples:

Videos

Example Code

/**
 * The 6-DOF pose of calibration targets can be estimated very accurately[*] once a camera has been calibrated.
 * In this example the high level FiducialDetector interface is used with a chessboard calibration target to
 * process a video sequence. Once the pose of the target is known the location of each calibration point is
 * found in the camera frame and visualized.
 *
 * [*] Accuracy is dependent on a variety of factors. Calibration targets are primarily designed to be viewed up close
 * and their accuracy drops with range, as can be seen in this example.
 *
 * @author Peter Abeles
 */
public class ExamplePoseOfCalibrationTarget {
	public static void main( String[] args ) {
		// Load camera calibration
		CameraPinholeBrown intrinsic =
				CalibrationIO.load(UtilIO.pathExample("calibration/mono/Sony_DSC-HX5V_Chess/intrinsic.yaml"));
		LensDistortionNarrowFOV lensDistortion = new LensDistortionBrown(intrinsic);

		// load the video file
		String fileName = UtilIO.pathExample("tracking/chessboard_SonyDSC_01.mjpeg");
		SimpleImageSequence<GrayF32> video =
				DefaultMediaManager.INSTANCE.openVideo(fileName, ImageType.single(GrayF32.class));
//				DefaultMediaManager.INSTANCE.openCamera(null, 640, 480, ImageType.single(GrayF32.class));

		// Let's use the FiducialDetector interface since it is much easier than coding up
		// the entire thing ourselves. Look at FiducialDetector's code if you want to understand how it works.
		CalibrationFiducialDetector<GrayF32> detector =
				FactoryFiducial.calibChessboardX(null, new ConfigGridDimen(4, 5, 0.03), GrayF32.class);

		detector.setLensDistortion(lensDistortion, intrinsic.width, intrinsic.height);

		// Get the 2D coordinate of calibration points for visualization purposes
		List<Point2D_F64> calibPts = detector.getCalibrationPoints();

		// Set up visualization
		PointCloudViewer viewer = VisualizeData.createPointCloudViewer();
		viewer.setCameraHFov(PerspectiveOps.computeHFov(intrinsic));
		viewer.setTranslationStep(0.01);
		viewer.setBackgroundColor(0xFFFFFF); // white background
		// make the view more interest. From the side.
		DMatrixRMaj rotY = ConvertRotation3D_F64.rotY(-Math.PI/2.0, null);
		viewer.setCameraToWorld(new Se3_F64(rotY, new Vector3D_F64(0.75, 0, 1.25)).invert(null));
		var imagePanel = new ImagePanel(intrinsic.width, intrinsic.height);
		var viewerComponent = viewer.getComponent();
		viewerComponent.setPreferredSize(new Dimension(intrinsic.width, intrinsic.height));
		var gui = new PanelGridPanel(1, imagePanel, viewerComponent);
		gui.setMaximumSize(gui.getPreferredSize());
		ShowImages.showWindow(gui, "Calibration Target Pose", true);

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

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

		// Process each frame in the video sequence
		var targetToCamera = new Se3_F64();
		while (video.hasNext()) {
			// detect calibration points
			detector.detect(video.next());

			if (detector.totalFound() == 1) {
				detector.getFiducialToCamera(0, targetToCamera);

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

				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 < calibPts.size(); j++) {
					Point2D_F64 p = calibPts.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.setImage((BufferedImage)video.getGuiImage());
			viewerComponent.repaint();
			imagePanel.repaint();

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