00001
00002 #include "gevd_float_operators.h"
00003
00004
00005
00006 #include <vcl_iostream.h>
00007 #include <vcl_fstream.h>
00008 #include <vcl_algorithm.h>
00009 #include <vcl_cassert.h>
00010 #include <vnl/vnl_math.h>
00011 #include <vnl/vnl_float_3.h>
00012 #include <vnl/vnl_cross.h>
00013
00014 #include <vcl_cmath.h>
00015 #include <vcl_cstring.h>
00016
00017 #include "gevd_pixel.h"
00018 #include "gevd_xpixel.h"
00019 #include "gevd_bufferxy.h"
00020 #ifdef DEBUG
00021 # include <vul/vul_timer.h>
00022 #endif
00023
00024 #if defined(VCL_VC) || defined(VCL_BORLAND)
00025 inline static double rint(double v)
00026 {
00027 return v - vcl_floor(v) < 0.5 ? vcl_floor(v) : vcl_ceil(v);
00028 }
00029 #endif
00030
00031 const unsigned char DIR0 = 8, DIR1 = 9, DIR2 = 10, DIR3 = 11, DIR4 = 12;
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 float
00048 gevd_float_operators::Convolve(const gevd_bufferxy& from,
00049 const gevd_bufferxy& kernel,
00050 gevd_bufferxy*& to)
00051 {
00052 #ifdef DEBUG
00053 vul_timer t;
00054 vcl_cout << "Convolve image";
00055 #endif
00056 bool overwrite = to == &from;
00057 gevd_bufferxy*& t = to;
00058 if (overwrite) to=0;
00059 to = gevd_float_operators::Allocate(to, from);
00060 const int wx = kernel.GetSizeX(), wy = kernel.GetSizeY();
00061 const int rx = wx/2, ry = wy/2;
00062 const int xhi = from.GetSizeX() - wx + 1;
00063 const int yhi = from.GetSizeY() - wy + 1;
00064 for (int y = 0; y < yhi; y++)
00065 for (int x = 0; x < xhi; x++) {
00066 float conv = 0;
00067 for (int j = 0; j < wy; j++)
00068 for (int i = 0; i < wx; i++)
00069 conv += floatPixel(from, x+i, y+j) * floatPixel(kernel, i, j);
00070 floatPixel(*to, x+rx, y+ry) = conv;
00071 }
00072 FillFrameX(*to, 0, rx);
00073 FillFrameY(*to, 0, ry);
00074 #ifdef DEBUG
00075 vcl_cout << " in " << t.real() << " msecs.\n";
00076 #endif
00077 if (overwrite) { gevd_float_operators::Update(*t,*to); delete to; to = t; }
00078 return 1;
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 float
00090 gevd_float_operators::Correlation(const gevd_bufferxy& from,
00091 const gevd_bufferxy& kernel,
00092 gevd_bufferxy*& to)
00093 {
00094 #ifdef DEBUG
00095 vul_timer t;
00096 vcl_cout << "Correlate image";
00097 #endif
00098 bool overwrite = to == &from;
00099 gevd_bufferxy*& t = to;
00100 if (overwrite) to=0;
00101 to = gevd_float_operators::Allocate(to, from);
00102 const int wx = kernel.GetSizeX(), wy = kernel.GetSizeY();
00103 const int rx = wx/2, ry = wy/2;
00104 const int xhi = from.GetSizeX() - wx + 1;
00105 const int yhi = from.GetSizeY() - wy + 1;
00106 const int sum1 = wx*wy;
00107 for (int y = 0; y < yhi; y++)
00108 for (int x = 0; x < xhi; x++) {
00109 register double sumx=0, sumy=0, sumxx=0, sumyy=0, sumxy=0, xval, yval;
00110 for (int j = 0; j < wy; j++)
00111 for (int i = 0; i < wx; i++) {
00112 xval = floatPixel(from, x+i, y+j);
00113 yval = floatPixel(kernel, i, j);
00114 sumxy += xval * yval;
00115 sumx += xval;
00116 sumy += yval;
00117 sumxx += xval * xval;
00118 sumyy += yval * yval;
00119 }
00120 double varx = sum1 * sumxx - sumx * sumx;
00121 double vary = sum1 * sumyy - sumy * sumy;
00122 double cvar = sum1 * sumxy - sumx * sumy;
00123 if (varx!=0 && vary!=0) cvar /= vcl_sqrt(varx * vary);
00124 floatPixel(*to, x+rx, y+ry) = (float)cvar;
00125 }
00126 FillFrameX(*to, 0, rx);
00127 FillFrameY(*to, 0, ry);
00128 #ifdef DEBUG
00129 vcl_cout << " in " << t.real() << " msecs.\n";
00130 #endif
00131 if (overwrite) { gevd_float_operators::Update(*t,*to); delete to; to = t; }
00132 return 1;
00133 }
00134
00135
00136
00137
00138
00139 float
00140 gevd_float_operators::CorrelationAlongAxis(const gevd_bufferxy& from,
00141 const gevd_bufferxy& kernel,
00142 gevd_bufferxy*& to)
00143 {
00144 #ifdef DEBUG
00145 vul_timer t;
00146 vcl_cout << "Correlate image";
00147 #endif
00148 bool overwrite = to == &from;
00149 gevd_bufferxy*& t = to;
00150 if (overwrite) to=0;
00151 to = gevd_float_operators::Allocate(to, from);
00152 to->Clear();
00153 const int wx = kernel.GetSizeX(), wy = kernel.GetSizeY();
00154 const int rx = wx/2, ry = wy/2;
00155 const int xhi = from.GetSizeX() - wx + 1;
00156 const int yhi = from.GetSizeY() - wy + 1;
00157 const int sum1 = wx*wy;
00158 for (int x = 0, y = yhi/2; x < xhi; ++x) {
00159 register double sumx=0, sumy=0, sumxx=0, sumyy=0, sumxy=0, xval, yval;
00160 for (int j = 0; j < wy; j++)
00161 for (int i = 0; i < wx; i++) {
00162 xval = floatPixel(from, x+i, y+j);
00163 yval = floatPixel(kernel, i, j);
00164 sumxy += xval * yval;
00165 sumx += xval;
00166 sumy += yval;
00167 sumxx += xval * xval;
00168 sumyy += yval * yval;
00169 }
00170 double varx = sum1 * sumxx - sumx * sumx;
00171 double vary = sum1 * sumyy - sumy * sumy;
00172 double cvar = sum1 * sumxy - sumx * sumy;
00173 if (varx!=0 && vary!=0) cvar /= vcl_sqrt(varx * vary);
00174 floatPixel(*to, x+rx, y+ry) = (float)cvar;
00175 }
00176 for (int x = xhi/2, y = 0; y < yhi; ++y) {
00177 register double sumx=0, sumy=0, sumxx=0, sumyy=0, sumxy=0, xval, yval;
00178 for (int j = 0; j < wy; j++)
00179 for (int i = 0; i < wx; i++) {
00180 xval = floatPixel(from, x+i, y+j);
00181 yval = floatPixel(kernel, i, j);
00182 sumxy += xval * yval;
00183 sumx += xval;
00184 sumy += yval;
00185 sumxx += xval * xval;
00186 sumyy += yval * yval;
00187 }
00188 double varx = sum1 * sumxx - sumx * sumx;
00189 double vary = sum1 * sumyy - sumy * sumy;
00190 double cvar = sum1 * sumxy - sumx * sumy;
00191 if (varx!=0 && vary!=0) cvar /= vcl_sqrt(varx * vary);
00192 floatPixel(*to, x+rx, y+ry) = (float)cvar;
00193 }
00194 #ifdef DEBUG
00195 vcl_cout << " in " << t.real() << " msecs.\n";
00196 #endif
00197 if (overwrite) { gevd_float_operators::Update(*t,*to); delete to; to = t; }
00198 return 1;
00199 }
00200
00201
00202
00203
00204 gevd_bufferxy*
00205 gevd_float_operators::Read2dKernel(const char* filename)
00206 {
00207 vcl_ifstream infile(filename, vcl_ios_in);
00208 if (!infile)
00209 return NULL;
00210 int width, height;
00211 infile >> width;
00212 infile >> height;
00213 if (width < 1 || height < 1) return NULL;
00214 gevd_bufferxy* kernel = new gevd_bufferxy(width, height, bits_per_float);
00215 for (int y = 0; y < height; y++)
00216 for (int x = 0; x < width; x++)
00217 infile >> floatPixel(*kernel, x, y);
00218 return kernel;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228 float
00229 gevd_float_operators::Convolve(const gevd_bufferxy& from, gevd_bufferxy*& to,
00230 const float* xkernel, const int xradius,
00231 const bool xevenp,
00232 const float* ykernel, const int yradius,
00233 const bool yevenp,
00234 const bool xwrap, const bool ywrap)
00235 {
00236 #ifdef DEBUG
00237 vul_timer t;
00238 vcl_cout << "Convolve image";
00239 #endif
00240 bool overwrite = to == &from;
00241 gevd_bufferxy*& t = to;
00242 if (overwrite) to=0;
00243 to = gevd_float_operators::Allocate(to, from);
00244 const int sizeX = to->GetSizeX(), sizeY = to->GetSizeY();
00245 const int ylo = yradius, yhi = sizeY - yradius;
00246 const int kborder = 2*yradius;
00247
00248
00249 float** cache = new float*[4*yradius+1];
00250 float** pipeline = cache+yradius;
00251 float* row;
00252 for (int p = 0; p <= kborder; ++p) {
00253 pipeline[p] = row = new float[sizeX];
00254 gevd_float_operators::Convolve(&floatPixel(from, 0, p),
00255 row, sizeX,
00256 xkernel, xradius, xevenp, xwrap);
00257 }
00258 if (ywrap)
00259 for (int r = 1; r <= yradius; r++) {
00260 pipeline[-r] = row = new float[sizeX];
00261 gevd_float_operators::Convolve(&floatPixel(from, 0, sizeY-r),
00262 row, sizeX,
00263 xkernel, xradius, xevenp, xwrap);
00264 pipeline[kborder+r] = row = new float[sizeX];
00265 for (int i = 0; i < sizeX; i++)
00266 row[i] = pipeline[r-1][i];
00267 }
00268 else
00269 for (int r = 1; r <= yradius; r++) {
00270 pipeline[-r] = row = new float[sizeX];
00271 for (int i = 0; i < sizeX; i++)
00272 row[i] = pipeline[r][i];
00273 pipeline[kborder+r] = row = new float[sizeX];
00274 gevd_float_operators::Convolve(&floatPixel(from, 0, sizeY-1-r),
00275 row, sizeX,
00276 xkernel, xradius, xevenp, xwrap);
00277 }
00278
00279
00280 if (yevenp)
00281 {
00282 int y=0;
00283 for (int yy = 0; y < ylo; ++y, ++yy) {
00284 row = &floatPixel(*to, 0, y);
00285 for (int x = 0; x < sizeX; x++) {
00286 float sum = ykernel[yradius] * pipeline[yy][x];
00287 for (int k = 1; k <= yradius; k++)
00288 sum += ykernel[yradius-k] * (pipeline[yy-k][x] + pipeline[yy+k][x]);
00289 row[x] = sum;
00290 }
00291 }
00292 int p = kborder+1;
00293 for ( ; y < yhi; ++y) {
00294 row = &floatPixel(*to, 0, y);
00295 for (int x = 0; x < sizeX; x++) {
00296 float sum = ykernel[yradius] * pipeline[yradius][x];
00297 for (int k = 1; k <= yradius; k++)
00298 sum += ykernel[yradius-k] * (pipeline[yradius-k][x] +
00299 pipeline[yradius+k][x]);
00300 row[x] = sum;
00301 }
00302 if (p < sizeY) {
00303 row = pipeline[0];
00304 for (int k = 0; k < kborder; k++)
00305 pipeline[k] = pipeline[k+1];
00306 gevd_float_operators::Convolve(&floatPixel(from, 0, p++),
00307 row, sizeX,
00308 xkernel, xradius, xevenp, xwrap);
00309 pipeline[kborder] = row;
00310 }
00311 }
00312 for (int yy = yradius+1; y < sizeY; y++, yy++) {
00313 row = &floatPixel(*to, 0, y);
00314 for (int x = 0; x < sizeX; x++) {
00315 float sum = ykernel[yradius] * pipeline[yy][x];
00316 for (int k = 1; k <= yradius; k++)
00317 sum += ykernel[yradius-k] * (pipeline[yy-k][x] + pipeline[yy+k][x]);
00318 row[x] = sum;
00319 }
00320 }
00321 }
00322 else
00323 {
00324 int y=0;
00325 for (int yy = 0; y < ylo; y++, yy++) {
00326 row = &floatPixel(*to, 0, y);
00327 for (int x = 0; x < sizeX; x++) {
00328 float sum = ykernel[yradius] * pipeline[yy][x];
00329 for (int k = 1; k <= yradius; k++)
00330 sum += ykernel[yradius-k] * (pipeline[yy-k][x] - pipeline[yy+k][x]);
00331 row[x] = sum;
00332 }
00333 }
00334 int p = kborder+1;
00335 for ( ; y < yhi; y++) {
00336 row = &floatPixel(*to, 0, y);
00337 for (int x = 0; x < sizeX; x++) {
00338 float sum = ykernel[yradius] * pipeline[yradius][x];
00339 for (int k = 1; k <= yradius; k++)
00340 sum += ykernel[yradius-k] * (pipeline[yradius-k][x] -
00341 pipeline[yradius+k][x]);
00342 row[x] = sum;
00343 }
00344 if (p < sizeY) {
00345 row = pipeline[0];
00346 for (int k = 0; k < kborder; k++)
00347 pipeline[k] = pipeline[k+1];
00348 gevd_float_operators::Convolve(&floatPixel(from, 0, p++),
00349 row, sizeX,
00350 xkernel, xradius, xevenp, xwrap);
00351 pipeline[kborder] = row;
00352 }
00353 }
00354 for (int yy = yradius+1; y < sizeY; y++, yy++) {
00355 row = &floatPixel(*to, 0, y);
00356 for (int x = 0; x < sizeX; x++) {
00357 float sum = ykernel[yradius] * pipeline[yy][x];
00358 for (int k = 1; k <= yradius; k++)
00359 sum += ykernel[yradius-k] * (pipeline[yy-k][x] - pipeline[yy+k][x]);
00360 row[x] = sum;
00361 }
00362 }
00363 }
00364 for (int p = 0; p <= 4*yradius; p++)
00365 delete[] cache[p];
00366 delete[] cache;
00367 #ifdef DEBUG
00368 vcl_cout << " in " << t.real() << " msecs.\n";
00369 #endif
00370 if (overwrite) { gevd_float_operators::Update(*t,*to); delete to; to = t; }
00371 return 1;
00372 }
00373
00374
00375
00376
00377
00378 float
00379 gevd_float_operators::Convolve(const gevd_bufferxy& from, gevd_bufferxy*& to,
00380 const float* xkernel, const int xradius,
00381 const bool xevenp,
00382 const int yradius,
00383 const bool xwrap, const bool ywrap)
00384 {
00385 float* ykernel = new float[2*yradius+1];
00386 const bool yevenp = true;
00387 for (int i = 0; i < 2*yradius+1; i++)
00388 ykernel[i] = 1;
00389 float fact = gevd_float_operators::Convolve(from, to,
00390 xkernel, xradius, xevenp,
00391 ykernel, yradius, yevenp,
00392 xwrap, ywrap);
00393 delete[] ykernel;
00394 return fact;
00395 }
00396
00397 #if 0 // commented out
00398 {
00399 #ifdef DEBUG
00400 vul_timer t;
00401 vcl_cout << "Convolve image";
00402 #endif
00403 to = gevd_float_operators::Allocate(to, from);
00404 const int sizeX = to->GetSizeX(), sizeY = to->GetSizeY();
00405 const int ylo = yradius, yhi = sizeY - yradius;
00406 const int kborder = 2*yradius;
00407
00408
00409 float** cache = new float*[4*yradius+1];
00410 float** pipeline = cache+yradius;
00411 double* rsum = new double[sizeX];
00412 float* row = NULL;
00413 for (int p = 0; p <= kborder; p++) {
00414 pipeline[p] = row = new float[sizeX];
00415 gevd_float_operators::Convolve(&floatPixel(from, 0, p),
00416 row, sizeX,
00417 xkernel, xradius, xevenp, xwrap);
00418 }
00419
00420 if (ywrap)
00421 for (int r = 1; r <= yradius; r++) {
00422 pipeline[-r] = row = new float[sizeX];
00423 gevd_float_operators::Convolve(&floatPixel(from, 0, sizeY-r),
00424 row, sizeX,
00425 xkernel, xradius, xevenp, xwrap);
00426 pipeline[kborder+r] = row = new float[sizeX];
00427 for (int i = 0; i < sizeX; i++)
00428 row[i] = pipeline[r-1][i];
00429 }
00430 else
00431 for (int r = 1; r <= yradius; r++) {
00432 pipeline[-r] = row = new float[sizeX];
00433 for (int i = 0; i < sizeX; i++)
00434 row[i] = pipeline[r][i];
00435 pipeline[kborder+r] = row = new float[sizeX];
00436 gevd_float_operators::Convolve(&floatPixel(from, 0, sizeY-1-r),
00437 row, sizeX,
00438 xkernel, xradius, xevenp, xwrap);
00439 }
00440
00441
00442 int y = 0, yy = 0;
00443 row = &floatPixel(*to, 0, y);
00444 for (int x = 0; x < sizeX; x++) {
00445 double sum = pipeline[yy][x];
00446 for (int k = 1; k <= yradius; k++)
00447 sum += (pipeline[yy-k][x] + pipeline[yy+k][x]);
00448 row[x] = float(rsum[x] = sum);
00449 }
00450 for (y++, yy++; y < ylo; y++, yy++) {
00451 row = &floatPixel(*to, 0, y);
00452 for (int x = 0; x < sizeX; x++)
00453 row[x] = float(rsum[x] = rsum[x] -
00454 pipeline[yy-yradius-1][x] + pipeline[yy+yradius][x]);
00455 }
00456 for ( ; y < yhi; y++) {
00457 row = &floatPixel(*to, 0, y);
00458 for (int x = 0; x < sizeX; x++)
00459 row[x] = float(rsum[x] = rsum[x] -
00460 pipeline[-1][x] + pipeline[kborder][x]);
00461 if (p < sizeY) {
00462 row = pipeline[0];
00463 for (int k = 0; k < kborder; k++)
00464 pipeline[k] = pipeline[k+1];
00465 gevd_float_operators::Convolve(&floatPixel(from, 0, p++),
00466 row, sizeX,
00467 xkernel, xradius, xevenp, xwrap);
00468 pipeline[kborder] = row;
00469 }
00470 }
00471 for (yy = yradius+1; y < sizeY; y++, yy++) {
00472 row = &floatPixel(*to, 0, y);
00473 for (int x = 0; x < sizeX; x++)
00474 row[x] = float(rsum[x] = rsum[x] -
00475 pipeline[yy-yradius-1][x] + pipeline[yy+yradius][x]);
00476 }
00477 for (int p = 0; p <= 4*yradius; p++)
00478 delete[] cache[p];
00479 delete[] cache;
00480 delete[] rsum;
00481 #ifdef DEBUG
00482 vcl_cout << " in " << t.real() << " msecs.\n";
00483 #endif
00484 return 2*yradius+1;
00485 }
00486 #endif
00487
00488
00489
00490
00491
00492 float
00493 gevd_float_operators::Convolve(const float* from, float*& to, const int len,
00494 const float* kernel, const int kradius,
00495 const bool evenp, const bool wrap)
00496 {
00497 bool overwrite = to == from;
00498 float*& t = to;
00499 if (!to || overwrite) to = new float[len];
00500 const int xlo = kradius, xhi = len - kradius;
00501 const int kborder = 2*kradius;
00502 float *cache, *pipeline;
00503 int p = gevd_float_operators::SetupPipeline(from, len, kradius, wrap,
00504 cache, pipeline);
00505
00506
00507 float sum;
00508 if (evenp)
00509 {
00510 int x=0;
00511 for (int xx = 0; x < xlo; ++x, ++xx) {
00512 sum = kernel[kradius] * pipeline[xx];
00513 for (int k = 1; k <= kradius; k++)
00514 sum += kernel[kradius-k] * (pipeline[xx-k] + pipeline[xx+k]);
00515 to[x] = sum;
00516 }
00517 for ( ; x < xhi; x++) {
00518 sum = kernel[kradius] * pipeline[kradius];
00519 for (int k = 1; k <= kradius; k++)
00520 sum += kernel[kradius-k] * (pipeline[kradius-k] +
00521 pipeline[kradius+k]);
00522 to[x] = sum;
00523 if (p < len) {
00524 for (int k = 0; k < kborder; k++)
00525 pipeline[k] = pipeline[k+1];
00526 pipeline[kborder] = from[p++];
00527 }
00528 }
00529 for (int xx = kradius+1; x < len; x++, xx++) {
00530 sum = kernel[kradius] * pipeline[xx];
00531 for (int k = 1; k <= kradius; k++)
00532 sum += kernel[kradius-k] * (pipeline[xx-k] + pipeline[xx+k]);
00533 to[x] = sum;
00534 }
00535 }
00536 else
00537 {
00538 int x=0;
00539 for (int xx = 0; x < xlo; ++x, ++xx) {
00540 sum = kernel[kradius] * pipeline[xx];
00541 for (int k = 1; k <= kradius; k++)
00542 sum += kernel[kradius-k] * (pipeline[xx-k] - pipeline[xx+k]);
00543 to[x] = sum;
00544 }
00545 for ( ; x < xhi; x++) {
00546 sum = kernel[kradius] * from[x];
00547 for (int k = 1; k <= kradius; k++)
00548 sum += kernel[kradius-k] * (pipeline[kradius-k] -
00549 pipeline[kradius+k]);
00550 to[x] = sum;
00551 if (p < len) {
00552 for (int k = 0; k < kborder; k++)
00553 pipeline[k] = pipeline[k+1];
00554 pipeline[kborder] = from[p++];
00555 }
00556 }
00557 for (int xx = kradius+1; x < len; x++, xx++) {
00558 sum = kernel[kradius] * pipeline[xx];
00559 for (int k = 1; k <= kradius; k++)
00560 sum += kernel[kradius-k] * (pipeline[xx-k] - pipeline[xx+k]);
00561 to[x] = sum;
00562 }
00563 }
00564 delete[] cache;
00565 if (overwrite) {
00566 for (int x=0 ; x < len; ++x) t[x] = to[x];
00567 delete[] to;
00568 to = t;
00569 }
00570 return 1;
00571 }
00572
00573
00574
00575
00576 float
00577 gevd_float_operators::RunningSum(float* from, float*& to, const int len,
00578 const int kradius, const bool wrap)
00579 {
00580 bool overwrite = to == from;
00581 if (!to || overwrite) to = new float[len];
00582 const int xlo = kradius, xhi = len - kradius;
00583 const int kborder = 2*kradius;
00584 float *cache, *pipeline;
00585 int p = gevd_float_operators::SetupPipeline(from, len, kradius, wrap,
00586 cache, pipeline);
00587
00588 int x = 0, xx = 0;
00589 float sum = pipeline[x];
00590 for (int k = 1; k <= kradius; k++)
00591 sum += (pipeline[xx-k] + pipeline[xx+k]);
00592 to[x] = sum;
00593 for (x++, xx++; x < xlo; x++, xx++) {
00594 sum += pipeline[xx+kradius] - pipeline[xx-kradius-1];
00595 to[x] = sum;
00596 }
00597 for ( ; x < xhi; x++) {
00598 sum += pipeline[kborder] - pipeline[-1];
00599 to[x] = sum;
00600 if (p < len) {
00601 for (int k = -1; k < kborder; k++)
00602 pipeline[k] = pipeline[k+1];
00603 pipeline[kborder] = from[p++];
00604 }
00605 }
00606 for ( ; x < len; x++, xx++) {
00607 sum += pipeline[xx+kradius] - pipeline[xx-kradius-1];
00608 to[x] = sum;
00609 }
00610 delete[] cache;
00611 if (overwrite) {
00612 for (int x=0 ; x < len; ++x) from[x] = to[x];
00613 delete[] to;
00614 to = from;
00615 }
00616 return float(2*kradius+1);
00617 }
00618
00619
00620
00621 bool
00622 gevd_float_operators::Read1dKernel(const char* filename,
00623 float*& kernel, int& radius, bool& evenp)
00624 {
00625 vcl_ifstream infile(filename, vcl_ios_in);
00626 if (!infile)
00627 return false;
00628 int width;
00629 infile >> width;
00630 if (width < 1) return false;
00631 radius = (width - 1)/2;
00632 width = 2*radius + 1;
00633 delete[] kernel;
00634 kernel = new float[width];
00635 for (int i = 0; i < width; i++)
00636 infile >> kernel[i];
00637 evenp = true;
00638 for (int i = 1; i <= radius; i++)
00639 if (kernel[radius-i] != kernel[radius+i])
00640 evenp = false;
00641 if (evenp)
00642 return true;
00643 for (int i = 1; i <= radius; i++)
00644 if (kernel[radius-i] != -kernel[radius+i])
00645 evenp = true;
00646 if (!evenp)
00647 return true;
00648 delete[] kernel; kernel = NULL;
00649 return false;
00650 }
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 float
00661 gevd_float_operators::Gaussian(gevd_bufferxy& from, gevd_bufferxy*& to, const float sigma,
00662 const bool xwrap, const bool ywrap)
00663 {
00664 float* kernel = NULL;
00665 int radius = 0;
00666 if (!gevd_float_operators::Find1dGaussianKernel(sigma, kernel, radius)) {
00667 to = gevd_float_operators::Allocate(to, from);
00668 if (to != &from)
00669 gevd_float_operators::Update(*to, from);
00670 } else {
00671 bool evenp = true;
00672
00673 gevd_float_operators::Convolve(from, to,
00674 kernel, radius, evenp,
00675 kernel, radius, evenp,
00676 xwrap, ywrap);
00677 }
00678 delete[] kernel;
00679 return 1;
00680 }
00681
00682
00683
00684
00685
00686
00687
00688 bool
00689 gevd_float_operators::Find1dGaussianKernel(const float sigma,
00690 float*& kernel, int& radius,
00691 const float fuzz)
00692 {
00693 for (radius = 0; Gaussian(float(radius), sigma) > fuzz; radius++)
00694 {;}
00695 if (radius == 0)
00696 return false;
00697
00698 kernel = new float[2*radius + 1];
00699 for (int i=0; i<=radius; ++i)
00700 kernel[radius+i] = kernel[radius-i] = Gaussian(float(i), sigma);
00701 float sum = 0;
00702 for (int i= 0; i <= 2*radius; ++i)
00703 sum += kernel[i];
00704 for (int i= 0; i <= 2*radius; ++i)
00705 kernel[i] /= sum;
00706 #ifdef DEBUG
00707 vcl_cout << "Gaussian kernel = ";
00708 for (int i= 0; i <= 2*radius; ++i)
00709 vcl_cout << kernel[i] << ' ';
00710 vcl_cout << vcl_endl;
00711 #endif
00712 return true;
00713 }
00714
00715
00716 float
00717 gevd_float_operators::Gaussian(const float x, const float sigma)
00718 {
00719 double x_on_sigma = x / sigma;
00720 return (float)vcl_exp(- x_on_sigma * x_on_sigma / 2);
00721 }
00722
00723
00724
00725
00726
00727
00728
00729 int
00730 gevd_float_operators::SetupPipeline(const float* data, const int len,
00731 const int kradius, const bool wrap,
00732 float*& cache, float*& pipeline)
00733 {
00734 cache = new float[4*kradius+1];
00735 pipeline = cache+kradius;
00736 int p = 0;
00737 for (; p <= 2*kradius; p++) pipeline[p] = data[p];
00738 if (wrap)
00739 for (int r = 1; r <= kradius; r++) {
00740 pipeline[-r] = data[len-r];
00741 pipeline[2*kradius+r] = data[r-1];
00742 }
00743 else
00744 for (int r = 1; r <= kradius; r++) {
00745 pipeline[-r] = data[r];
00746 pipeline[2*kradius+r] = data[len-1-r];
00747 }
00748 return p;
00749 }
00750
00751
00752
00753 gevd_bufferxy*
00754 gevd_float_operators::WrapAlongX(const gevd_bufferxy& img)
00755 {
00756 const int lx = img.GetSizeX()-1, sy = img.GetSizeY();
00757 gevd_bufferxy* wrap = gevd_float_operators::SimilarBuffer(img, bits_per_float, 4, sy);
00758 for (int i = 0; i < 2; i++)
00759 for (int j = 0; j < sy; j++) {
00760 floatPixel(*wrap, 2+i, j) = floatPixel(img, i, j);
00761 floatPixel(*wrap, 1-i, j) = floatPixel(img, lx-i, j);
00762 }
00763 return wrap;
00764 }
00765
00766
00767 gevd_bufferxy*
00768 gevd_float_operators::WrapAlongY(const gevd_bufferxy& img)
00769 {
00770 const int sx = img.GetSizeX(), ly = img.GetSizeY()-1;
00771 gevd_bufferxy* wrap = gevd_float_operators::SimilarBuffer(img, bits_per_float, sx, 4);
00772 for (int j = 0; j < 2; j++)
00773 for (int i = 0; i < sx; i++) {
00774 floatPixel(*wrap, i, 2+j) = floatPixel(img, i, j);
00775 floatPixel(*wrap, i, 1-j) = floatPixel(img, i, ly-j);
00776 }
00777 return wrap;
00778 }
00779
00780
00781
00782 inline void
00783 LocalGradient(const gevd_bufferxy& smooth, const int i, const int j,
00784 float& mag, float& gx, float& gy)
00785 {
00786 gx = floatPixel(smooth, i+1, j) - floatPixel(smooth, i-1, j);
00787 gy = floatPixel(smooth, i, j+1) - floatPixel(smooth, i, j-1);
00788 mag = vcl_sqrt(gx*gx + gy*gy);
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805 float
00806 gevd_float_operators::Gradient(const gevd_bufferxy& smooth,
00807 gevd_bufferxy*& magnitude,
00808 gevd_bufferxy*& gradx, gevd_bufferxy*& grady,
00809 const bool xwrap, const bool ywrap)
00810 {
00811 #ifdef DEBUG
00812 vul_timer t;
00813 vcl_cout << "Compute local gradient magnitude/direction";
00814 #endif
00815 magnitude = gevd_float_operators::Allocate(magnitude, smooth);
00816 gradx = gevd_float_operators::Allocate(gradx, smooth);
00817 grady = gevd_float_operators::Allocate(grady, smooth);
00818
00819
00820 const int frame = 1;
00821 const int highx = smooth.GetSizeX() - frame;
00822 const int highy = smooth.GetSizeY() - frame;
00823 for (int j = frame; j < highy; ++j)
00824 for (int i = frame; i < highx; ++i)
00825 LocalGradient(smooth, i, j,
00826 floatPixel(*magnitude, i, j),
00827 floatPixel(*gradx, i, j),
00828 floatPixel(*grady, i, j));
00829
00830
00831 if (xwrap) {
00832 const int lo = 2, hi = 1;
00833 gevd_bufferxy* pad = gevd_float_operators::WrapAlongX(smooth);
00834 for (int j = 1; j < highy; ++j) {
00835 LocalGradient(*pad, lo, j,
00836 floatPixel(*magnitude, 0, j),
00837 floatPixel(*gradx, 0, j),
00838 floatPixel(*grady, 0, j));
00839 LocalGradient(*pad, hi, j,
00840 floatPixel(*magnitude, highx, j),
00841 floatPixel(*gradx, highx, j),
00842 floatPixel(*grady, highx, j));
00843 }
00844 delete pad;
00845 } else {
00846 gevd_float_operators::FillFrameX(*magnitude, 0, frame);
00847 gevd_float_operators::FillFrameX(*gradx, 0, frame);
00848 gevd_float_operators::FillFrameX(*grady, 0, frame);
00849 }
00850 if (ywrap) {
00851 const int lo = 2, hi = 1;
00852 gevd_bufferxy* pad = gevd_float_operators::WrapAlongY(smooth);
00853 for (int i = 1; i < highx; ++i) {
00854 LocalGradient(*pad, i, lo,
00855 floatPixel(*magnitude, i, 0),
00856 floatPixel(*gradx, i, 0),
00857 floatPixel(*grady, i, 0));
00858 LocalGradient(*pad, i, hi,
00859 floatPixel(*magnitude, i, highy),
00860 floatPixel(*gradx, i, highy),
00861 floatPixel(*grady, i, highy));
00862 }
00863 delete pad;
00864 } else {
00865 gevd_float_operators::FillFrameY(*magnitude, 0, frame);
00866 gevd_float_operators::FillFrameY(*gradx, 0, frame);
00867 gevd_float_operators::FillFrameY(*grady, 0, frame);
00868 }
00869 #ifdef DEBUG
00870 vcl_cout << ", in " << t.real() << " msecs.\n";
00871 #endif
00872 return 2;
00873 }
00874
00875
00876
00877
00878
00879 float
00880 gevd_float_operators::Slope(float* from, float*& to, const int len,
00881 const bool wrap)
00882 {
00883 bool overwrite = to == from;
00884 if (!to || overwrite) to = new float[len];
00885 const int xlo = 1, xhi = len - 1;
00886 float *cache = NULL, *pipeline;
00887 int p = gevd_float_operators::SetupPipeline(from, len, 1, wrap,
00888 cache, pipeline);
00889 to[0] = pipeline[+1] - pipeline[-1];
00890 for (int x = xlo; x < xhi; x++) {
00891 to[x] = pipeline[2] - pipeline[0];
00892 if (p < len) {
00893 for (int k = 0; k < 2; k++)
00894 pipeline[k] = pipeline[k+1];
00895 pipeline[2] = from[p++];
00896 }
00897 }
00898 to[xhi] = pipeline[3] - pipeline[1];
00899 delete[] cache;
00900 if (overwrite) {
00901 for (int x=0 ; x < len; ++x) from[x] = to[x];
00902 delete[] to;
00903 to = from;
00904 }
00905 return 2;
00906 }
00907
00908
00909
00910
00911
00912 void
00913 LocalHessian(const gevd_bufferxy& smooth, const int i, const int j,
00914 float& mag, float& dirx, float& diry)
00915 {
00916 float two_pij = 2 * floatPixel(smooth, i, j);
00917 float ddx = floatPixel(smooth, i+1, j) + floatPixel(smooth, i-1, j) - two_pij;
00918 float ddy = floatPixel(smooth, i, j+1) + floatPixel(smooth, i, j-1) - two_pij;
00919 float two_dxdy = (floatPixel(smooth, i+1, j+1) +
00920 floatPixel(smooth, i-1, j-1) -
00921 floatPixel(smooth, i-1, j+1) -
00922 floatPixel(smooth, i+1, j-1)) / 2;
00923 float ddx_plus_ddy = ddx + ddy;
00924 float ddx_minus_ddy = ddx - ddy;
00925 float theta = (two_dxdy==0 && ddx_minus_ddy==0) ? 0 :
00926 (float)vcl_atan2(two_dxdy, ddx_minus_ddy) / 2;
00927 if (ddx_plus_ddy < 0) {
00928 mag = - ddx_plus_ddy
00929 + vcl_sqrt((ddx_minus_ddy * ddx_minus_ddy) + (two_dxdy * two_dxdy));
00930 theta += (float)vnl_math::pi_over_2;
00931 } else {
00932 mag = + ddx_plus_ddy
00933 + vcl_sqrt((ddx_minus_ddy * ddx_minus_ddy) + (two_dxdy * two_dxdy));
00934 if (theta > 0)
00935 theta -= (float)vnl_math::pi;
00936 }
00937 dirx = (float)vcl_cos(theta);
00938 diry = (float)vcl_sin(theta);
00939 }
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951 float
00952 gevd_float_operators::Hessian(const gevd_bufferxy& smooth,
00953 gevd_bufferxy*& magnitude,
00954 gevd_bufferxy*& dirx, gevd_bufferxy*& diry,
00955 const bool xwrap, const bool ywrap)
00956 {
00957 #ifdef DEBUG
00958 vul_timer t;
00959 vcl_cout << "Compute local Hessian magnitude/direction";
00960 #endif
00961 magnitude = gevd_float_operators::Allocate(magnitude, smooth);
00962 dirx = gevd_float_operators::Allocate(dirx, smooth);
00963 diry = gevd_float_operators::Allocate(diry, smooth);
00964
00965
00966 const int frame = 1;
00967 const int highx = smooth.GetSizeX() - frame;
00968 const int highy = smooth.GetSizeY() - frame;
00969 for (int j = frame; j < highy; ++j)
00970 for (int i = frame; i < highx; ++i)
00971 LocalHessian(smooth, i, j,
00972 floatPixel(*magnitude, i, j),
00973 floatPixel(*dirx, i, j),
00974 floatPixel(*diry, i, j));
00975
00976
00977 if (xwrap) {
00978 const int lo = 2, hi = 1;
00979 gevd_bufferxy* pad = gevd_float_operators::WrapAlongX(smooth);
00980 for (int j = 1; j < highy; ++j) {
00981 LocalHessian(*pad, lo, j,
00982 floatPixel(*magnitude, 0, j),
00983 floatPixel(*dirx, 0, j),
00984 floatPixel(*diry, 0, j));
00985 LocalHessian(*pad, hi, j,
00986 floatPixel(*magnitude, highx, j),
00987 floatPixel(*dirx, highx, j),
00988 floatPixel(*diry, highx, j));
00989 }
00990 delete pad;
00991 } else {
00992 gevd_float_operators::FillFrameX(*magnitude, 0, frame);
00993 gevd_float_operators::FillFrameX(*dirx, 0, frame);
00994 gevd_float_operators::FillFrameX(*diry, 0, frame);
00995 }
00996 if (ywrap) {
00997 const int lo = 2, hi = 1;
00998 gevd_bufferxy* pad = gevd_float_operators::WrapAlongY(smooth);
00999 for (int i = 1; i < highx; ++i) {
01000 LocalHessian(*pad, i, lo,
01001 floatPixel(*magnitude, i, 0),
01002 floatPixel(*dirx, i, 0),
01003 floatPixel(*diry, i, 0));
01004 LocalHessian(*pad, i, hi,
01005 floatPixel(*magnitude, i, highy),
01006 floatPixel(*dirx, i, highy),
01007 floatPixel(*diry, i, highy));
01008 }
01009 delete pad;
01010 } else {
01011 gevd_float_operators::FillFrameY(*magnitude, 0, frame);
01012 gevd_float_operators::FillFrameY(*dirx, 0, frame);
01013 gevd_float_operators::FillFrameY(*diry, 0, frame);
01014 }
01015 #ifdef DEBUG
01016 vcl_cout << ", in " << t.real() << " msecs.\n";
01017 #endif
01018 return 2;
01019 }
01020
01021
01022
01023
01024 void
01025 LocalLaplacian(const gevd_bufferxy& smooth, const int i, const int j,
01026 float& mag, float& dirx, float& diry)
01027 {
01028 float two_pij = 2 * floatPixel(smooth, i, j);
01029 float ddx = floatPixel(smooth, i+1, j) + floatPixel(smooth, i-1, j) - two_pij;
01030 float ddy = floatPixel(smooth, i, j+1) + floatPixel(smooth, i, j-1) - two_pij;
01031 float diag1 = floatPixel(smooth, i+1, j+1) + floatPixel(smooth, i-1, j-1);
01032 float diag2 = floatPixel(smooth, i-1, j+1) + floatPixel(smooth, i+1, j-1);
01033 mag = 4*(ddx + ddy) - 2*two_pij + diag1 + diag2;
01034 #if 0 // commented out
01035 mag = (floatPixel(smooth, i+1, j+1) + floatPixel(smooth, i-1, j-1) +
01036 floatPixel(smooth, i-1, j+1) + floatPixel(smooth, i+1, j-1) +
01037 4 * (floatPixel(smooth, i+1, j) + floatPixel(smooth, i-1, j) +
01038 floatPixel(smooth, i, j+1) + floatPixel(smooth, i, j-1)) +
01039 -20 * floatPixel(smooth, i, j)) / 6;
01040 #endif
01041 float theta = (diag1==diag2 && ddx==ddy) ? 0 :
01042 (float)vcl_atan2((diag1 - diag2) / 2, ddx - ddy) / 2;
01043 if (mag < 0) {
01044 mag = - mag;
01045 theta += (float)vnl_math::pi_over_2;
01046 }
01047 dirx = (float)vcl_cos(theta);
01048 diry = (float)vcl_sin(theta);
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 float
01063 gevd_float_operators::Laplacian(const gevd_bufferxy& smooth,
01064 gevd_bufferxy*& magnitude,
01065 gevd_bufferxy*& dirx, gevd_bufferxy*& diry,
01066 const bool xwrap, const bool ywrap)
01067 {
01068 #ifdef DEBUG
01069 vul_timer t;
01070 vcl_cout << "Compute local Laplacian magnitude/direction";
01071 #endif
01072 magnitude = gevd_float_operators::Allocate(magnitude, smooth);
01073 dirx = gevd_float_operators::Allocate(dirx, smooth);
01074 diry = gevd_float_operators::Allocate(diry, smooth);
01075
01076
01077 const int frame = 1;
01078 const int highx = smooth.GetSizeX() - frame;
01079 const int highy = smooth.GetSizeY() - frame;
01080 for (int j = frame; j < highy; ++j)
01081 for (int i = frame; i < highx; ++i)
01082 LocalLaplacian(smooth, i, j,
01083 floatPixel(*magnitude, i, j),
01084 floatPixel(*dirx, i, j),
01085 floatPixel(*diry, i, j));
01086
01087
01088 if (xwrap) {
01089 const int lo = 2, hi = 1;
01090 gevd_bufferxy* pad = gevd_float_operators::WrapAlongX(smooth);
01091 for (int j = 1; j < highy; ++j) {
01092 LocalLaplacian(*pad, lo, j,
01093 floatPixel(*magnitude, 0, j),
01094 floatPixel(*dirx, 0, j),
01095 floatPixel(*diry, 0, j));
01096 LocalLaplacian(*pad, hi, j,
01097 floatPixel(*magnitude, highx, j),
01098 floatPixel(*dirx, highx, j),
01099 floatPixel(*diry, highx, j));
01100 }
01101 delete pad;
01102 } else {
01103 gevd_float_operators::FillFrameX(*magnitude, 0, frame);
01104 gevd_float_operators::FillFrameX(*dirx, 0, frame);
01105 gevd_float_operators::FillFrameX(*diry, 0, frame);
01106 }
01107 if (ywrap) {
01108 const int lo = 2, hi = 1;
01109 gevd_bufferxy* pad = gevd_float_operators::WrapAlongY(smooth);
01110