001/******************************************************************************* 002 * Permission to use and distribute this software is granted under the BSD 2-Clause 003 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 004 * Copyright (c) 2016-2023 Wilhelm Burger. All rights reserved. 005 * Visit https://imagingbook.com for additional details. 006 ******************************************************************************/ 007package imagingbook.calibration.zhang; 008 009import imagingbook.calibration.zhang.util.MathUtil; 010import imagingbook.common.geometry.basic.Pnt2d; 011import imagingbook.common.geometry.basic.Pnt2d.PntDouble; 012import imagingbook.common.geometry.mappings.Mapping2D; 013import org.apache.commons.math3.linear.RealMatrix; 014 015/** 016 * <p> 017 * This class represents a special geometric mapping for rectifying (i.e., removing the lens distortion from) an image, 018 * given the associated camera parameters. The transformation maps any position {@code x'} in the rectified image to the 019 * corresponding position {@code x} in the original (distorted) image. The mapping is implicitly inverted, i.e., maps 020 * target to source image coordinates. 021 * </p> 022 * <p> 023 * Typically usage (by target-to-source-mapping): 024 * </p> 025 * <pre> 026 * ImageProcessor original = ... ; // the distorted image 027 * ImageProcessor rectified = ... ; // the (new) rectified image 028 * mapping.applyTo(original, rectified, InterpolationMethod.Bicubic); 029 * </pre> 030 */ 031public class RectificationMapping implements Mapping2D { 032 private final Camera cam; 033 private final RealMatrix Ai; // inverse of the intrinsic camera matrix (2 x 3) 034 035 public RectificationMapping (Camera cam) { 036// this.isInverseFlag = true; // maps target -> source 037 this.cam = cam; 038 this.Ai = cam.getInverseA(); 039 } 040 041 @Override 042 public Pnt2d applyTo(Pnt2d uv) { 043 // (u,v) is an observed sensor point 044 // apply the inverse camera mapping to get the normalized (x,y) point: 045 double[] xy = Ai.operate(MathUtil.toHomogeneous(uv.toDoubleArray())); 046 // apply the camera's radial lens distortion in the normalized plane: 047 double[] xyd = cam.warp(xy); 048 // apply the (forward) camera mapping to get the undistorted sensor point (u',v'): 049 return PntDouble.from(cam.mapToSensorPlane(xyd)); 050 } 051 052}