00001
00002 #include "vsrl_image_correlation.h"
00003
00004 #include <vcl_cmath.h>
00005 #include <vcl_cstdlib.h>
00006 #include <vcl_cassert.h>
00007 #include <vil1/vil1_image.h>
00008 #include <vsrl/vsrl_window_accumulator.h>
00009 #include <vsrl/vsrl_parameters.h>
00010
00011
00012
00013 vsrl_image_correlation::vsrl_image_correlation(const vil1_image &im1, const vil1_image &im2):
00014 buffer1_(im1),
00015 buffer2_(im2)
00016 {
00017
00018
00019 window_width_=vsrl_parameters::instance()->correlation_window_width;
00020 window_height_=vsrl_parameters::instance()->correlation_window_height;
00021 correlation_range_=vsrl_parameters::instance()->correlation_range;
00022
00023 image_correlations_=0;
00024 mean_x_=0;
00025 mean_y_=0;
00026 std_x_=0;
00027 std_y_=0;
00028 }
00029
00030
00031 vsrl_image_correlation::~vsrl_image_correlation()
00032 {
00033 if (image_correlations_)
00034 {
00035 int i;
00036 for (i=0;i<correlation_range_*2+1;i++)
00037 delete image_correlations_[i];
00038 delete[] image_correlations_;
00039 }
00040 delete mean_x_;
00041 delete mean_y_;
00042 delete std_x_;
00043 delete std_y_;
00044 }
00045
00046
00047
00048
00049 void vsrl_image_correlation::set_window_width(int width)
00050 {
00051 window_width_=width;
00052 }
00053
00054 void vsrl_image_correlation::set_window_height(int height)
00055 {
00056 window_height_=height;
00057 }
00058
00059 void vsrl_image_correlation::set_correlation_range(int range)
00060 {
00061 correlation_range_ = range;
00062 }
00063
00064
00065 int vsrl_image_correlation::get_correlation_range()
00066 {
00067 return correlation_range_;
00068 }
00069
00070
00071
00072
00073 bool vsrl_image_correlation::check_range(vil1_byte_buffer &buf, int x, int y)
00074 {
00075 return x>=0 && x<buf.width() && y>=0 && y<buf.height();
00076 }
00077
00078
00079
00080
00081
00082
00083 void vsrl_image_correlation::compute_local_stats(vnl_matrix<double> &im, vnl_matrix<double> &mean,
00084 vnl_matrix<double> &std)
00085 {
00086
00087
00088
00089
00090
00091
00092
00093 vsrl_window_accumulator ac_mean;
00094
00095 ac_mean.set_in_matrix(&im);
00096 ac_mean.set_out_matrix(&mean);
00097 ac_mean.set_window_width(this->window_width_);
00098 ac_mean.set_window_height(this->window_height_);
00099 ac_mean.execute();
00100
00101
00102
00103 vnl_matrix<double> squares(im.rows(),im.cols());
00104
00105 shift_multiply_matrix(0,im,im,squares);
00106
00107 vsrl_window_accumulator ac_std;
00108
00109 ac_std.set_in_matrix(&squares);
00110 ac_std.set_out_matrix(&std);
00111 ac_std.set_window_width(this->window_width_);
00112 ac_std.set_window_height(this->window_height_);
00113 ac_std.execute();
00114
00115 for (unsigned int r=0;r<std.rows();r++)
00116 for (unsigned int c=0;c<std.cols();c++)
00117 {
00118 double xx=std(r,c);
00119 double m=mean(r,c);
00120 std(r,c) = vcl_sqrt(xx-m*m);
00121 }
00122 }
00123
00124 void vsrl_image_correlation::shift_multiply_matrix(int offset, vnl_matrix<double> &X, vnl_matrix<double> &Y,
00125 vnl_matrix<double> &XY)
00126 {
00127 assert(offset >= 0);
00128 assert((unsigned int)offset <= Y.cols());
00129
00130
00131
00132 XY.fill(0.0);
00133
00134
00135
00136 int start_col = 0-offset;
00137 if (start_col<0)
00138 start_col=0;
00139
00140 unsigned int end_col = Y.cols()-offset;
00141 if (end_col>X.cols())
00142 end_col=X.cols();
00143
00144 for (unsigned int r=0;r<X.rows();r++)
00145 for (unsigned int c=start_col;c<end_col;c++)
00146 XY(r,c) = X(r,c) * Y(r,c+offset);
00147 }
00148
00149
00150 void vsrl_image_correlation::compute_correlation(int x_offset,
00151 vnl_matrix<double> &X,
00152 vnl_matrix<double> &Y,
00153 vnl_matrix<double> &mean_x,
00154 vnl_matrix<double> &mean_y,
00155 vnl_matrix<double> &std_x,
00156 vnl_matrix<double> &std_y,
00157 vnl_matrix<double> &corr_matrix)
00158 {
00159
00160
00161
00162
00163 assert(x_offset >= 0);
00164 assert((unsigned int)x_offset <= Y.cols());
00165
00166
00167
00168 vnl_matrix<double> XY(X.rows(),X.cols());
00169
00170 shift_multiply_matrix(x_offset,X,Y,XY);
00171
00172
00173
00174 vnl_matrix<double> ac_XY(X.rows(),X.cols());
00175
00176 vsrl_window_accumulator win_ac;
00177
00178 win_ac.set_in_matrix(&XY);
00179 win_ac.set_out_matrix(&ac_XY);
00180 win_ac.set_window_width(this->window_width_);
00181 win_ac.set_window_height(this->window_height_);
00182 win_ac.execute();
00183
00184
00185
00186 corr_matrix.fill(0.0);
00187
00188
00189
00190
00191 int start_col = 0-x_offset;
00192 if (start_col <0)
00193 start_col=0;
00194
00195 unsigned int end_col = Y.cols()-x_offset;
00196 if (end_col>X.cols())
00197 end_col=X.cols();
00198
00199 for (unsigned int r=0;r<X.rows();r++)
00200 for (unsigned int c=start_col;c<end_col;c++)
00201 {
00202 double sx = std_x(r,c);
00203 double sy = std_y(r,c+x_offset);
00204
00205 double mx = mean_x(r,c);
00206 double my = mean_y(r,c+x_offset);
00207
00208 double xy = ac_XY(r,c);
00209
00210 if (sx!=0.0 && sy!=0.0)
00211 corr_matrix(r,c) = (xy-mx*my)/(sx*sy);
00212 }
00213 }
00214
00215
00216 void vsrl_image_correlation::initial_calculations()
00217 {
00218
00219
00220
00221 if (mean_x_)
00222 return;
00223
00224
00225
00226
00227 vnl_matrix<double> X(buffer1_.height(),buffer1_.width());
00228
00229 for (unsigned int r=0;r<X.rows();r++)
00230 for (unsigned int c=0;c<X.cols();c++)
00231 X(r,c)= buffer1_(c,r);
00232
00233 vnl_matrix<double> Y(buffer2_.height(),buffer2_.width());
00234
00235
00236 for (unsigned int r=0;r<Y.rows();r++)
00237 for (unsigned int c=0;c<Y.cols();c++)
00238 Y(r,c)= buffer2_(c,r);
00239
00240
00241
00242
00243 mean_x_ = new vnl_matrix<double>(X.rows(),X.cols());
00244 mean_y_ = new vnl_matrix<double>(Y.rows(),Y.cols());
00245 std_x_ = new vnl_matrix<double>(X.rows(),X.cols());
00246 std_y_ = new vnl_matrix<double>(Y.rows(),Y.cols());
00247
00248
00249 compute_local_stats(X,*mean_x_,*std_x_);
00250 compute_local_stats(Y,*mean_y_,*std_y_);
00251
00252
00253
00254
00255 image_correlations_ = (vnl_matrix<double>**)(vcl_malloc(sizeof(*image_correlations_) * (correlation_range_*2 +1)));
00256
00257
00258
00259 for (int i=0;i<correlation_range_*2 + 1;i++)
00260 {
00261 vnl_matrix<double> *corr = new vnl_matrix<double>(X.rows(),X.cols());
00262 image_correlations_[i]=corr;
00263
00264 int x_offset = i-correlation_range_;
00265
00266 if (x_offset >= 0)
00267 compute_correlation(x_offset,X,Y,*mean_x_,*mean_y_,*std_x_,*std_y_,*corr);
00268 }
00269 }
00270
00271
00272 double vsrl_image_correlation::get_mean_1(int x, int y)
00273 {
00274 return (*mean_x_)(y,x);
00275 }
00276
00277 double vsrl_image_correlation::get_mean_2(int x, int y)
00278 {
00279 return (*mean_y_)(y,x);
00280 }
00281
00282 double vsrl_image_correlation::get_std_1(int x, int y)
00283 {
00284 return (*std_x_)(y,x);
00285 }
00286
00287 double vsrl_image_correlation::get_std_2(int x, int y)
00288 {
00289 return (*std_y_)(y,x);
00290 }
00291
00292 double vsrl_image_correlation::get_image_value1(int x, int y)
00293 {
00294 return buffer1_(x,y);
00295 }
00296
00297
00298 double vsrl_image_correlation::get_image_value2(int x, int y)
00299 {
00300 return buffer2_(x,y);
00301 }
00302
00303 double vsrl_image_correlation::get_correlation(int x1, int y1, int delta_x)
00304 {
00305 if (!image_correlations_)
00306 return 0.0;
00307
00308 int index = delta_x + correlation_range_;
00309
00310 if (index < 0 || index >=(2*correlation_range_ +1))
00311 return 0.0;
00312
00313 return (*(image_correlations_[index]))(y1,x1);
00314 }
00315
00316
00317 int vsrl_image_correlation::get_image1_width()
00318 {
00319 return buffer1_.width();
00320 }
00321
00322 int vsrl_image_correlation::get_image2_width()
00323 {
00324 return buffer2_.width();
00325 }
00326
00327 int vsrl_image_correlation::get_image1_height()
00328 {
00329 return buffer1_.height();
00330 }
00331
00332 int vsrl_image_correlation::get_image2_height()
00333 {
00334 return buffer2_.height();
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 void vsrl_image_correlation::compute_local_stats(vil1_byte_buffer &buf, int x, int y, double &mean, double &std)
00346 {
00347
00348
00349 int low_x= x- window_width_/2;
00350 int hi_x= x+ window_width_/2;
00351
00352 if (low_x <0)
00353 low_x=0;
00354
00355 if (hi_x>buf.width()-1)
00356 hi_x=buf.width()-1;
00357
00358 int low_y= y- window_height_/2;
00359 int hi_y= y+ window_height_/2;
00360
00361 if (low_y <0)
00362 low_y=0;
00363
00364 if (hi_y>buf.height()-1)
00365 hi_y=buf.height()-1;
00366
00367
00368
00369
00370 double sum_x=0.0;
00371 double sum_xx=0.0;
00372 double N=0;
00373
00374 for (int ix=low_x;ix<= hi_x;ix++)
00375 for (int iy=low_y;iy<=hi_y;iy++)
00376 {
00377 double val = buf(ix,iy);
00378 sum_x=sum_x+val;
00379 sum_xx=sum_xx + val*val;
00380 N++;
00381 }
00382
00383
00384
00385 if (N)
00386 {
00387 mean=sum_x/N;
00388
00389 double var=sum_xx/N - mean*mean;
00390
00391 std= vcl_sqrt(var);
00392 }
00393 else
00394 {
00395 mean=0;
00396 std=0;
00397 }
00398 }
00399
00400
00401
00402 double vsrl_image_correlation::get_correlation(int x1, int y1, int x2, int y2)
00403 {
00404
00405
00406 if (!check_range(buffer1_,x1,y1) || !check_range(buffer2_,x2,y2))
00407 return 0.0;
00408
00409
00410
00411
00412
00413 int dx = window_width_/2;
00414 if (x1 < dx)
00415 dx=x1;
00416
00417 if (x2 < dx)
00418 dx=x2;
00419
00420 int low_x1 = x1-dx;
00421 int low_x2 = x2-dx;
00422
00423 dx=window_width_/2;
00424 if ((buffer1_.width()-1 -x1) < dx)
00425 dx=(buffer1_.width()-1 -x1);
00426
00427 if ((buffer2_.width()-1 -x2) < dx)
00428 dx=(buffer2_.width()-1 -x2);
00429
00430 int hi_x1= x1+dx;
00431
00432
00433
00434 int dy = window_height_/2;
00435 if (y1 < dy)
00436 dy=y1;
00437
00438 if (y2 < dy)
00439 dy=y2;
00440
00441 int low_y1 = y1-dy;
00442 int low_y2 = y2-dy;
00443
00444 dy=window_height_/2;
00445 if ((buffer1_.height()-1 -y1) < dy)
00446 dy=(buffer1_.height()-1 -y1);
00447
00448 if ((buffer2_.height()-1 -y2) < dy)
00449 dy=(buffer2_.height()-1 -y2);
00450
00451 int hi_y1= y1+dy;
00452
00453
00454
00455
00456 double mean1,std1,mean2,std2;
00457
00458 compute_local_stats(buffer1_,x1,y1,mean1,std1);
00459 compute_local_stats(buffer2_,x2,y2,mean2,std2);
00460
00461
00462
00463 if (std1 && std2)
00464 {
00465 double val1, val2;
00466 double N=0;
00467 double corr=0;
00468
00469 for (int i1=low_x1, i2=low_x2; i1<= hi_x1;i1++, i2++)
00470 for (int j1=low_y1, j2=low_y2; j1 <= hi_y1;j1++, j2++)
00471 {
00472 val1=buffer1_(i1,j1);
00473 val2=buffer2_(i2,j2);
00474
00475 corr=corr+((val1-mean1)/std1)*((val2-mean2)/std2);
00476 N++;
00477 }
00478
00479 if (N != 0)
00480 corr=corr/N;
00481
00482
00483 return corr;
00484 }
00485 else
00486 return 0.0;
00487 }
00488
00489
00490 double vsrl_image_correlation::get_sub_pixel_delta(int x1,int y1, int delta_x)
00491 {
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 int index = delta_x + correlation_range_;
00519
00520 if (index <1 || index >= (2*correlation_range_))
00521 return delta_x;
00522
00523
00524
00525 double Y1 = get_correlation(x1,y1,delta_x -1);
00526 double Y2 = get_correlation(x1,y1,delta_x);
00527 double Y3 = get_correlation(x1,y1,delta_x +1);
00528
00529 double a = 0.5*Y1 -Y2 + 0.5 *Y3;
00530 double b = 0.5*Y3 - 0.5*Y1;
00531
00532 double x_hat;
00533 if (a>=0)
00534 {
00535
00536
00537
00538 x_hat =0;
00539
00540 if (Y1 > Y3)
00541 x_hat = 0.0-0.5;
00542
00543 if (Y3 > Y1)
00544 x_hat = 0.5;
00545 }
00546 else
00547 {
00548
00549 x_hat = 0.0-b/ (2.0*a);
00550 if (x_hat >0.5)
00551 x_hat = 0.5;
00552
00553 if (x_hat < (0.0-0.5))
00554 x_hat = (0.0-0.5);
00555 }
00556
00557 return delta_x + x_hat;
00558 }
00559
00560
00561 void vsrl_image_correlation::get_correlation_stats(int x, int y, double &mean, double &std)
00562 {
00563
00564
00565
00566
00567 double N=0;
00568 double sum_z=0;
00569 double sum_zz=0;
00570
00571
00572
00573 for (int delta=0-correlation_range_;delta<correlation_range_+1;delta++)
00574 {
00575 double z = this->get_correlation(x,y,delta);
00576 sum_z += z;
00577 sum_zz += z*z;
00578 ++N;
00579 }
00580
00581 if (N!=0)
00582 {
00583 mean = sum_z/N;
00584 double var = sum_zz/N - mean*mean;
00585 std = vcl_sqrt(var);
00586 }
00587 }