/*
* Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved.
*
* This file is part of BoofCV (http://boofcv.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package boofcv.alg.geo.calibration;
import georegression.geometry.ConvertRotation3D_F64;
import georegression.geometry.UtilVector3D_F64;
import georegression.struct.point.Vector3D_F64;
import georegression.struct.se.Se3_F64;
import org.ejml.data.DenseMatrix64F;
import org.ejml.ops.CommonOps;
import org.ejml.ops.NormOps;
import org.ejml.ops.SpecializedOps;
/**
*
* Decomposes a homography into rigid body motion (rotation and translation) utilizing specific
* assumptions made inside the Zhang99 paper [1].
*
*
*
* Let K and R be the calibration matrix and rotation matrix.
* R = [ r1 , r1 , r1 ]
* ri is the ith column in R.
* Then compute R using the column of the homography matrix:
* r1 = λ*inv(K)*h1
* r2 = λ*inv(K)*h2
* r3 = cross(r1,r2)
* t = λ*inv(K)*h3
* t is the translation vector. The R computed above is only approximate and needs to be turned into
* a real rotation matrix.
*
*
*
* [1] Zhengyou Zhang, "Flexible Camera Calibration By Viewing a Plane From Unknown Orientations,",
* International Conference on Computer Vision (ICCV'99), Corfu, Greece, pages 666-673, September 1999.
*
*
* @author Peter Abeles
*/
public class Zhang99DecomposeHomography {
// Rows in rotation matrix
DenseMatrix64F r1 = new DenseMatrix64F(3,1);
DenseMatrix64F r2 = new DenseMatrix64F(3,1);
// storage for translation vector
DenseMatrix64F t = new DenseMatrix64F(3,1);
DenseMatrix64F temp = new DenseMatrix64F(3,1);
// storage for rotation matrix
DenseMatrix64F R = new DenseMatrix64F(3,3);
// calibration matrix and its inverse
DenseMatrix64F K;
DenseMatrix64F K_inv = new DenseMatrix64F(3,3);
/**
* Specifies the calibration matrix.
*
* @param K upper triangular calibration matrix.
*/
public void setCalibrationMatrix( DenseMatrix64F K ) {
this.K = K;
CommonOps.invert(K,K_inv);
}
/**
* Compute the rigid body motion that composes the homography matrix H. It is assumed
* that H was computed using {@link Zhang99ComputeTargetHomography}.
*
* @param H homography matrix.
* @return Found camera motion.
*/
public Se3_F64 decompose( DenseMatrix64F H )
{
// step through each calibration grid and compute its parameters
DenseMatrix64F h[] = SpecializedOps.splitIntoVectors(H, true);
// lambda = 1/norm(inv(K)*h1) or 1/norm(inv(K)*h2)
// use the average to attempt to reduce error
CommonOps.mult(K_inv,h[0],temp);
double lambda = NormOps.normF(temp);
CommonOps.mult(K_inv,h[1],temp);
lambda += NormOps.normF(temp);
lambda = 2.0/lambda;
// compute the column in the rotation matrix
CommonOps.mult(lambda,K_inv,h[0],r1);
CommonOps.mult(lambda,K_inv,h[1],r2);
CommonOps.mult(lambda,K_inv,h[2],t);
Vector3D_F64 v1 = UtilVector3D_F64.convert(r1);
Vector3D_F64 v2 = UtilVector3D_F64.convert(r2);
Vector3D_F64 v3 = v1.cross(v2);
UtilVector3D_F64.createMatrix(R, v1, v2, v3);
Se3_F64 ret = new Se3_F64();
// the R matrix is probably not a real rotation matrix. So find
// the closest real rotation matrix
ConvertRotation3D_F64.approximateRotationMatrix(R,ret.getR());
ret.getT().set(t.data[0],t.data[1],t.data[2]);
return ret;
}
}
Ads help maintain this website.