docs: public boolean process(List<DMatrixRMaj> cameraMatrices) {
  		if( cameraMatrices.size() == 0 )
  			throw new IllegalArgumentException("Must contain at least 1 matrix");
  
  		// Apply normalization as suggested in the paper, then force the first camera matrix to be [I|0] again
  		CommonOps_DDRM.setIdentity(tmpP);
  		CommonOps_DDRM.mult(Vinv,tmpP,P1);
  		MultiViewOps.projectiveToIdentityH(P1,H);
  
  		// P = inv(V)*P/||P(2,0:2)||
  		this.normalizedP.reset();
  		for (int i = 0; i < cameraMatrices.size(); i++) {
  			DMatrixRMaj A = cameraMatrices.get(i);
  
  			DMatrixRMaj Pi = normalizedP.grow();
  			CommonOps_DDRM.mult(Vinv,A,tmpP);
  			CommonOps_DDRM.mult(tmpP,H,Pi);
  			double a0 = Pi.get(2,0);
  			double a1 = Pi.get(2,1);
  			double a2 = Pi.get(2,2);
  			double scale = Math.sqrt(a0*a0 + a1*a1 + a2*a2);
  			CommonOps_DDRM.scale(1.0/scale,Pi);
  		}
  
  		// Find the best combinations of focal lengths
  		double bestScore;
  		if( sameFocus ) {
  			bestScore = findBestFocusOne(normalizedP.get(0));
  		} else {
  			bestScore = findBestFocusTwo(normalizedP.get(0));
  		}
  
  		// undo normalization
  		CommonOps_DDRM.extract(bestH,0,0,tmp);
  		CommonOps_DDRM.mult(V,tmp, K1);
  		CommonOps_DDRM.insert(K1,bestH,0,0);
  
  		// if it's not at a local minimum it almost definately failed
  		return bestScore != Double.MAX_VALUE && localMinimum;
  	}