00001
00002 #include "sdet_gauss_fit.h"
00003
00004
00005
00006 #include <vcl_iostream.h>
00007 #include <vcl_fstream.h>
00008 #include <vcl_cmath.h>
00009 #include <vgl/vgl_point_3d.h>
00010 #include <vnl/vnl_math.h>
00011 #include <vsol/vsol_point_2d.h>
00012
00013
00014 #include <vnl/vnl_matrix_fixed.h>
00015 #include <vnl/vnl_inverse.h>
00016
00017 #include <vnl/algo/vnl_levenberg_marquardt.h>
00018
00019 #define JIL_DIAGNOSTICS
00020
00021
00022 sdet_adjust_lsqr::
00023 sdet_adjust_lsqr( vcl_vector<vgl_point_3d<double> > const& img_pts,
00024 unsigned int num_unknowns, unsigned int num_residuals,
00025 int n_peaks)
00026 : vnl_least_squares_function(num_unknowns, num_residuals,
00027 vnl_least_squares_function::no_gradient)
00028 , img_pts_(img_pts)
00029 , num_pixels_(img_pts_.size())
00030 , n_peaks_(n_peaks)
00031 {
00032 }
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 void sdet_adjust_lsqr::f( vnl_vector<double> const& unknowns,
00054 vnl_vector<double> & fit_error)
00055 {
00056
00057
00058
00059 vnl_vector<double> fit_value(num_pixels_);
00060 vnl_vector<double> sum(num_pixels_);
00061
00062 for (unsigned i=0; i < num_pixels_; ++i) {
00063 sum[i] = 0.0;
00064 }
00065
00066
00067
00068
00069
00070 for (int j=0; j < n_peaks_; ++j)
00071 {
00072 vnl_matrix_fixed<double,2,2> V;
00073 V(0,0) = unknowns[6*j+4];
00074 V(0,1) = unknowns[6*j+6];
00075 V(1,0) = unknowns[6*j+6];
00076 V(1,1) = unknowns[6*j+5];
00077
00078 vnl_matrix_fixed<double,2,2> Vinv = vnl_inverse(V);
00079
00080 for (unsigned i=0; i < img_pts_.size(); ++i)
00081 {
00082 double peak_delta = unknowns[6*j+1] - unknowns[0];
00083
00084 vnl_matrix_fixed<double,2,1> D;
00085 D(0,0) = img_pts_[i].x() - unknowns[6*j+2];
00086 D(1,0) = img_pts_[i].y() - unknowns[6*j+3];
00087
00088 vnl_matrix_fixed<double,1,2> Dtrans = D.transpose();
00089 double exponent = ((-1.0 * Dtrans * Vinv * D)(0,0))/2.0;
00090
00091
00092 double gaussian = peak_delta * vcl_exp(exponent);
00093
00094
00095 sum[i] += gaussian;
00096 }
00097 }
00098
00099
00100 for (unsigned i=0; i < img_pts_.size(); ++i)
00101 fit_value[i] = sum[i] + unknowns[0];
00102
00103 #if 0 // Debug: print out values for this step
00104 vcl_cout << "plane(" << unknowns[0] << "), peak(" << unknowns[1] << "),\n"
00105 << "x(" << unknowns[2] << "), y(" << unknowns[3] << ")\n"
00106 << "var x(" << unknowns[4] << "), var y(" << unknowns[5] << ")\n"
00107 << "covar(" << unknowns[6] << ')' << vcl_endl;
00108 #endif
00109
00110
00111 for (unsigned i = 0; i < img_pts_.size(); ++i)
00112 {
00113 double e = (fit_value[i] - img_pts_[i].z());
00114 fit_error[i] = vcl_fabs(e);
00115 #if 0 // Debug: print out values of fit error for each point
00116 vcl_cout << "fiterror[" << i << ']' << fit_error[i] << vcl_endl;
00117 #endif
00118 }
00119 }
00120
00121
00122
00123
00124
00125 static bool init(vcl_vector<vgl_point_3d<double> > img_pts, vcl_vector<double>& peak,
00126 double& plane, vcl_vector<double>& ux, vcl_vector<double>& uy,
00127 vcl_vector<double>& sxx, vcl_vector<double>& syy, vcl_vector<double>& sxy,
00128 vcl_vector<vsol_point_2d_sptr> ps_list, int n_peaks, double xmin, double ymin)
00129 {
00130
00131 plane = 65000.;
00132 for (unsigned i=0; i<img_pts.size(); ++i)
00133 {
00134 if ( img_pts[i].z() < plane )
00135 plane = img_pts[i].z();
00136 }
00137
00138
00139
00140
00141
00142 for (int j=0; j < n_peaks; ++j)
00143 {
00144 peak.push_back(0.0);
00145 ux.push_back(0.0);
00146 uy.push_back(0.0);
00147 sxx.push_back(0.0);
00148 syy.push_back(0.0);
00149 sxy.push_back(0.0);
00150
00151 double xf = ps_list[j]->x() - xmin;
00152 double yf = ps_list[j]->y() - ymin;
00153
00154 for (unsigned i=0; i<img_pts.size(); ++i)
00155 {
00156 double dx = img_pts[i].x() - xf;
00157 double dy = img_pts[i].y() - yf;
00158
00159 if (dx >= -2. && dx <= 2. && dy >= -2. && dy <= 2.)
00160 if ( img_pts[i].z() > peak[j] ) {
00161 peak[j] = img_pts[i].z();
00162 ux[j] = img_pts[i].x();
00163 uy[j] = img_pts[i].y();
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174 #if 0 // Original code, now commented out
00175 double sum = 0.0;
00176 ux = 0.0;
00177 uy = 0.0;
00178 for (unsigned i=0; i<img_pts.size(); ++i)
00179 {
00180 vgl_point_3d<double>& p = img_pts[i];
00181 double w = p.z()-plane;
00182 sum += w;
00183 double x = p.x(), y = p.y();
00184 ux += w*x;
00185 uy += w*y;
00186 sxx[j] += x*x*w;
00187 syy[j] += y*y*w;
00188 sxy[j] += x*y*w;
00189 }
00190
00191 if (sum<=0) return false;
00192 ux /= sum;
00193 uy /= sum;
00194 sxx[j] = 0;
00195 syy[j] = 0;
00196 sxy[j] = 0;
00197
00198 for (unsigned i=0; i<img_pts.size(); ++i)
00199 {
00200 vgl_point_3d<double>& p = img_pts[i];
00201 double w = p.z()-plane;
00202 double x = p.x(), y = p.y();
00203 sxx[j] += (x-ux)*(x-ux)*w;
00204 syy[j] += (y-uy)*(y-uy)*w;
00205 sxy[j] += (x-ux)*(y-uy)*w;
00206 }
00207
00208 sxx[j] /= sum;
00209 syy[j] /= sum;
00210 sxy[j] /= sum;
00211
00212 #else // more rough guesses
00213 sxx[j] = 0.5;
00214 syy[j] = 0.5;
00215 sxy[j] = 0.0;
00216 #endif // 0
00217 }
00218 return true;
00219 }
00220
00221
00222
00223
00224
00225
00226 vnl_vector<double> sdet_gauss_fit::adjust( vcl_vector<vgl_point_3d<double> > img_pts,
00227 vcl_vector<vsol_point_2d_sptr> ps_list,
00228 int n_peaks, vcl_ofstream& outfile,
00229 double xmin, double ymin)
00230 {
00231 unsigned num_pixels = img_pts.size();
00232 unsigned num_unknowns = 6*n_peaks + 1;
00233 unsigned num_residuals = num_pixels;
00234
00235
00236
00237
00238
00239
00240
00241 double plane;
00242 vcl_vector<double> peak;
00243 vcl_vector<double> ux;
00244 vcl_vector<double> uy;
00245 vcl_vector<double> sxx;
00246 vcl_vector<double> syy;
00247 vcl_vector<double> sxy;
00248
00249 if (!init(img_pts, peak, plane, ux, uy, sxx, syy, sxy, ps_list, n_peaks, xmin, ymin))
00250 {
00251 outfile << "ERROR!! sdet_gauss_fit::adjust(), Cannot init()" << vcl_endl;
00252 vcl_cerr << "ERROR!! sdet_gauss_fit::adjust(), Cannot init()\n";
00253 }
00254
00255 for (int i=0; i < n_peaks; ++i)
00256 {
00257 #if 0
00258 outfile << "Init values:\n-----------------------------------------------\n Peak "
00259 << i+1 << "\n -------------------------\nplane= " << plane << vcl_endl
00260 << "peak=" << peak[i] << ", ux=" << ux[i]
00261 << ", uy=" << uy[i] << ", sxx=" << sxx[i] << ", syy=" << syy[i]
00262 << ", sxy=" << sxy[i] << vcl_endl;
00263 outfile.flush();
00264 #endif
00265 vcl_cout << "Init values:\n-----------------------------------------------\n Peak "
00266 << i+1 << "\n -------------------------\nplane= " << plane << vcl_endl
00267 << "peak=" << peak[i] << ", ux=" << ux[i]
00268 << ", uy=" << uy[i] << ", sxx=" << sxx[i] << ", syy=" << syy[i]
00269 << ", sxy=" << sxy[i] << vcl_endl;
00270 }
00271
00272
00273 sdet_adjust_lsqr lsf(img_pts, num_unknowns, num_residuals, n_peaks);
00274
00275
00276
00277 vnl_levenberg_marquardt levmarq(lsf);
00278
00279 #ifdef JIL_DIAGNOSTICS
00280 levmarq.set_verbose(true);
00281 levmarq.set_trace(true);
00282 #endif
00283
00284
00285 #if 0
00286
00287
00288 levmarq.set_x_tolerance(1e-10);
00289
00290
00291 levmarq.set_epsilon_function(1);
00292
00293
00294
00295 levmarq.set_f_tolerance(1e-15);
00296 #endif
00297
00298
00299 levmarq.set_max_function_evals(1000);
00300
00301
00302 vnl_vector<double> unknowns(num_unknowns);
00303
00304 unknowns[0] = plane;
00305 for (int i=0; i < n_peaks; ++i)
00306 {
00307 unknowns[1+6*i] = peak[i];
00308 unknowns[2+6*i] = ux[i];
00309 unknowns[3+6*i] = uy[i];
00310 unknowns[4+6*i] = sxx[i];
00311 unknowns[5+6*i] = syy[i];
00312 unknowns[6+6*i] = sxy[i];
00313
00314 outfile << "max pixel for peak " << i+1 << " = " << peak[i] << vcl_endl;
00315 }
00316
00317 vcl_cout << "\nStarting Levenberg-Marquardt minimizer, may take a few seconds per iteration"
00318 << vcl_endl;
00319
00320
00321 levmarq.minimize(unknowns);
00322
00323
00324 levmarq.diagnose_outcome();
00325 #if 0
00326 outfile << "Min error of " << levmarq.get_end_error()
00327 << " at the following local minima :" << vcl_endl;
00328 #endif
00329 vcl_cout << "Min error of " << levmarq.get_end_error()
00330 << " at the following local minima :" << vcl_endl;
00331
00332
00333 #if 0
00334 outfile << " -----------------------------\nFitted parameters:\n------------" << vcl_endl;
00335 #endif
00336 vcl_cout << " -----------------------------\nFitted parameters:\n------------" << vcl_endl;
00337
00338 for (unsigned i=0; i<num_unknowns; ++i)
00339 {
00340 #if 0
00341 outfile << "unknowns[" << i << "]= " << unknowns[i] << vcl_endl;
00342 if (i%6==4||i%6==5) vcl_cout << " sd = " << vcl_sqrt(unknowns[i]) << vcl_endl;
00343 #endif
00344
00345 vcl_cout << "unknowns[" << i << "]= " << unknowns[i] << vcl_endl;
00346 if (i%6==4||i%6==5) vcl_cout << " sd = " << vcl_sqrt(unknowns[i]) << vcl_endl;
00347
00348 if ((i % 6) == 0) {
00349 #if 0
00350 outfile << "------------" << vcl_endl;
00351 #endif
00352 vcl_cout << "------------" << vcl_endl;
00353 }
00354 }
00355 outfile.flush();
00356 vcl_cout.flush();
00357
00358 return unknowns;
00359 }
00360
00361
00362
00363
00364
00365 vnl_vector<double> sdet_gauss_fit::calculate_ellipse( vnl_vector<double> result, float x,
00366 float y, int i, int n_peaks,
00367 vcl_ofstream& outfile)
00368 {
00369
00370 vnl_vector<double> params(3*n_peaks);
00371
00372 const double pi = vnl_math::pi;
00373 double theta = 0.0;
00374 double a = 0.0;
00375 double b = 0.0;
00376 double sxx = result[6*i+4];
00377 double syy = result[6*i+5];
00378 double sxy = result[6*i+6];
00379
00380
00381
00382 bool xxgtyy = (sxx > syy);
00383 bool xxeqyy = (vcl_fabs(sxx - syy) < 0.0001);
00384 bool xygt0 = (sxy > 0.0001);
00385 bool xyeq0 = (vcl_fabs(sxy) < 0.0001);
00386
00387
00388 if (xyeq0 && xxeqyy)
00389 theta = 0.0;
00390
00391 else if (xxeqyy && xygt0)
00392 theta = pi/4.0;
00393
00394 else if (xxeqyy && !xygt0)
00395 theta = 3.0*pi/4.0;
00396
00397 else
00398 {
00399 theta = 0.5 * vcl_atan(2.0 * sxy/(sxx - syy));
00400
00401
00402 if (xxgtyy && xygt0) {}
00403
00404 else if (xxgtyy && !xygt0)
00405 theta = theta + pi;
00406
00407 else if (!xxgtyy)
00408 theta = theta + pi/2.0;
00409 }
00410
00411 double angle = theta*180./pi;
00412
00413
00414 double sqrt2 = vcl_sqrt(2.0);
00415 double factor = vcl_sqrt(sxx*sxx + syy*syy + 4.0*sxy*sxy - 2.0*sxx*syy);
00416 a = vcl_sqrt(sxx + syy + factor)/sqrt2;
00417 b = vcl_sqrt(sxx + syy - factor)/sqrt2;
00418
00419
00420 outfile << "--------------------\nresults for peak " << i+1 << vcl_endl;
00421 vcl_cout << "--------------------\nresults for peak " << i+1 << vcl_endl;
00422
00423 double bkgd = result[0];
00424 double peak = result[6*i+1];
00425 double d_peak = peak - bkgd;
00426
00427 outfile << "bkgd= " << bkgd << ", peak= " << peak << ", d_peak= "
00428 << d_peak << vcl_endl
00429 << "x= " << x << ", y= " << y << vcl_endl;
00430 vcl_cout << "bkgd= " << bkgd << ", peak= " << peak << ", d_peak= "
00431 << d_peak << vcl_endl
00432 << "x= " << x << ", y= " << y << vcl_endl;
00433 #if 0
00434 outfile << "sxx= " << sxx << ", syy= " << syy << ", sxy= " << sxy
00435 << ", factor= " << factor << vcl_endl;
00436 vcl_cout << "sxx= " << sxx << ", syy= " << syy << ", sxy= " << sxy
00437 << ", factor= " << factor << vcl_endl
00438 << "sin(theta)= " << vcl_sin(theta) << ", cos(theta)= "
00439 << vcl_cos(theta) << vcl_endl;
00440 #endif
00441
00442 outfile << "theta= " << theta << ", angle= " << angle
00443 << ", a= " << a << ", b= " << b << vcl_endl;
00444 vcl_cout << "theta= " << theta << ", angle= " << angle
00445 << ", a= " << a << ", b= " << b << vcl_endl;
00446 outfile.flush();
00447 vcl_cout.flush();
00448
00449 params[0] = theta;
00450 params[1] = a;
00451 params[2] = b;
00452
00453 return params;
00454 }