All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boofcv.struct.calib.CameraUniversalOmni Maven / Gradle / Ivy

Go to download

BoofCV is an open source Java library for real-time computer vision and robotics applications.

There is a newer version: 1.1.7
Show newest version
/*
 * Copyright (c) 2023, 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.struct.calib;

import org.ejml.FancyPrint;

import static boofcv.struct.calib.CameraPinholeBrown.toStringArray;

/**
 * 

Camera model for omnidirectional single viewpoint sensors [1]. Designed to work with parabolic, * hyperbolic, wide-angle, and spherical sensors. The FOV that this model can describe is dependent * on the mirror parameter ξ. See [1] for details, but for example ξ=0 is a pinhole camera, * ξ=1 can describe fisheye cameras, but a value larger than 1 is limited to 180 degrees due to * multiple points on the unit sphere intersecting the same projection line. This is the same model as * {@link CameraPinholeBrown} except that there is a change in reference frame which allows it to model wider FOV.

* * Forward Projection *
    *
  1. Given a 3D point X=(x,y,z) in camera (mirror) coordinates
  2. *
  3. Project onto unit sphere Xs=X/||X||
  4. *
  5. Change reference frame X'=(x',y',z') = (xs,ys,zs + ξ)
  6. *
  7. Compute normalized image coordinates (u,v)=(x'/z', y'/z')
  8. *
  9. Apply radial and tangential distortion (see below)
  10. *
  11. Convert into pixels p = K*distort([u;v])
  12. *
* *
 * Camera Projection
 *     [ fx  skew cx ]
 * K = [  0   fy  cy ]
 *     [  0    0   1 ]
 * 
* *

* Radial and Tangential Distortion:
* xd = xn + xn[k1 r2 + ... + kn r2n]
* dxu = [ 2t1 u v + t2(r2 + 2u2)]
* dxv = [ t1(r2 + 2v2) + 2 t2 u v]
*
* r2 = u2 + v2
* where xd is the distorted normalized image coordinates, xn=(u,v) is * undistorted normalized image coordinates. *

* *

NOTE: The only difference from [1] is that skew is used instead of fx*alpha.

*

* [1] Christopher Mei, and Patrick Rives. "Single view point omnidirectional camera calibration * from planar grids." ICRA 2007. *

* * @author Peter Abeles */ @SuppressWarnings({"NullAway.Init"}) public class CameraUniversalOmni extends CameraPinhole { /** Mirror offset distance. ξ */ public double mirrorOffset; /** radial distortion parameters: k1,...,kn */ public double[] radial; /** tangential distortion parameters */ public double t1, t2; /** * Constructor for specifying number of radial distortion * * @param numRadial Number of radial distortion parameters */ public CameraUniversalOmni( int numRadial ) { this.radial = new double[numRadial]; } /** * Copy constructor * * @param original Model which is to be copied */ public CameraUniversalOmni( CameraUniversalOmni original ) { setTo(original); } public CameraUniversalOmni fsetMirror( double mirrorOffset ) { this.mirrorOffset = mirrorOffset; return this; } public CameraUniversalOmni fsetRadial( double... radial ) { this.radial = radial.clone(); return this; } public CameraUniversalOmni fsetTangential( double t1, double t2 ) { this.t1 = t1; this.t2 = t2; return this; } /** * Assigns this model to be identical to the passed in model * * @param original Model which is to be copied */ public void setTo( CameraUniversalOmni original ) { super.setTo(original); this.mirrorOffset = original.mirrorOffset; if (radial.length != original.radial.length) radial = new double[original.radial.length]; System.arraycopy(original.radial, 0, radial, 0, radial.length); this.t1 = original.t1; this.t2 = original.t2; } @Override public T createLike() { return (T)new CameraUniversalOmni(radial.length); } public double[] getRadial() { return radial; } public void setRadial( double[] radial ) { this.radial = radial; } public double getT1() { return t1; } public void setT1( double t1 ) { this.t1 = t1; } public double getT2() { return t2; } public void setT2( double t2 ) { this.t2 = t2; } public double getMirrorOffset() { return mirrorOffset; } public void setMirrorOffset( double mirrorOffset ) { this.mirrorOffset = mirrorOffset; } @Override public String toString() { FancyPrint fp = new FancyPrint(); String txt = "CameraUniversalOmni{" + "width=" + width + ", height=" + height + ", fx=" + fx + ", fy=" + fy + ", skew=" + skew + ", cx=" + cx + ", cy=" + cy + ", mirrorOffset=" + fp.s(mirrorOffset); txt += toStringArray(fp, "r", radial); if (t1 != 0 || t2 != 0) { txt += ", t1=" + fp.s(t1) + " t2=" + fp.s(t2); } txt += '}'; return txt; } @Override public void print() { super.print(); if (radial != null) { for (int i = 0; i < radial.length; i++) { System.out.printf("radial[%d] = %6.2e\n", i, radial[i]); } } else { System.out.println("No radial"); } if (t1 != 0 && t2 != 0) System.out.printf("tangential = ( %6.2e , %6.2e)\n", t1, t2); else { System.out.println("No tangential"); } System.out.printf("mirror offset = %7.3f", mirrorOffset); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy