docs: public void process(CameraPinholeBrown intrinsic , List<BufferedImage> colorImages ) {
  
  		DetectDescribePoint detDesc = FactoryDetectDescribe.surfStable(null, null, null, GrayF32.class);
  		ScoreAssociation scorer = FactoryAssociation.defaultScore(detDesc.getDescriptionType());
  		AssociateDescription<TupleDesc> associate =
  				FactoryAssociation.greedy(scorer, Double.MAX_VALUE, true);
  		PairwiseImageMatching<GrayF32> imageMatching = new PairwiseImageMatching<>(detDesc,associate);
  		imageMatching.setVerbose(System.out,0);
  
  		String cameraName = "camera";
  		imageMatching.addCamera(cameraName, LensDistortionFactory.narrow(intrinsic).undistort_F64(true,false),intrinsic);
  
  		for (int i = 0; i < colorImages.size(); i++) {
  			BufferedImage colorImage = colorImages.get(i);
  			if( colorImage.getWidth() != intrinsic.width || colorImage.getHeight() != intrinsic.height )
  				throw new RuntimeException("Looks like you tried to hack this example and run it on random images. Please RTFM");
  			GrayF32 image = ConvertBufferedImage.convertFrom(colorImage, (GrayF32) null);
  			imageMatching.addImage(image,cameraName);
  		}
  
  		if( !imageMatching.process() ) {
  			throw new RuntimeException("Failed to match images! total="+colorImages.size());
  		}
  
  		EstimateSceneCalibrated estimateScene = new EstimateSceneCalibrated();
  		estimateScene.setVerbose(System.out,0);
  
  		if( !estimateScene.process(imageMatching.getGraph()))
  			throw new RuntimeException("Scene estimation failed");
  
  		// get the results
  		SceneStructureMetric structure = estimateScene.getSceneStructure();
  		SceneObservations observations = estimateScene.getObservations();
  
  		// Configure bundle adjustment
  		ConfigLevenbergMarquardt configLM = new ConfigLevenbergMarquardt();
  		configLM.dampeningInitial = 1e-12;
  		configLM.hessianScaling = true;
  		ConfigBundleAdjustment configSBA = new ConfigBundleAdjustment();
  		configSBA.configOptimizer = configLM;
  
  		BundleAdjustment<SceneStructureMetric> sba = FactoryMultiView.bundleSparseMetric(configSBA);
  		sba.configure(1e-10,1e-10,100);
  		sba.setVerbose(System.out,0);
  
  		// Scale to improve numerical accuracy
  		ScaleSceneStructure bundleScale = new ScaleSceneStructure();
  
  		PruneStructureFromSceneMetric pruner = new PruneStructureFromSceneMetric(structure,observations);
  
  		// Requiring 3 views per point reduces the number of outliers by a lot but also removes
  		// many valid points
  		pruner.prunePoints(3);
  
  		// Optimize the results
  		int pruneCycles=5;
  		for (int i = 0; i < pruneCycles; i++) {
  			System.out.println("BA + Prune iteration = "+i+"  points="+structure.points.length+"  obs="+observations.getObservationCount());
  			bundleScale.applyScale(structure,observations);
  			sba.setParameters(structure,observations);
  			if( !sba.optimize(structure) ) {
  				throw new RuntimeException("Bundle adjustment failed!");
  			}
  
  			bundleScale.undoScale(structure,observations);
  
  			if( i == pruneCycles-1 )
  				break;
  
  			System.out.println("Pruning....");
  			pruner.pruneObservationsByErrorRank(0.97);  // Prune outlier observations
  			pruner.prunePoints(3,0.4);            // Prune stray points in 3D space
  			pruner.prunePoints(2);                           // Prune invalid points
  			pruner.pruneViews(10);                           // Prune views with too few observations
  		}
  
  		visualizeResults(structure,colorImages);
  		System.out.println("Done!");
  	}