00001
00002
00003
00004
00005
00006 #ifndef HSCORNER_FILTER_H
00007 #define HSCORNER_FILTER_H
00008
00009 #include "filter.h"
00010 #include "image.h"
00011 #include "image_op.h"
00012 #include "gauss.h"
00013 #include "filter_grad.h"
00014 #include "property_image.h"
00015 #include "corner.h"
00016
00017 namespace mimas {
00018
00031 template<typename T>
00032 class corner_tool
00033 {
00034 private:
00035
00036 double sigma, maxError;
00037 double thres;
00038 double lowd, upd, width;
00039 double disp ;
00040 double uniqueness, correlate, asymetry ;
00041 double tuniqueness, tcorrelate, tasymetry;
00042 double theight, twidth ;
00043 double patch_sigma;
00044 int stereo_images;
00045 int fixed_matches;
00046 int good_matches;
00047
00048 public:
00049 corner_tool()
00050 {
00051 sigma = 1.0, maxError = 0.5 / 256.0, thres = 6.0;
00052 lowd = -0.5, upd = 0.5, width = 3.0;
00053 disp = 0;
00054 uniqueness = 0.004, correlate = 0.985, asymetry= 0.85;
00055 tuniqueness = 0.001, tcorrelate = 0.980, tasymetry = 0.85;
00056 theight = 20.0, twidth = 60.0;
00057 patch_sigma = 3.0;
00058 stereo_images = 1;
00059 fixed_matches = 0;
00060 good_matches = 0;
00061 }
00062
00063 corner_tool(double t)
00064 {
00065 sigma = 1.0, maxError = 0.5 / 256.0, thres = t;
00066 lowd = -0.5, upd = 0.5, width = 3.0;
00067 disp = 0;
00068 uniqueness = 0.004, correlate = 0.985, asymetry= 0.85;
00069 tuniqueness = 0.001, tcorrelate = 0.980, tasymetry = 0.85;
00070 theight = 20.0, twidth = 60.0;
00071 patch_sigma = 3.0;
00072 stereo_images = 1;
00073 fixed_matches = 0;
00074 good_matches = 0;
00075 }
00076
00077 void setThreshold( double t )
00078 {
00079 thres = t;
00080 }
00081
00082 void filterImage( image<T> &input, corner_image &corner_im )
00083 {
00084 image<T> gradx,grady,outsq;
00085 image<T> gim;
00086 image<T> peak_im;
00087
00088
00089 doCornerExtract( input, sigma, maxError, 0.05, peak_im, gradx, grady );
00090 gim = gaussBlur< float >( peak_im, sigma, maxError );
00091 peak_im.clear();
00092 findMaxima( gim, 1024.0*thres,0,corner_im);
00093 cornerLocate( gim, gradx, grady, corner_im );
00094 }
00095
00096
00097 private:
00098 void doCornerExtract( image<T>& im, double sigma, double maxError,
00099 double edge_sup, image<T>& output_im, image<T>& gradx,
00100 image<T>& grady )
00101 {
00102 if ( &output_im != &im && &output_im != &gradx && &output_im != &grady )
00103 output_im.init( im.getWidth(), im.getHeight() );
00104
00105 filter<T>::gradX( im, gradx );
00106 filter<T>::gradY( im, grady );
00107
00108 image<T>
00109 gradsqx ( gradx * gradx ),
00110 gradsqy ( grady * grady ),
00111 gradsqxy( gradx * grady ),
00112 gradsqxsqy( gradsqx + gradsqy );
00113
00114 image<T> gimx, gimy, gimxy, gimedge;
00115
00116 gimx = gaussBlur< float >( gradsqx, sigma, maxError );
00117 gradsqx.clear();
00118 gimy = gaussBlur< float >( gradsqy, sigma, maxError );
00119 gradsqy.clear();
00120 gimxy = gaussBlur< float >( gradsqxy, sigma, maxError );
00121 gradsqxy.clear();
00122
00123 gimedge = gaussBlur< float >( gradsqxsqy, 1.1 * sigma, maxError );
00124 gradsqxsqy.clear();
00125
00126
00127 doCornerExtract2(gimx,gimy,gimxy,gimedge,edge_sup, output_im);
00128
00130 }
00131
00132
00133 void doCornerExtract2( const image<T>& im1, const image<T>& im2,
00134 const image<T>& im3, const image<T>& im4,
00135 double edge_supp, image<T>& output ) const
00136 {
00137 MMERROR( im1.getSize() == im2.getSize(),
00138 mimasexception, , "corner_tool::doCornerExtract2 - "
00139 "Images 1 and 2 are of different size." );
00140 MMERROR( im1.getSize() == im3.getSize(),
00141 mimasexception, , "corner_tool::doCornerExtract2 - "
00142 "Images 1 and 3 are of different size." );
00143 MMERROR( im1.getSize() == im4.getSize(),
00144 mimasexception, , "corner_tool::doCornerExtract2 - "
00145 "Images 1 and 4 are of different size." );
00146 MMERROR( im1.getSize() == output.getSize(),
00147 mimasexception, , "corner_tool::doCornerExtract2 - "
00148 "Image 1 and output image are of different size." );
00149 const T
00150 *p1 = im1.rawData(),
00151 *p2 = im2.rawData(),
00152 *p3 = im3.rawData(),
00153 *p4 = im4.rawData();
00154 T *q = output.rawData();
00155
00156 for ( int i=0; i<(signed)output.getSize(); i++ ) {
00157 *q = (T)( (double)*p1 * (double)*p2 -
00158 (double)*p3 * (double)*p3 -
00159 edge_supp * (double)*p4 * (double)*p4 );
00160 p1++; p2++; p3++; p4++; q++;
00161 };
00162 }
00163
00164 void findMaxima(const image<T> &input, double thres, int num,
00165 corner_image& output)
00166 {
00167 output.init( input.getWidth(), input.getHeight() );
00168
00169 int wm1 = input.getWidth()-1;
00170 int hm1 = input.getHeight()-1;
00171 int nmax;
00172 double pix;
00173
00174 for(int y=1;y<hm1;++y)
00175 {
00176 const T
00177 *max = input.rawData() + y * input.getWidth(),
00178 *max_m1 = max - input.getWidth(),
00179 *max_p1 = max + input.getWidth();
00180 for(int x=1;x<wm1;++x)
00181 {
00182
00183 pix = (double) max[x];
00184 if (pix<thres)
00185 continue;
00186
00187 nmax = 0;
00188
00189 if (pix<max_m1[x-1] && ++nmax > num) continue;
00190 if (pix<max_m1[x] && ++nmax > num) continue;
00191 if (pix<max_m1[x+1] && ++nmax > num) continue;
00192 if (pix<max[x-1] && ++nmax > num) continue;
00193 if (pix<max[x+1] && ++nmax > num) continue;
00194 if (pix<max_p1[x-1] && ++nmax > num) continue;
00195 if (pix<max_p1[x] && ++nmax > num) continue;
00196 if (pix<max_p1[x+1] && ++nmax > num) continue;
00197
00198 corner_ptr c( new corner );
00199
00200 c->setPosition((double)x+0.5,(double)y+0.5);
00201 c->setOrientation(angle(0));
00202 c->setContrast( sqrt(pix) );
00203
00204 if (!output.pixel(x,y))
00205 output.pixel( x,y ) = c;
00206 }
00207 }
00208 }
00209
00210
00211 void cornerLocate( image<T>& corner_im,
00212 image<T>& gradx, image<T>& grady,
00213 corner_image& im )
00214 {
00215 int x,y;
00216 double rx,ry;
00217
00218 for(y=0;y<im.getHeight();++y)
00219 {
00220 for(x=0;x<im.getWidth();x++)
00221 {
00222
00223 corner_ptr c( boost::dynamic_pointer_cast< corner >
00224 ( im.pixel(x,y) ) );
00225
00226 if (!c) continue;
00227
00228
00229
00230 c->setContrast( sqrt(quadFit( corner_im, x,y, &rx, &ry )) );
00231 c->setPosition( rx,ry );
00232 c->setOrientation( cornerOrient(rx,ry, 10.0, gradx, grady ) );
00233 }
00234 }
00235 }
00236
00237 double quadFit( image<T>& image, int xin, int yin, double * px, double *py )
00238 {
00239 double x,y;
00240 x = (double)xin;
00241 y = (double)yin;
00242
00243 int n,m;
00244 double pixval[3][3];
00245 for(n=0;n<3;++n)
00246 {
00247 for(m=0;m<3;++m)
00248 {
00249 pixval[n][m] = image.getPixel( xin+m-1, yin+n-1 );
00250 }
00251 }
00252
00253 double a, b, c, d, e, f;
00254 double inter;
00255 double temp;
00256 double xs,ys;
00257
00258 a = pixval[1][1];
00259 b = (pixval[0][2] - pixval[0][0]
00260 + pixval[1][2] - pixval[1][0]
00261 + pixval[2][2] - pixval[2][0]) / 6.0;
00262 c = (pixval[2][0] - pixval[0][0]
00263 + pixval[2][1] - pixval[0][1]
00264 + pixval[2][2] - pixval[0][2]) / 6.0;
00265 d = (pixval[0][0] - 2.0 * pixval[0][1] + pixval[0][2]
00266 + 3.0 * pixval[1][0] - 6.0 * pixval[1][1] + 3.0 * pixval[1][2]
00267 + pixval[2][0] - 2.0 * pixval[2][1] + pixval[2][2]) / 10.0;
00268 e = (pixval[0][0] - pixval[2][0]
00269 + pixval[2][2] - pixval[0][2]) / 4.0;
00270 f = (pixval[0][0] + 3.0 * pixval[0][1] + pixval[0][2]
00271 - 2.0 * pixval[1][0] - 6.0 * pixval[1][1] - 2.0 * pixval[1][2]
00272 + pixval[2][0] + 3.0 * pixval[2][1] + pixval[2][2]) / 10.0;
00273
00274 temp = 4.0 * d * f - e * e;
00275 *px = 1.5 + x + (e * c - 2 * f * b) / temp;
00276 *py = 1.5 + y + (e * b - 2 * d * c) / temp;
00277
00278 xs = (e * c - 2 * f * b) / temp;
00279 ys = (e * b - 2 * d * c) / temp;
00280
00281 inter = a + b * xs + c * ys + d * xs * xs + e * xs * ys + f * ys * ys;
00282
00283 return (inter);
00284 }
00285
00286
00287 angle
00288 cornerOrient(double rx,double ry, double range,
00289 image<T>& gradx, image<T>& grady )
00290 {
00291
00292 int lx,ux,ly,uy,x,y;
00293 double meanx=0.0,meany=0.0;
00294 double dx,dy, delx,dely;
00295 double twosigma2 = range*range/2.0;
00296 double weight;
00297 double thresh=0.0;
00298 double pix,v;
00299 angle orient;
00300
00301 lx = (int)(rx-range-1.0);
00302 ux = (int)(rx+range+2);
00303 ly = (int)(ry-range-1.0);
00304 uy = (int)(ry+range+2);
00305
00306 image<double> grad;
00307 grad.init( ux-lx, uy-ly );
00308
00309
00310 for (y=ly;y<uy;++y)
00311 {
00312 for (x=lx;x<ux;++x)
00313 {
00314 dx = (double)gradx.getPixel( x,y );
00315 dy = (double)grady.getPixel( x,y );
00316 v = dx*dx+dy*dy;
00317 grad.setPixel( x-lx, y-ly, v );
00318 thresh += v;
00319 }
00320 }
00321
00322 thresh /= (double)((ux-lx)*(uy-ly));
00323
00324
00325 for (y=ly+1;y<uy-1;++y)
00326 {
00327 for (x=lx+1;x<ux-1;++x)
00328 {
00329 if ((pix=grad.getPixel(x-lx,y-ly)) > thresh)
00330 {
00331 delx = (double)x + 0.5 - rx;
00332 dely = (double)y + 0.5 - ry;
00333
00334 if (delx*delx + dely*dely < twosigma2*2.0) weight = 1.0;
00335 else weight = 0.0;
00336 meanx += delx*weight;
00337 meany += dely*weight;
00338 }
00339 }
00340 }
00341
00342 if (meanx ==0) orient = angle(0);
00343 else
00344 orient = angle(meany,meanx);
00345
00346 return(orient);
00347 }
00348
00349 };
00350
00351 };
00352
00353 #endif
00354