Difference between revisions of "ExampleComputeTrifocalTensor"
From BoofCV
Jump to navigationJump to searchm  | 
				m  | 
				||
| (One intermediate revision by the same user not shown) | |||
| Line 2: | Line 2: | ||
'''Example Code:'''  | '''Example Code:'''  | ||
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.  | * [https://github.com/lessthanoptimal/BoofCV/blob/v0.40/examples/src/main/java/boofcv/examples/sfm/ExampleComputeTrifocalTensor.java ExampleComputeTrifocalTensor.java]  | ||
'''Concepts:'''  | '''Concepts:'''  | ||
*   | * 3D Point Cloud  | ||
'''Related Examples:'''  | '''Related Examples:'''  | ||
* [[  | * [[Example_View_Point_Cloud| Viewing a Point Cloud]]  | ||
= Example Code =  | = Example Code =  | ||
| Line 96: | Line 94: | ||
		var triplePanel = new AssociatedTriplePanel();  | 		var triplePanel = new AssociatedTriplePanel();  | ||
		triplePanel.setImages(  | 		triplePanel.setImages(  | ||
				UtilImageIO.  | 				UtilImageIO.loadImageNotNull(UtilIO.pathExample("triple/" + name + "01.jpg")),  | ||
				UtilImageIO.  | 				UtilImageIO.loadImageNotNull(UtilIO.pathExample("triple/" + name + "02.jpg")),  | ||
				UtilImageIO.  | 				UtilImageIO.loadImageNotNull(UtilIO.pathExample("triple/" + name + "03.jpg")));  | ||
		triplePanel.setAssociation(inliers);  | 		triplePanel.setAssociation(inliers);  | ||
		ShowImages.showWindow(triplePanel, "Inliers", true);  | 		ShowImages.showWindow(triplePanel, "Inliers", true);  | ||
Latest revision as of 16:31, 17 January 2022
Shows how to compute a trifocal tensor robustly from a set of image features between three views.
Example Code:
Concepts:
- 3D Point Cloud
 
Related Examples:
Example Code
/**
 * This example shows how to robustly compute a trifocal tensor to features across three views. The trifocal tensor
 * is used extensively in reconstruction scenarios and is more robust than applying two-view tensors (e.g. Fundamental
 * and Essential matrices) which have issues along the epipolar lines.
 */
public class ExampleComputeTrifocalTensor {
	/**
	 * Computes the trifocal tensor given three images. Returns the set of inlier features found when computing
	 * the tensor
	 */
	public static List<AssociatedTriple> imagesToTrifocal(
			GrayU8 gray01, GrayU8 gray02, GrayU8 gray03, TrifocalTensor model ) {
		// Using SURF features. Robust and fairly fast to compute
		var configDetector = new ConfigFastHessian();
		configDetector.maxFeaturesAll = 2500; // limit the feature count
		configDetector.extract.radius = 4;
		DetectDescribePoint<GrayU8, TupleDesc_F64> detDesc = FactoryDetectDescribe.surfStable(configDetector, null, null, GrayU8.class);
		// Associate features across all three views using previous example code
		var associateThree = new ExampleAssociateThreeView();
		associateThree.initialize(detDesc);
		associateThree.detectFeatures(gray01, 0);
		associateThree.detectFeatures(gray02, 1);
		associateThree.detectFeatures(gray03, 2);
		DogArray<AssociatedTripleIndex> associatedIdx = associateThree.threeViewPairwiseAssociate();
		System.out.println("features01.size = " + associateThree.features01.size);
		System.out.println("features02.size = " + associateThree.features02.size);
		System.out.println("features03.size = " + associateThree.features03.size);
		// Convert the matched indexes into AssociatedTriple which contain the actual pixel coordinates
		var associated = new DogArray<>(AssociatedTriple::new);
		associatedIdx.forEach(p -> associated.grow().setTo(
				associateThree.locations01.get(p.a),
				associateThree.locations02.get(p.b),
				associateThree.locations03.get(p.c)));
		System.out.println("Total Matched Triples = " + associated.size);
		// Storage for the found model. In this example we don't actually use the tensor.
		List<AssociatedTriple> inliers = computeTrifocal(associated, model);
		System.out.println("Remaining after RANSAC " + inliers.size());
		return inliers;
	}
	/**
	 * Computes the Trifocal Tensor using RANSAC given associated features across 3-views. The found tensor
	 * is copied into model and the inliers are returned.
	 */
	public static List<AssociatedTriple> computeTrifocal( DogArray<AssociatedTriple> associated, TrifocalTensor model ) {
		var configRansac = new ConfigRansac();
		configRansac.iterations = 500;
		configRansac.inlierThreshold = 1;
		var configTri = new ConfigTrifocal();
		ConfigTrifocalError configError = new ConfigTrifocalError();
		configError.model = ConfigTrifocalError.Model.REPROJECTION_REFINE;
		Ransac<TrifocalTensor, AssociatedTriple> ransac =
				FactoryMultiViewRobust.trifocalRansac(configTri, configError, configRansac);
		ransac.process(associated.toList());
		model.setTo(ransac.getModelParameters());
		return ransac.getMatchSet();
	}
	public static void main( String[] args ) {
		String name = "rock_leaves_";
		GrayU8 gray01 = UtilImageIO.loadImage(UtilIO.pathExample("triple/" + name + "01.jpg"), GrayU8.class);
		GrayU8 gray02 = UtilImageIO.loadImage(UtilIO.pathExample("triple/" + name + "02.jpg"), GrayU8.class);
		GrayU8 gray03 = UtilImageIO.loadImage(UtilIO.pathExample("triple/" + name + "03.jpg"), GrayU8.class);
		// Compute the trifocal tensor which matches features inside these images
		var model = new TrifocalTensor();
		List<AssociatedTriple> inliers = imagesToTrifocal(gray01, gray02, gray03, model);
		// Show inlier associations from RANSAC
		var triplePanel = new AssociatedTriplePanel();
		triplePanel.setImages(
				UtilImageIO.loadImageNotNull(UtilIO.pathExample("triple/" + name + "01.jpg")),
				UtilImageIO.loadImageNotNull(UtilIO.pathExample("triple/" + name + "02.jpg")),
				UtilImageIO.loadImageNotNull(UtilIO.pathExample("triple/" + name + "03.jpg")));
		triplePanel.setAssociation(inliers);
		ShowImages.showWindow(triplePanel, "Inliers", true);
	}
}