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
;
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_Test
implements PlugIn
, KeyListener
29 private static int steps
= 3;
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;
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
46 * This is useful for images scmaller than 1000px per side only.
48 private static boolean upscale
= false;
49 private static float scale
= 1.0f
;
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
)
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
);
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
);
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
);
125 FloatArray2D fat
= new FloatArray2D( fa
.width
* 2 - 1, fa
.height
* 2 - 1 );
126 FloatArray2DScaleOctave
.upsample( fa
, fat
);
128 fa
= ImageFilter
.computeGaussianFastMirror( fa
, ( float )Math
.sqrt( initial_sigma
* initial_sigma
- 1.0 ) );
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
];
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
)
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
);
175 os
= ( int )Math
.pow( 2, o
);
176 FloatProcessor fp
= new FloatProcessor( ls
.width
, ls
.height
);
177 ImageArrayConverter
.FloatArrayToFloatProcessor( fp
, ls
);
178 fp
.setMinAndMax( 0.0, 1.0 );
179 //ImageProcessor ipl = fp.convertToRGB();
180 ImageProcessor ipl
= fp
.duplicate();
181 ImageArrayConverter
.FloatArrayToFloatProcessor( fp
, ds
);
182 fp
.setMinAndMax( -1.0, 1.0 );
183 ImageProcessor ipd
= fp
.convertToRGB();
185 // draw DoG detections
187 ipl
.setLineWidth( 1 );
188 ipl
.setColor( Color
.red
);
189 for ( Feature f
: fs1
)
191 int ol
= General
.ldu( ( int )( f
.scale
/ initial_sigma
) );
192 int sl
= ( int )Math
.round( steps
* ( Math
.log( f
.scale
/ Math
.pow( 2.0, ol
) / initial_sigma
) ) / Math
.log( 2.0 ) );
199 if ( ol
<= o
&& sl
<= i
)
200 drawSquare( ipl
, new double[]{ f
.location
[ 0 ] / scale
, f
.location
[ 1 ] / scale
}, fdsize
* ( double )f
.scale
/ scale
, ( double )f
.orientation
);
204 FloatArray2D[] gradients = so.getL1( i );
205 ImageArrayConverter.FloatArrayToFloatProcessor( fp, gradients[ 0 ] );
206 stackGradientAmplitude.addSlice( null, fp );
207 ImageArrayConverter.FloatArrayToFloatProcessor( fp, gradients[ 1 ] );
208 stackGradientOrientation.addSlice( null, fp );
213 for ( int i = 0; i < d.length; ++i )
215 FloatProcessor fp = new FloatProcessor( d[ i ].width, d[ i ].height );
216 ImageArrayConverter.FloatArrayToFloatProcessor( fp, d[ i ] );
217 fp.setMinAndMax( -255.0, 255.0 );
218 ImageProcessor ipl = fp.convertToRGB();
220 // draw DoG detections
221 ipl.setLineWidth( 2 );
222 ipl.setColor( Color.green );
224 Vector< float[] > candidates = dog.getCandidates();
225 for ( float[] c : candidates )
227 if ( i == ( int )Math.round( c[ 2 ] ) )
228 ipl.drawDot( ( int )Math.round( c[ 0 ] ), ( int )Math.round( c[ 1 ] ) );
231 stackDoG.addSlice( null, ipl );
234 //stackDoG.addSlice( null, fp );
239 //#############################################################################
242 ip2
.setLineWidth( 1 );
243 ip2
.setColor( Color
.red
);
244 for ( Feature f
: fs1
)
246 System
.out
.println( f
.location
[ 0 ] + " " + f
.location
[ 1 ] + " " + f
.scale
+ " " + f
.orientation
);
247 drawSquare( ip2
, new double[]{ f
.location
[ 0 ] / scale
, f
.location
[ 1 ] / scale
}, fdsize
* ( double )f
.scale
/ scale
, ( double )f
.orientation
);
250 ImagePlus imp1
= new ImagePlus( imp
.getTitle() + " Features ", ip2
);
254 public void keyPressed(KeyEvent e
)
257 ( e
.getKeyCode() == KeyEvent
.VK_F1
) &&
258 ( e
.getSource() instanceof TextField
) )
263 public void keyReleased(KeyEvent e
) { }
265 public void keyTyped(KeyEvent e
) { }