001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit http://imagingbook.com for additional details. 008 *******************************************************************************/ 009 010package imagingbook.pub.geometry.mappings.nonlinear; 011 012import imagingbook.lib.math.Matrix; 013import imagingbook.pub.geometry.mappings.Mapping; 014 015import java.awt.geom.Point2D; 016 017 018/* 019 * 2007: Changed to use the JAMA numerical math package 020 * (http://math.nist.gov/javanumerics/jama/) instead of JAMPACK. 021 * 2013: changed to use methods from the local matrix library 022 * (based on Apache Common Maths) to solve linear systems of 023 * equations. 024 */ 025 026public class BilinearMapping extends Mapping { 027 double a1, a2, a3, a4; 028 double b1, b2, b3, b4; 029 030 BilinearMapping( 031 double a1, double a2, double a3, double a4, 032 double b1, double b2, double b3, double b4, 033 boolean isInverse) { 034 this.a1 = a1; this.a2 = a2; this.a3 = a3; this.a4 = a4; 035 this.b1 = b1; this.b2 = b2; this.b3 = b3; this.b4 = b4; 036 this.isInverseFlag = isInverse; 037 } 038 039 //map between arbitrary quadrilaterals 040 public static BilinearMapping makeInverseMapping( 041 Point2D P1, Point2D P2, Point2D P3, Point2D P4, // source quad 042 Point2D Q1, Point2D Q2, Point2D Q3, Point2D Q4) // target quad 043 { 044 //define column vectors X, Y 045 double[] x = {Q1.getX(), Q2.getX(), Q3.getX(), Q4.getX()}; 046 double[] y = {Q1.getY(), Q2.getY(), Q3.getY(), Q4.getY()}; 047 048 //define matrix M 049 double[][] M = new double[][] 050 {{P1.getX(), P1.getY(), P1.getX() * P1.getY(), 1}, 051 {P2.getX(), P2.getY(), P2.getX() * P2.getY(), 1}, 052 {P3.getX(), P3.getY(), P3.getX() * P3.getY(), 1}, 053 {P4.getX(), P4.getY(), P4.getX() * P4.getY(), 1}}; 054 055 double[] a = Matrix.solve(M, x); // solve x = M * a = x (a is unknown) 056 double[] b = Matrix.solve(M, y); // solve y = M * b = y (b is unknown) 057 058 double a1 = a[0]; double b1 = b[0]; 059 double a2 = a[1]; double b2 = b[1]; 060 double a3 = a[2]; double b3 = b[2]; 061 double a4 = a[3]; double b4 = b[3]; 062 063 return new BilinearMapping(a1, a2, a3, a4, b1, b2, b3, b4, true); 064 } 065 066 public double[] applyTo (double[] xy){ 067 double x0 = xy[0]; 068 double y0 = xy[1]; 069 double x1 = a1 * x0 + a2 * y0 + a3 * x0 * y0 + a4; 070 double y1 = b1 * x0 + b2 * y0 + b3 * x0 * y0 + b4; 071 //pnt.setLocation(x1, y1); 072 return new double[] {x1, y1}; 073 } 074 075// public Point2D applyTo (Point2D pnt){ 076// double x0 = pnt.getX(); 077// double y0 = pnt.getY(); 078// double x1 = a1 * x0 + a2 * y0 + a3 * x0 * y0 + a4; 079// double y1 = b1 * x0 + b2 * y0 + b3 * x0 * y0 + b4; 080// //pnt.setLocation(x1, y1); 081// return new Point2D.Double(x1, y1); 082// } 083 084 public String toString() { 085 return 086 "A=(" + a1 + "," + a2 + "," + a3 + "," + a4 + ")" + 087 " / " + 088 "B=(" + b1 + "," + b2 + "," + b3 + "," + b4 + ")" ; 089 } 090 091}