3 * Copyright (C) 2008 Verena Kaynig.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation (http://www.gnu.org/licenses/gpl.txt )
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 /* **************************************************************** *
20 * Representation of a non linear transform by explicit polynomial
24 * - make different kernels available
25 * - inverse transform for visualization
26 * - improve image interpolation
27 * - apply and applyInPlace should use precalculated transform?
28 * (What about out of image range pixels?)
30 * Author: Verena Kaynig
31 * Kontakt: verena.kaynig@inf.ethz.ch
33 * **************************************************************** */
35 package mpicbg
.trakem2
.transform
;
37 public class NonLinearCoordinateTransform
implements mpicbg
.trakem2
.transform
.CoordinateTransform
39 protected double[][] beta
= null;
40 protected double[] normMean
= null;
41 protected double[] normVar
= null;
42 protected int dimension
= 0;
43 protected int length
= 0;
44 protected int width
= 0;
45 protected int height
= 0;
47 public NonLinearCoordinateTransform(){};
50 public void init( final String data
) throws NumberFormatException
{
51 final String
[] fields
= data
.split( " " );
54 dimension
= Integer
.parseInt(fields
[c
]); c
++;
55 length
= Integer
.parseInt(fields
[c
]); c
++;
57 beta
= new double[length
][2];
58 normMean
= new double[length
];
59 normVar
= new double[length
];
61 if ( fields
.length
== 4 + 4*length
)
63 for (int i
=0; i
< length
; i
++){
64 beta
[i
][0] = Double
.parseDouble(fields
[c
]); c
++;
65 beta
[i
][1] = Double
.parseDouble(fields
[c
]); c
++;
68 for (int i
=0; i
< length
; i
++){
69 normMean
[i
] = Double
.parseDouble(fields
[c
]); c
++;
72 for (int i
=0; i
< length
; i
++){
73 normVar
[i
] = Double
.parseDouble(fields
[c
]); c
++;
76 width
= Integer
.parseInt(fields
[c
]); c
++;
77 height
= Integer
.parseInt(fields
[c
]); c
++;
80 else throw new NumberFormatException( "Inappropriate parameters for " + this.getClass().getCanonicalName() );
84 public String
toXML(final String indent
){
85 return new StringBuilder(indent
).append("<ict_transform class=\"").append(this.getClass().getCanonicalName()).append("\" data=\"").append(toDataString()).append("\"/>").toString();
89 public String
toDataString(){
91 data
+= Integer
.toString(dimension
) + " ";
92 data
+= Integer
.toString(length
) + " ";
94 for (int i
=0; i
< length
; i
++){
95 data
+= Double
.toString(beta
[i
][0]) + " ";
96 data
+= Double
.toString(beta
[i
][1]) + " ";
99 for (int i
=0; i
< length
; i
++){
100 data
+= Double
.toString(normMean
[i
]) + " ";
103 for (int i
=0; i
< length
; i
++){
104 data
+= Double
.toString(normVar
[i
]) + " ";
106 data
+= Integer
.toString(width
) + " ";
107 data
+= Integer
.toString(height
) + " ";
114 public String
toString(){ return toDataString(); }
117 public float[] apply(final float[] location
) {
119 final double[] position
= { (double) location
[0], (double) location
[1] };
120 final double[] featureVector
= kernelExpand(position
);
121 final double[] newPosition
= multiply(beta
, featureVector
);
123 final float[] newLocation
= new float[2];
124 newLocation
[0] = (float) newPosition
[0];
125 newLocation
[1] = (float) newPosition
[1];
131 public void applyInPlace(final float[] location
) {
132 final double[] position
= { (double) location
[0], (double) location
[1] };
133 final double[] featureVector
= kernelExpand(position
);
134 final double[] newPosition
= multiply(beta
, featureVector
);
136 location
[0] = (float) newPosition
[0];
137 location
[1] = (float) newPosition
[1];
141 static protected double[] multiply(final double beta
[][], final double featureVector
[]) {
142 final double[] result
= { 0.0, 0.0 };
144 if (beta
.length
!= featureVector
.length
)
146 return new double[2];
149 for (int i
= 0; i
< featureVector
.length
; ++i
)
151 result
[0] = result
[0] + featureVector
[i
] * beta
[i
][0];
152 result
[1] = result
[1] + featureVector
[i
] * beta
[i
][1];
158 public double[] kernelExpand( final double position
[] ) {
159 final double expanded
[] = new double[length
];
162 for (int i
= 1; i
<= dimension
; i
++) {
163 for (double j
= i
; j
>= 0; j
--) {
164 final double val
= Math
.pow(position
[0], j
)
165 * Math
.pow(position
[1], i
- j
);
166 expanded
[counter
] = val
;
171 for (int i
= 0; i
< length
- 1; i
++) {
172 expanded
[i
] = expanded
[i
] - normMean
[i
];
173 expanded
[i
] = expanded
[i
] / normVar
[i
];
176 expanded
[length
- 1] = 100;
182 * TODO Make this more efficient
185 public NonLinearCoordinateTransform
copy()
187 final NonLinearCoordinateTransform t
= new NonLinearCoordinateTransform();
188 t
.init(toDataString());