/*
 * 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.struct.point.Point2D_F64;
import georegression.struct.point.Point3D_F64;
import georegression.struct.se.Se3_F64;
import georegression.transform.se.SePointOps_F64;
import org.ddogleg.optimization.functions.FunctionNtoM;

import java.util.ArrayList;
import java.util.List;

/**
 * Function for performing non-linear optimization on the Zhang99 calibration parameters.
 *
 * @author Peter Abeles
 */
public class Zhang99OptimizationFunction implements FunctionNtoM {

	private int N,M;
	
	// description of the calibration grid
	private List grid = new ArrayList();
	// optimization parameters
	private Zhang99ParamAll param;

	// variables for storing intermediate results
	private Se3_F64 se = new Se3_F64();

	private Point3D_F64 cameraPt = new Point3D_F64();
	private Point2D_F64 normPt = new Point2D_F64();

	// observations
	private List observations;

	/**
	 * Configurations the optimization function.
	 *
	 * @param param Storage for calibration parameters. Effectively specifies the number of target views
	 * and radial terms
	 * @param grid Location of points on the calibration grid.  z=0
	 * @param observations calibration point observation pixel coordinates
	 */
	public Zhang99OptimizationFunction(Zhang99ParamAll param,
									   List grid,
									   List observations) {
		if( param.views.length != observations.size() )
			throw new IllegalArgumentException("For each view there should be one observation");

		this.param = param;
		this.observations = observations;

		for( Point2D_F64 p : grid ) {
			this.grid.add( new Point3D_F64(p.x,p.y,0) );
		}

		N = param.numParameters();
		M = CalibrationPlanarGridZhang99.totalPoints(observations)*2;
	}

	@Override
	public int getNumOfInputsN() {
		return N;
	}

	@Override
	public int getNumOfOutputsM() {
		return M;
	}

	@Override
	public void process(double[] input, double[] output) {
		param.setFromParam(input);

		process(param,output);
	}

	public void process( Zhang99ParamAll param , double []residuals ) {
		int index = 0;
		for( int indexView = 0; indexView < param.views.length; indexView++ ) {

			Zhang99ParamAll.View v = param.views[indexView];

			ConvertRotation3D_F64.rodriguesToMatrix(v.rotation,se.getR());
			se.T = v.T;

			CalibrationObservation viewSet = observations.get(indexView);

			for( int i = 0; i < viewSet.size(); i++ ) {

				int gridIndex = viewSet.get(i).index;
				Point2D_F64 obs = viewSet.get(i).pixel;

				// Put the point in the camera's reference frame
				SePointOps_F64.transform(se,grid.get(gridIndex), cameraPt);

				// normalized image coordinates
				normPt.x = cameraPt.x/ cameraPt.z;
				normPt.y = cameraPt.y/ cameraPt.z;

				// apply distortion
				CalibrationPlanarGridZhang99.applyDistortion(normPt, param.radial, param.t1, param.t2);

				// convert to pixel coordinates
				double x = param.a * normPt.x + param.c * normPt.y + param.x0;
				double y = param.b * normPt.y + param.y0;

				residuals[index++] = x-obs.x;
				residuals[index++] = y-obs.y;
			}
		}
	}
}

 

Ads help maintain this website.