Fixed potential native memory leak with ARGB BufferedImages.
[trakem2.git] / SIFT_Movie.java
blob7410a7cc776aa973216074e2558ad27a53145a77
1 //package mpi.fruitfly.registration;
3 import mpi.fruitfly.general.*;
4 import mpi.fruitfly.math.datastructures.*;
5 import mpi.fruitfly.math.*;
6 import mpi.fruitfly.registration.FloatArray2DSIFT;
7 import mpi.fruitfly.registration.FloatArray2DScaleOctave;
8 import mpi.fruitfly.registration.FloatArray2DScaleOctaveDoGDetector;
9 import mpi.fruitfly.registration.ImageFilter;
10 import mpi.fruitfly.registration.Feature;
12 import ij.plugin.*;
13 import ij.gui.*;
14 import ij.*;
15 import ij.process.*;
17 import java.util.Collections;
18 import java.util.Vector;
19 import java.awt.Color;
20 import java.awt.Polygon;
21 import java.awt.TextField;
22 import java.awt.event.KeyEvent;
23 import java.awt.event.KeyListener;
26 public class SIFT_Movie implements PlugIn, KeyListener
28 // steps
29 private static int steps = 3;
30 // initial sigma
31 private static float initial_sigma = 1.6f;
32 // feature descriptor size
33 private static int fdsize = 8;
34 // feature descriptor orientation bins
35 private static int fdbins = 8;
36 // size restrictions for scale octaves, use octaves < max_size and > min_size only
37 private static int min_size = 64;
38 private static int max_size = 1024;
40 /**
41 * Set true to double the size of the image by linear interpolation to
42 * ( with * 2 + 1 ) * ( height * 2 + 1 ). Thus we can start identifying
43 * DoG extrema with $\sigma = INITIAL_SIGMA / 2$ like proposed by
44 * \citet{Lowe04}.
46 * This is useful for images scmaller than 1000px per side only.
47 */
48 private static boolean upscale = false;
49 private static float scale = 1.0f;
52 /**
53 * draws a rotated square with center point center, having size and orientation
55 static void drawSquare( ImageProcessor ip, double[] o, double scale, double orient )
57 scale /= 2;
59 double sin = Math.sin( orient );
60 double cos = Math.cos( orient );
62 int[] x = new int[ 6 ];
63 int[] y = new int[ 6 ];
66 x[ 0 ] = ( int )( o[ 0 ] + ( sin - cos ) * scale );
67 y[ 0 ] = ( int )( o[ 1 ] - ( sin + cos ) * scale );
69 x[ 1 ] = ( int )o[ 0 ];
70 y[ 1 ] = ( int )o[ 1 ];
72 x[ 2 ] = ( int )( o[ 0 ] + ( sin + cos ) * scale );
73 y[ 2 ] = ( int )( o[ 1 ] + ( sin - cos ) * scale );
74 x[ 3 ] = ( int )( o[ 0 ] - ( sin - cos ) * scale );
75 y[ 3 ] = ( int )( o[ 1 ] + ( sin + cos ) * scale );
76 x[ 4 ] = ( int )( o[ 0 ] - ( sin + cos ) * scale );
77 y[ 4 ] = ( int )( o[ 1 ] - ( sin - cos ) * scale );
78 x[ 5 ] = x[ 0 ];
79 y[ 5 ] = y[ 0 ];
81 ip.drawPolygon( new Polygon( x, y, x.length ) );
85 public void run( String args )
87 if ( IJ.versionLessThan( "1.37i" ) ) return;
89 final ImagePlus imp = WindowManager.getCurrentImage();
90 if ( imp == null ) { System.err.println( "There are no images open" ); return; }
92 final GenericDialog gd = new GenericDialog( "Test SIFT" );
94 gd.addNumericField( "steps_per_scale_octave :", steps, 0 );
95 gd.addNumericField( "initial_gaussian_blur :", initial_sigma, 2 );
96 gd.addNumericField( "feature_descriptor_size :", fdsize, 0 );
97 gd.addNumericField( "feature_descriptor_orientation_bins :", fdbins, 0 );
98 gd.addNumericField( "minimum_image_size :", min_size, 0 );
99 gd.addNumericField( "maximum_image_size :", max_size, 0 );
100 gd.addCheckbox( "upscale_image_first", upscale );
101 gd.showDialog();
102 if ( gd.wasCanceled() ) return;
103 steps = ( int )gd.getNextNumber();
104 initial_sigma = ( float )gd.getNextNumber();
105 fdsize = ( int )gd.getNextNumber();
106 fdbins = ( int )gd.getNextNumber();
107 min_size = ( int )gd.getNextNumber();
108 max_size = ( int )gd.getNextNumber();
109 upscale = gd.getNextBoolean();
110 if ( upscale ) scale = 2.0f;
113 ImageProcessor ip1 = imp.getProcessor().convertToFloat();
114 ImageProcessor ip2 = imp.getProcessor().duplicate().convertToRGB();
116 Vector< Feature > fs1;
118 FloatArray2DSIFT sift = new FloatArray2DSIFT( fdsize, fdbins );
120 FloatArray2D fa = ImageArrayConverter.ImageToFloatArray2D( ip1 );
121 ImageFilter.enhance( fa, 1.0f );
123 if ( upscale )
125 FloatArray2D fat = new FloatArray2D( fa.width * 2 - 1, fa.height * 2 - 1 );
126 FloatArray2DScaleOctave.upsample( fa, fat );
127 fa = fat;
128 fa = ImageFilter.computeGaussianFastMirror( fa, ( float )Math.sqrt( initial_sigma * initial_sigma - 1.0 ) );
130 else
131 fa = ImageFilter.computeGaussianFastMirror( fa, ( float )Math.sqrt( initial_sigma * initial_sigma - 0.25 ) );
133 long start_time = System.currentTimeMillis();
134 System.out.print( "processing SIFT ..." );
135 sift.init( fa, steps, initial_sigma, min_size, max_size );
136 fs1 = sift.run( max_size );
137 Collections.sort( fs1 );
138 System.out.println( " took " + ( System.currentTimeMillis() - start_time ) + "ms" );
140 System.out.println( fs1.size() + " features identified and processed" );
142 //#############################################################################
144 FloatArray2DScaleOctave[] sos = sift.getOctaves();
145 for ( int o = 0; o < sos.length; ++o )
147 FloatArray2DScaleOctave so = sos[ o ];
149 FloatArray2D[] l = so.getL();
150 FloatArray2D[] d = so.getD();
152 for ( int i = 0; i < steps; ++i )
154 FloatArray2D ls = l[ i ];
155 FloatArray2D ds = d[ i ];
156 int os;
157 for ( int oi = o; oi > 0; --oi )
159 os = ( int )Math.pow( 2, oi - 1 );
160 int w = imp.getWidth();
161 int h = imp.getHeight();
162 for ( os = oi; os > 1; --os )
164 w = w / 2 + w % 2;
165 h = h / 2 + h % 2;
167 //System.out.println( "o: " + o + ", w: " + w + ", h: " + h );
168 FloatArray2D ld = new FloatArray2D( w, h );
169 FloatArray2D dd = new FloatArray2D( w, h );
170 FloatArray2DScaleOctave.upsample( ls, ld );
171 FloatArray2DScaleOctave.upsample( ds, dd );
172 ls = ld;
173 ds = dd;
175 os = ( int )Math.pow( 2, o );
177 System.out.println( os * so.SIGMA[ i ] );
179 FloatProcessor fp = new FloatProcessor( ls.width, ls.height );
180 ImageArrayConverter.FloatArrayToFloatProcessor( fp, ls );
181 fp.setMinAndMax( 0.0, 1.0 );
182 // FloatProcessor fp = new FloatProcessor( ds.width, ds.height );
183 // ImageArrayConverter.FloatArrayToFloatProcessor( fp, ds );
184 // fp.setMinAndMax( -0.25, 0.25 );
185 ImageProcessor ip = fp.convertToRGB();
187 // draw DoG detections
189 // ip.setLineWidth( 2 );
190 // ip.setColor( Color.red );
191 // for ( FloatArray2DSIFT.Feature f : fs1 )
192 // {
193 // int ot = ( int )( f.scale / initial_sigma );
194 // int ol = 0;
195 // while ( ot > 1 )
196 // {
197 // ot /= 2;
198 // ++ol;
199 // }
200 // //int ol = General.ldu( ( int )( f.scale / initial_sigma ) ) - 1;
201 // int sl = ( int )Math.round( steps * ( Math.log( f.scale / Math.pow( 2.0, ol ) / initial_sigma ) ) / Math.log( 2.0 ) );
202 // if ( sl >= steps )
203 // {
204 // ++ol;
205 // sl = sl % steps;
206 // }
208 // //if ( ol < o || ( ol == o && sl <= i ) )
209 // if ( ol == o && sl == i )
210 // drawSquare( ip, new double[]{ f.location[ 0 ] / scale, f.location[ 1 ] / scale }, fdsize * ( double )f.scale / scale, ( double )f.orientation );
211 // }
213 imp.setProcessor( null, ip );
214 imp.updateAndDraw();
216 new ij.io.FileSaver( imp ).saveAsTiff(
217 "D:/Benutzer/Stephan/Eigene Dateien/diploma/gauss-0" + ( steps * o + i ) + ".tif" );
220 FloatArray2D[] gradients = so.getL1( i );
221 ImageArrayConverter.FloatArrayToFloatProcessor( fp, gradients[ 0 ] );
222 stackGradientAmplitude.addSlice( null, fp );
223 ImageArrayConverter.FloatArrayToFloatProcessor( fp, gradients[ 1 ] );
224 stackGradientOrientation.addSlice( null, fp );
229 for ( int i = 0; i < d.length; ++i )
231 FloatProcessor fp = new FloatProcessor( d[ i ].width, d[ i ].height );
232 ImageArrayConverter.FloatArrayToFloatProcessor( fp, d[ i ] );
233 fp.setMinAndMax( -255.0, 255.0 );
234 ImageProcessor ipl = fp.convertToRGB();
236 // draw DoG detections
237 ipl.setLineWidth( 2 );
238 ipl.setColor( Color.green );
240 Vector< float[] > candidates = dog.getCandidates();
241 for ( float[] c : candidates )
243 if ( i == ( int )Math.round( c[ 2 ] ) )
244 ipl.drawDot( ( int )Math.round( c[ 0 ] ), ( int )Math.round( c[ 1 ] ) );
247 stackDoG.addSlice( null, ipl );
250 //stackDoG.addSlice( null, fp );
255 //#############################################################################
258 ip2.setLineWidth( 2 );
259 ip2.setColor( Color.red );
260 for ( Feature f : fs1 )
262 //System.out.println( f.location[ 0 ] + " " + f.location[ 1 ] + " " + f.scale + " " + f.orientation );
263 drawSquare( ip2, new double[]{ f.location[ 0 ] / scale, f.location[ 1 ] / scale }, fdsize * ( double )f.scale / scale, ( double )f.orientation );
266 ImagePlus imp1 = new ImagePlus( imp.getTitle() + " Features ", ip2 );
267 imp1.show();
270 public void keyPressed(KeyEvent e)
272 if (
273 ( e.getKeyCode() == KeyEvent.VK_F1 ) &&
274 ( e.getSource() instanceof TextField) )
279 public void keyReleased(KeyEvent e) { }
281 public void keyTyped(KeyEvent e) { }