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.linear; 011 012import java.awt.geom.Point2D; 013 014public class AffineMapping extends ProjectiveMapping { 015 016 /** 017 * Creates the identity mapping. 018 */ 019 public AffineMapping() { 020 super(); 021 } 022 023 public AffineMapping ( 024 double a11, double a12, double a13, 025 double a21, double a22, double a23, 026 boolean inv) { 027 super( 028 a11, a12, a13, 029 a21, a22, a23, 030 0, 0, inv); 031 } 032 033 public AffineMapping(LinearMapping lm) { 034 super(lm); 035 a20 = 0; 036 a21 = 0; 037 a22 = 1; 038 } 039 040 public AffineMapping(Point2D A1, Point2D A2, Point2D A3, Point2D B1, Point2D B2, Point2D B3) { 041 super(); 042 double ax1 = A1.getX(), ax2 = A2.getX(), ax3 = A3.getX(); 043 double ay1 = A1.getY(), ay2 = A2.getY(), ay3 = A3.getY(); 044 double bx1 = B1.getX(), bx2 = B2.getX(), bx3 = B3.getX(); 045 double by1 = B1.getY(), by2 = B2.getY(), by3 = B3.getY(); 046 047 double S = ax1*(ay3-ay2) + ax2*(ay1-ay3) + ax3*(ay2-ay1); // TODO: check S for zero value and throw exception! 048 a00 = (ay1*(bx2-bx3) + ay2*(bx3-bx1) + ay3*(bx1-bx2)) / S; 049 a01 = (ax1*(bx3-bx2) + ax2*(bx1-bx3) + ax3*(bx2-bx1)) / S; 050 a10 = (ay1*(by2-by3) + ay2*(by3-by1) + ay3*(by1-by2)) / S; 051 a11 = (ax1*(by3-by2) + ax2*(by1-by3) + ax3*(by2-by1)) / S; 052 a02 = 053 (ax1*(ay3*bx2-ay2*bx3) + ax2*(ay1*bx3-ay3*bx1) + ax3*(ay2*bx1-ay1*bx2)) / S; 054 a12 = 055 (ax1*(ay3*by2-ay2*by3) + ax2*(ay1*by3-ay3*by1) + ax3*(ay2*by1-ay1*by2)) / S; 056 } 057 058 public AffineMapping(Point2D[] A, Point2D[] B) { 059 this(A[0], A[1], A[2], B[0], B[1], B[2]); 060 } 061 062 public AffineMapping concat(AffineMapping B) { // TODO: more general arguments? 063 AffineMapping A = new AffineMapping(this); 064 A.concatDestructive(B); 065 return A; 066 } 067 068 @Override 069 public AffineMapping invert() { 070 AffineMapping pm = new AffineMapping(this); 071 pm.invertDestructive(); 072 return pm; 073 } 074 075 @Override 076 public AffineMapping duplicate() { 077 return (AffineMapping) this.clone(); 078 } 079 080 // warp parameter support (used in Lucas-Kanade-matcher) -------------------------- 081 082 @Override 083 public int getWarpParameterCount() { 084 return 6; 085 } 086 087 @Override 088 public double[] getWarpParameters() { 089 double[] p = new double[] { 090 a00 - 1, 091 a01, 092 a10, 093 a11 - 1, 094 a02, 095 a12 }; 096 return p; 097 } 098 099 @Override 100 public void setWarpParameters(double[] p) { 101 a00 = p[0] + 1; 102 a01 = p[1]; 103 a10 = p[2]; 104 a11 = p[3] + 1; 105 a02 = p[4]; 106 a12 = p[5]; 107 } 108 109 @Override 110 public double[][] getWarpJacobian(double[] xy) { 111 final double x = xy[0]; 112 final double y = xy[1]; 113 return new double[][] 114 {{x, y, 0, 0, 1, 0}, 115 {0, 0, x, y, 0, 1}}; 116 } 117 118} 119 120 121 122