Given a set of homographies computed from a sequence of images that observe the same
plane it estimates the camera's calibration.

@param homographies Homographies computed from observations of the calibration grid.
500524
public void process( List<DMatrixRMaj> homographies ) {
		if( assumeZeroSkew ) {
			if( homographies.size() < 2 )
				throw new IllegalArgumentException("At least two homographies are required. Found "+homographies.size());
		} else if( homographies.size() < 3 ) {
			throw new IllegalArgumentException("At least three homographies are required. Found "+homographies.size());
		}

		if( assumeZeroSkew ) {
			setupA_NoSkew(homographies);
			if( !solverNull.process(A,1,b) )
				throw new RuntimeException("SVD failed");
			computeParam_ZeroSkew();
		} else {
			setupA(homographies);
			if( !solverNull.process(A,1,b) )
				throw new RuntimeException("SVD failed");
			computeParam();
		}
		if(MatrixFeatures_DDRM.hasUncountable(K)) {
			throw new RuntimeException("Failed!");
		}
	}
714983
void triangulateStereoEdges(Motion edge ) {
		View viewA = edge.viewSrc;
		View viewB = edge.viewDst;

		triangulationError.configure(viewA.camera.pinhole,viewB.camera.pinhole);

		for (int i = 0; i < edge.associated.size(); i++) {
			AssociatedIndex f = edge.associated.get(i);

			Point2D_F64 normA = viewA.observationNorm.get(f.src);
			Point2D_F64 normB = viewB.observationNorm.get(f.dst);

			double angle = triangulationAngle(normA,normB,edge.a_to_b);
			if( angle < TRIANGULATE_MIN_ANGLE )
				continue;

			Feature3D feature3D = new Feature3D();

			if( !triangulate.triangulate(normA,normB,edge.a_to_b,feature3D.worldPt) ) {
				continue;
			}

			// must be in front of the camera
			if( feature3D.worldPt.z <= 0 )
				continue;

			// can't have an excessively large reprojection error either
			double error = triangulationError.process(normA,normB,edge.a_to_b,feature3D.worldPt);
			if( error > maxPixelError*maxPixelError )
				continue;

			feature3D.views.add(viewA);
			feature3D.views.add(viewB);
			feature3D.obsIdx.add(f.src);
			feature3D.obsIdx.add(f.dst);
			feature3D.triangulationAngle = angle;

			edge.stereoTriangulations.add(feature3D);
		}
	}
646328
@Override
	public boolean process(PairwiseImageGraph pairwiseGraph ) {
		this.graph = new MetricSceneGraph(pairwiseGraph);
		for (int i = 0; i < graph.edges.size(); i++) {
			decomposeEssential(graph.edges.get(i));
		}

		declareModelFitting();

		for (int i = 0; i < graph.edges.size(); i++) {
			Motion e = graph.edges.get(i);
			e.triangulationAngle = medianTriangulationAngle(e);
		}

		if( verbose != null )
			verbose.println("Selecting root");
		// Select the view which will act as the origin
		View origin = selectOriginNode();
		// Select the motion which will define the coordinate system
		Motion baseMotion = selectCoordinateBase( origin );

		this.graph.sanityCheck();

		if( verbose != null )
			verbose.println("Stereo triangulation");
		// Triangulate features in all motions which exceed a certain angle
		for (int i = 0; i < graph.edges.size() && !stopRequested ; i++) {
			Motion e = graph.edges.get(i);
			if( e.triangulationAngle > Math.PI/10 || e == baseMotion) {
				triangulateStereoEdges(e);
				if( verbose != null ) {
					int a = e.viewSrc.index;
					int b = e.viewDst.index;
					verbose.println("   Edge[" + i + "] "+a+"->"+b+"  feat3D="+e.stereoTriangulations.size());
				}
			}
		}
		if( stopRequested )
			return false;

		if( verbose != null )
			verbose.println("Defining the coordinate system");

		// Using the selecting coordinate frames and triangulated points define the coordinate system
		defineCoordinateSystem(origin, baseMotion);
		if( stopRequested )
			return false;

		if( verbose != null )
			verbose.println("Estimate all features");

		// Now estimate all the other view locations and 3D features
		estimateAllFeatures(origin, baseMotion.destination(origin));
		if( stopRequested )
			return false;

		// Convert the graph into the output format
		convertToOutput(origin);

		return viewsAdded.size() >= 2;
	}
388395
public void initialize( int totalCameras , int totalViews , int totalPoints , int totalRigid ) {
		cameras = new Camera[totalCameras];
		views = new View[totalViews];
		points = new Point[totalPoints];
		rigids = new Rigid[totalRigid];

		for (int i = 0; i < cameras.length; i++) {
			cameras[i] = new Camera();
		}
		for (int i = 0; i < views.length; i++) {
			views[i] = new View();
		}
		for (int i = 0; i < points.length; i++) {
			points[i] = new Point(pointSize);
		}

		for (int i = 0; i < rigids.length; i++) {
			rigids[i] = new Rigid();
		}
		// forget old assignments
		lookupRigid = null;
	}
631290
public void setEdges(java.util.Collection<Edge> edges) {
        if (edges == null) {
            this.edges = null;
            return;
        }

        this.edges = new java.util.ArrayList<Edge>(edges);
    }
1264804
public void setProjectionMatrix(float x1, float y1, float z1, float w1,
            float x2, float y2, float z2, float w2, float x3, float y3,
            float z3, float w3, float x4, float y4, float z4, float w4) {
        NativeCustomCamera.setProjectionMatrix(getNative(), x1, y1, z1, w1, x2,
                y2, z2, w2, x3, y3, z3, w3, x4, y4, z4, w4);
    }
197535
public static void computeCameraControl(double beta[],
											List<Point3D_F64> nullPts[],
											FastQueue<Point3D_F64> cameraPts ,
											int numControl )
	{
		cameraPts.reset();
		for( int i = 0; i < numControl; i++ ) {
			cameraPts.grow().set(0,0,0);
		}

		for( int i = 0; i < numControl; i++ ) {
			double b = beta[i];
//			System.out.printf("%7.3f ", b);

			for( int j = 0; j < numControl; j++ ) {
				Point3D_F64 s = cameraPts.get(j);
				Point3D_F64 p = nullPts[i].get(j);
				s.x += b*p.x;
				s.y += b*p.y;
				s.z += b*p.z;
			}
		}
	}
849942
protected void setOffsetPixels(float offsetPixels) {
		final int oldOffset = (int) mOffsetPixels;
		final int newOffset = (int) offsetPixels;

		mOffsetPixels = offsetPixels;

		if (newOffset != oldOffset) {
			onOffsetPixelsChanged(newOffset);
			mSwipeBackViewVisible = newOffset != 0;

			// Notify any attached listeners of the current open ratio
			final float openRatio = ((float) Math.abs(newOffset)) / mSwipeBackViewSize;
			dispatchOnDrawerSlide(openRatio, newOffset);
		}
	}
975884
public void setObservations( List<Point2D_F64> observations,
								 List<DMatrixRMaj> essential ) {
		this.observations = observations;
		this.essential = essential;
	}
808557
public void setGeometries(Geometry[] geometries) {
		List<Coordinate> coordinates = getCoordinates(geometries);
		sortedX = sortX(coordinates);
		sortedY = sortY(coordinates);
	}
306688
public void setGeoMatchSets(java.util.Collection<GeoMatchSetSummary> geoMatchSets) {
        if (geoMatchSets == null) {
            this.geoMatchSets = null;
            return;
        }

        this.geoMatchSets = new java.util.ArrayList<GeoMatchSetSummary>(geoMatchSets);
    }
1349111
private void createHoughPixels( double[][][] houghValues, byte houghPixels[] ) {
        double d = -1D;
        for( int j = 0; j < height; j++ ) {
            for( int k = 0; k < width; k++ ) {
                if (houghValues[k][j][0] > d) {
                    d = houghValues[k][j][0];
                }
            }
        }
        for( int l = 0; l < height; l++ ) {
            for( int i = 0; i < width; i++ ) {
                houghPixels[i + l * width] = (byte) Math.round((houghValues[i][l][0] * 255D) / d);
            }
        }
    }
1053222
void filterPointsOnPlaneAtInfinity(List<DMatrixRMaj> homographies_view1_to_view0,
											   List<List<PointIndex2D_F64>> observations,
											   int totalFeatures ) {
		filtered.clear();
		for (int viewIdx = 0; viewIdx < homographies_view1_to_view0.size(); viewIdx++) {
			List<PointIndex2D_F64> filter = new ArrayList<>();
			filtered.add(filter);
			DMatrixRMaj H = homographies_view1_to_view0.get(viewIdx);

			List<PointIndex2D_F64> obs = observations.get(viewIdx);
			for (int i = 0; i < obs.size(); i++) {
				PointIndex2D_F64 p = obs.get(i);

				if( p.index < 0 || p.index >= totalFeatures)
					throw new IllegalArgumentException("Feature index outside of bounds. Must be from 0 to "+(totalFeatures-1));

				GeometryMath_F64.mult(H,p,tmp);
				// Homogenous coordinates are scale invariant. A scale
				// needs to be picked for consistency. I picked the largest x or y value
				double m = Math.max(Math.abs(tmp.x),Math.abs(tmp.y));
				 if( m == 0 ) m = 1;
				tmp.z /= m;

				// See if it's zero or almost zero, meaning it's on the plane at infinity
				if( Math.abs(tmp.z) > infinityThreshold ) {
					filter.add(p);
				}
			}
		}
	}
1316494
public void setDepthsFrom3D(int view , List<Point3D_F64> locations ) {
		if( locations.size() != pixels.numCols )
			throw new IllegalArgumentException("Pixel count must be constant and match "+pixels.numCols);

		int N = depths.numCols;
		for (int i = 0; i < N; i++) {
			depths.set(view,i, locations.get(i).z );
		}
	}
110747
public void setMeshes(java.util.Collection<MeshRef> meshes) {
        if (meshes == null) {
            this.meshes = null;
            return;
        }

        this.meshes = new java.util.ArrayList<MeshRef>(meshes);
    }
1073393
public boolean estimate(List<Homography2D_F64> viewsI_to_view0 , CameraPinhole calibration ) {
		singular = false;
		int N = viewsI_to_view0.size();

		ensureDeterminantOfOne(viewsI_to_view0);

		A.reshape(N*6,6);

		for (int i = 0; i < N; i++) {
			add(i,viewsI_to_view0.get(i),A);
		}

		// Compute the SVD for its null space
		if( !svd.decompose(A)) {
			return false;
		}

		DMatrixRMaj nv = new DMatrixRMaj(6,1);
		SingularOps_DDRM.nullVector(svd,true,nv);

		if( !extractCalibration(nv,calibration) )
			return false;

		// determine if the solution is good by looking at two smallest singular values
		// If there isn't a steep drop it either isn't singular or more there is more than 1 singular value
		double sv[] = svd.getSingularValues();
		Arrays.sort(sv);
		if( singularThreshold*sv[1] <= sv[0] )  {
			return false;
		}
		return true;
	}
446161
private void setupA( List<DMatrixRMaj> homographies ) {
		A.reshape(2*homographies.size(),6, false);

		DMatrixRMaj h1 = new DMatrixRMaj(3,1);
		DMatrixRMaj h2 = new DMatrixRMaj(3,1);

		DMatrixRMaj v12 = new DMatrixRMaj(1,6);
		DMatrixRMaj v11 = new DMatrixRMaj(1,6);
		DMatrixRMaj v22 = new DMatrixRMaj(1,6);

		DMatrixRMaj v11m22 = new DMatrixRMaj(1,6);

		for( int i = 0; i < homographies.size(); i++ ) {
			DMatrixRMaj H = homographies.get(i);

			CommonOps_DDRM.extract(H,0,3,0,1,h1,0,0);
			CommonOps_DDRM.extract(H,0,3,1,2,h2,0,0);

			// normalize H by the max value to reduce numerical error when computing A
			// several numbers are multiplied against each other and could become quite large/small
			double max1 = CommonOps_DDRM.elementMaxAbs(h1);
			double max2 = CommonOps_DDRM.elementMaxAbs(h2);
			double max = Math.max(max1,max2);

			CommonOps_DDRM.divide(h1,max);
			CommonOps_DDRM.divide(h2,max);

			// compute elements of A
			computeV(h1, h2, v12);
			computeV(h1, h1, v11);
			computeV(h2, h2, v22);

			CommonOps_DDRM.subtract(v11, v22, v11m22);

			CommonOps_DDRM.insert( v12    , A, i*2   , 0);
			CommonOps_DDRM.insert( v11m22 , A, i*2+1 , 0);
		}
	}