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 }
00671 else {
00672 bool evenp = true;
00673
00674 gevd_float_operators::Convolve(from, to,
00675 kernel, radius, evenp,
00676 kernel, radius, evenp,
00677 xwrap, ywrap);
00678 }
00679 delete[] kernel;
00680 return 1;
00681 }
00682
00683
00684
00685
00686
00687
00688
00689 bool
00690 gevd_float_operators::Find1dGaussianKernel(const float sigma,
00691 float*& kernel, int& radius,
00692 const float fuzz)
00693 {
00694 for (radius = 0; Gaussian(float(radius), sigma) > fuzz; radius++)
00695 {;}
00696 if (radius == 0)
00697 return false;
00698
00699 kernel = new float[2*radius + 1];
00700 for (int i=0; i<=radius; ++i)
00701 kernel[radius+i] = kernel[radius-i] = Gaussian(float(i), sigma);
00702 float sum = 0;
00703 for (int i= 0; i <= 2*radius; ++i)
00704 sum += kernel[i];
00705 for (int i= 0; i <= 2*radius; ++i)
00706 kernel[i] /= sum;
00707 #ifdef DEBUG
00708 vcl_cout << "Gaussian kernel = ";
00709 for (int i= 0; i <= 2*radius; ++i)
00710 vcl_cout << kernel[i] << ' ';
00711 vcl_cout << vcl_endl;
00712 #endif
00713 return true;
00714 }
00715
00716
00717 float
00718 gevd_float_operators::Gaussian(const float x, const float sigma)
00719 {
00720 double x_on_sigma = x / sigma;
00721 return (float)vcl_exp(- x_on_sigma * x_on_sigma / 2);
00722 }
00723
00724
00725
00726
00727
00728
00729
00730 int
00731 gevd_float_operators::SetupPipeline(const float* data, const int len,
00732 const int kradius, const bool wrap,
00733 float*& cache, float*& pipeline)
00734 {
00735 cache = new float[4*kradius+1];
00736 pipeline = cache+kradius;
00737 int p = 0;
00738 for (; p <= 2*kradius; p++) pipeline[p] = data[p];
00739 if (wrap)
00740 for (int r = 1; r <= kradius; r++) {
00741 pipeline[-r] = data[len-r];
00742 pipeline[2*kradius+r] = data[r-1];
00743 }
00744 else
00745 for (int r = 1; r <= kradius; r++) {
00746 pipeline[-r] = data[r];
00747 pipeline[2*kradius+r] = data[len-1-r];
00748 }
00749 return p;
00750 }
00751
00752
00753
00754 gevd_bufferxy*
00755 gevd_float_operators::WrapAlongX(const gevd_bufferxy& img)
00756 {
00757 const int lx = img.GetSizeX()-1, sy = img.GetSizeY();
00758 gevd_bufferxy* wrap = gevd_float_operators::SimilarBuffer(img, bits_per_float, 4, sy);
00759 for (int i = 0; i < 2; i++)
00760 for (int j = 0; j < sy; j++) {
00761 floatPixel(*wrap, 2+i, j) = floatPixel(img, i, j);
00762 floatPixel(*wrap, 1-i, j) = floatPixel(img, lx-i, j);
00763 }
00764 return wrap;
00765 }
00766
00767
00768 gevd_bufferxy*
00769 gevd_float_operators::WrapAlongY(const gevd_bufferxy& img)
00770 {
00771 const int sx = img.GetSizeX(), ly = img.GetSizeY()-1;
00772 gevd_bufferxy* wrap = gevd_float_operators::SimilarBuffer(img, bits_per_float, sx, 4);
00773 for (int j = 0; j < 2; j++)
00774 for (int i = 0; i < sx; i++) {
00775 floatPixel(*wrap, i, 2+j) = floatPixel(img, i, j);
00776 floatPixel(*wrap, i, 1-j) = floatPixel(img, i, ly-j);
00777 }
00778 return wrap;
00779 }
00780
00781
00782
00783 inline void
00784 LocalGradient(const gevd_bufferxy& smooth, const int i, const int j,
00785 float& mag, float& gx, float& gy)
00786 {
00787 gx = floatPixel(smooth, i+1, j) - floatPixel(smooth, i-1, j);
00788 gy = floatPixel(smooth, i, j+1) - floatPixel(smooth, i, j-1);
00789 mag = vcl_sqrt(gx*gx + gy*gy);
00790 }
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806 float
00807 gevd_float_operators::Gradient(const gevd_bufferxy& smooth,
00808 gevd_bufferxy*& magnitude,
00809 gevd_bufferxy*& gradx, gevd_bufferxy*& grady,
00810 const bool xwrap, const bool ywrap)
00811 {
00812 #ifdef DEBUG
00813 vul_timer t;
00814 vcl_cout << "Compute local gradient magnitude/direction";
00815 #endif
00816 magnitude = gevd_float_operators::Allocate(magnitude, smooth);
00817 gradx = gevd_float_operators::Allocate(gradx, smooth);
00818 grady = gevd_float_operators::Allocate(grady, smooth);
00819
00820
00821 const int frame = 1;
00822 const int highx = smooth.GetSizeX() - frame;
00823 const int highy = smooth.GetSizeY() - frame;
00824 for (int j = frame; j < highy; ++j)
00825 for (int i = frame; i < highx; ++i)
00826 LocalGradient(smooth, i, j,
00827 floatPixel(*magnitude, i, j),
00828 floatPixel(*gradx, i, j),
00829 floatPixel(*grady, i, j));
00830
00831
00832 if (xwrap) {
00833 const int lo = 2, hi = 1;
00834 gevd_bufferxy* pad = gevd_float_operators::WrapAlongX(smooth);
00835 for (int j = 1; j < highy; ++j) {
00836 LocalGradient(*pad, lo, j,
00837 floatPixel(*magnitude, 0, j),
00838 floatPixel(*gradx, 0, j),
00839 floatPixel(*grady, 0, j));
00840 LocalGradient(*pad, hi, j,
00841 floatPixel(*magnitude, highx, j),
00842 floatPixel(*gradx, highx, j),
00843 floatPixel(*grady, highx, j));
00844 }
00845 delete pad;
00846 }
00847 else {
00848 gevd_float_operators::FillFrameX(*magnitude, 0, frame);
00849 gevd_float_operators::FillFrameX(*gradx, 0, frame);
00850 gevd_float_operators::FillFrameX(*grady, 0, frame);
00851 }
00852 if (ywrap) {
00853 const int lo = 2, hi = 1;
00854 gevd_bufferxy* pad = gevd_float_operators::WrapAlongY(smooth);
00855 for (int i = 1; i < highx; ++i) {
00856 LocalGradient(*pad, i, lo,
00857 floatPixel(*magnitude, i, 0),
00858 floatPixel(*gradx, i, 0),
00859 floatPixel(*grady, i, 0));
00860 LocalGradient(*pad, i, hi,
00861 floatPixel(*magnitude, i, highy),
00862 floatPixel(*gradx, i, highy),
00863 floatPixel(*grady, i, highy));
00864 }
00865 delete pad;
00866 }
00867 else {
00868 gevd_float_operators::FillFrameY(*magnitude, 0, frame);
00869 gevd_float_operators::FillFrameY(*gradx, 0, frame);
00870 gevd_float_operators::FillFrameY(*grady, 0, frame);
00871 }
00872 #ifdef DEBUG
00873 vcl_cout << ", in " << t.real() << " msecs.\n";
00874 #endif
00875 return 2;
00876 }
00877
00878
00879
00880
00881
00882 float
00883 gevd_float_operators::Slope(float* from, float*& to, const int len,
00884 const bool wrap)
00885 {
00886 bool overwrite = to == from;
00887 if (!to || overwrite) to = new float[len];
00888 const int xlo = 1, xhi = len - 1;
00889 float *cache = NULL, *pipeline;
00890 int p = gevd_float_operators::SetupPipeline(from, len, 1, wrap,
00891 cache, pipeline);
00892 to[0] = pipeline[+1] - pipeline[-1];
00893 for (int x = xlo; x < xhi; x++) {
00894 to[x] = pipeline[2] - pipeline[0];
00895 if (p < len) {
00896 for (int k = 0; k < 2; k++)
00897 pipeline[k] = pipeline[k+1];
00898 pipeline[2] = from[p++];
00899 }
00900 }
00901 to[xhi] = pipeline[3] - pipeline[1];
00902 delete[] cache;
00903 if (overwrite) {
00904 for (int x=0 ; x < len; ++x) from[x] = to[x];
00905 delete[] to;
00906 to = from;
00907 }
00908 return 2;
00909 }
00910
00911
00912
00913
00914
00915 void
00916 LocalHessian(const gevd_bufferxy& smooth, const int i, const int j,
00917 float& mag, float& dirx, float& diry)
00918 {
00919 float two_pij = 2 * floatPixel(smooth, i, j);
00920 float ddx = floatPixel(smooth, i+1, j) + floatPixel(smooth, i-1, j) - two_pij;
00921 float ddy = floatPixel(smooth, i, j+1) + floatPixel(smooth, i, j-1) - two_pij;
00922 float two_dxdy = (floatPixel(smooth, i+1, j+1) +
00923 floatPixel(smooth, i-1, j-1) -
00924 floatPixel(smooth, i-1, j+1) -
00925 floatPixel(smooth, i+1, j-1)) / 2;
00926 float ddx_plus_ddy = ddx + ddy;
00927 float ddx_minus_ddy = ddx - ddy;
00928 float theta = (two_dxdy==0 && ddx_minus_ddy==0) ? 0 :
00929 (float)vcl_atan2(two_dxdy, ddx_minus_ddy) / 2;
00930 if (ddx_plus_ddy < 0) {
00931 mag = - ddx_plus_ddy
00932 + vcl_sqrt((ddx_minus_ddy * ddx_minus_ddy) + (two_dxdy * two_dxdy));
00933 theta += (float)vnl_math::pi_over_2;
00934 }
00935 else {
00936 mag = + ddx_plus_ddy
00937 + vcl_sqrt((ddx_minus_ddy * ddx_minus_ddy) + (two_dxdy * two_dxdy));
00938 if (theta > 0)
00939 theta -= (float)vnl_math::pi;
00940 }
00941 dirx = (float)vcl_cos(theta);
00942 diry = (float)vcl_sin(theta);
00943 }
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955 float
00956 gevd_float_operators::Hessian(const gevd_bufferxy& smooth,
00957 gevd_bufferxy*& magnitude,
00958 gevd_bufferxy*& dirx, gevd_bufferxy*& diry,
00959 const bool xwrap, const bool ywrap)
00960 {
00961 #ifdef DEBUG
00962 vul_timer t;
00963 vcl_cout << "Compute local Hessian magnitude/direction";
00964 #endif
00965 magnitude = gevd_float_operators::Allocate(magnitude, smooth);
00966 dirx = gevd_float_operators::Allocate(dirx, smooth);
00967 diry = gevd_float_operators::Allocate(diry, smooth);
00968
00969
00970 const int frame = 1;
00971 const int highx = smooth.GetSizeX() - frame;
00972 const int highy = smooth.GetSizeY() - frame;
00973 for (int j = frame; j < highy; ++j)
00974 for (int i = frame; i < highx; ++i)
00975 LocalHessian(smooth, i, j,
00976 floatPixel(*magnitude, i, j),
00977 floatPixel(*dirx, i, j),
00978 floatPixel(*diry, i, j));
00979
00980
00981 if (xwrap) {
00982 const int lo = 2, hi = 1;
00983 gevd_bufferxy* pad = gevd_float_operators::WrapAlongX(smooth);
00984 for (int j = 1; j < highy; ++j) {
00985 LocalHessian(*pad, lo, j,
00986 floatPixel(*magnitude, 0, j),
00987 floatPixel(*dirx, 0, j),
00988 floatPixel(*diry, 0, j));
00989 LocalHessian(*pad, hi, j,
00990 floatPixel(*magnitude, highx, j),
00991 floatPixel(*dirx, highx, j),
00992 floatPixel(*diry, highx, j));
00993 }
00994 delete pad;
00995 }
00996 else {
00997 gevd_float_operators::FillFrameX(*magnitude, 0, frame);
00998 gevd_float_operators::FillFrameX(*dirx, 0, frame);
00999 gevd_float_operators::FillFrameX(*diry, 0, frame);
01000 }
01001 if (ywrap) {
01002 const int lo = 2, hi = 1;
01003 gevd_bufferxy* pad = gevd_float_operators::WrapAlongY(smooth);
01004 for (int i = 1; i < highx; ++i) {
01005 LocalHessian(*pad, i, lo,
01006 floatPixel(*magnitude, i, 0),
01007 floatPixel(*dirx, i, 0),
01008 floatPixel(*diry, i, 0));
01009 LocalHessian(*pad, i, hi,
01010 floatPixel(*magnitude, i, highy),
01011 floatPixel(*dirx, i, highy),
01012 floatPixel(*diry, i, highy));
01013 }
01014 delete pad;
01015 }
01016 else {
01017 gevd_float_operators::FillFrameY(*magnitude, 0, frame);
01018 gevd_float_operators::FillFrameY(*dirx, 0, frame);
01019 gevd_float_operators::FillFrameY(*diry, 0, frame);
01020 }
01021 #ifdef DEBUG
01022 vcl_cout << ", in " << t.real() << " msecs.\n";
01023 #endif
01024 return 2;
01025 }
01026
01027
01028
01029
01030 void
01031 LocalLaplacian(const gevd_bufferxy& smooth, const int i, const int j,
01032 float& mag, float& dirx, float& diry)
01033 {
01034 float two_pij = 2 * floatPixel(smooth, i, j);
01035 float ddx = floatPixel(smooth, i+1, j) + floatPixel(smooth, i-1, j) - two_pij;
01036 float ddy = floatPixel(smooth, i, j+1) + floatPixel(smooth, i, j-1) - two_pij;
01037 float diag1 = floatPixel(smooth, i+1, j+1) + floatPixel(smooth, i-1, j-1);
01038 float diag2 = floatPixel(smooth, i-1, j+1) + floatPixel(smooth, i+1, j-1);
01039 mag = 4*(ddx + ddy) - 2*two_pij + diag1 + diag2;
01040 #if 0 // commented out
01041 mag = (floatPixel(smooth, i+1, j+1) + floatPixel(smooth, i-1, j-1) +
01042 floatPixel(smooth, i-1, j+1) + floatPixel(smooth, i+1, j-1) +
01043 4 * (floatPixel(smooth, i+1, j) + floatPixel(smooth, i-1, j) +
01044 floatPixel(smooth, i, j+1) + floatPixel(smooth, i, j-1)) +
01045 -20 * floatPixel(smooth, i, j)) / 6;
01046 #endif
01047 float theta = (diag1==diag2 && ddx==ddy) ? 0 :
01048 (float)vcl_atan2((diag1 - diag2) / 2, ddx - ddy) / 2;
01049 if (mag < 0) {
01050 mag = - mag;
01051 theta += (float)vnl_math::pi_over_2;
01052 }
01053 dirx = (float)vcl_cos(theta);
01054 diry = (float)vcl_sin(theta);
01055 }
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 float
01069 gevd_float_operators::Laplacian(const gevd_bufferxy& smooth,
01070 gevd_bufferxy*& magnitude,
01071 gevd_bufferxy*& dirx, gevd_bufferxy*& diry,
01072 const bool xwrap, const bool ywrap)
01073 {
01074 #ifdef DEBUG
01075 vul_timer t;
01076 vcl_cout << "Compute local Laplacian magnitude/direction";
01077 #endif
01078 magnitude = gevd_float_operators::Allocate(magnitude, smooth);
01079 dirx = gevd_float_operators::Allocate(dirx, smooth);
01080 diry = gevd_float_operators::Allocate(diry, smooth);
01081
01082
01083 const int frame = 1;
01084 const int highx = smooth.GetSizeX() - frame;
01085 const int highy = smooth.GetSizeY() - frame;
01086 for (int j = frame; j < highy; ++j)
01087 for (int i = frame; i < highx; ++i)
01088 LocalLaplacian(smooth, i, j,
01089 floatPixel(*magnitude, i, j),
01090 floatPixel(*dirx, i, j),
01091 floatPixel(*diry, i, j));
01092
01093
01094 if (xwrap) {
01095 const int lo = 2, hi = 1;
01096 gevd_bufferxy* pad = gevd_float_operators::WrapAlongX(smooth);
01097 for (int j = 1; j < highy; ++j) {
01098 LocalLaplacian(*pad, lo, j,
01099 floatPixel(*magnitude, 0, j),
01100 floatPixel(*dirx, 0, j),
01101 floatPixel(*diry, 0, j));
01102 LocalLaplacian(*pad, hi, j,
01103 floatPixel(*magnitude, highx, j),
01104 floatPixel(*dirx, highx, j),
01105 floatPixel(*diry, highx, j));
01106 }
01107 delete pad;
01108 }
01109 else {
01110 gevd_float_operators::FillFrameX(*magnitude, 0, frame);
01111 gevd_float_operators::FillFrameX(*dirx, 0, frame);
01112 gevd_float_operators::FillFrameX(*diry, 0, frame);
01113 }
01114 if (ywrap) {
01115 const int lo = 2, hi = 1;
01116 gevd_bufferxy* pad = gevd_float_operators::WrapAlongY(smooth);
01117 for (int i = 1; i < highx; ++i) {
01118 LocalLaplacian(*pad, i, lo,
01119 floatPixel(*magnitude, i, 0),
01120 floatPixel(*dirx, i, 0),
01121 floatPixel(*diry, i, 0));
01122 LocalLaplacian(*pad, i, hi,
01123 floatPixel(*magnitude, i, highy),
01124 floatPixel(*dirx, i, highy),
01125 floatPixel(*diry, i, highy));
01126 }
01127 delete pad;
01128 }
01129 else {
01130 gevd_float_operators::FillFrameY(*magnitude, 0, frame);
01131 gevd_float_operators::FillFrameY(*dirx, 0, frame);
01132 gevd_float_operators::FillFrameY(*diry, 0, frame);
01133 }
01134 #ifdef DEBUG
01135 vcl_cout << ", in " << t.real() << " msecs.\n";
01136 #endif
01137 return 6;
01138 }
01139
01140
01141
01142
01143
01144 float
01145 gevd_float_operators::Curvature(float* from, float*& to, const int len,
01146 const bool wrap)
01147 {
01148 bool overwrite = to == from;
01149 if (!to || overwrite) to = new float[len];
01150 const int xlo = 1, xhi = len - 1;
01151 float *cache, *pipeline;
01152 int p = gevd_float_operators::SetupPipeline(from, len, 1, wrap,
01153 cache, pipeline);
01154 to[0] = pipeline[+1] + pipeline[-1] - 2*pipeline[0];
01155 for (int x = xlo; x < xhi; x++) {
01156 to[x] = pipeline[2] + pipeline[0] - 2*pipeline[1];
01157 if (p < len) {
01158 for (int k = 0; k < 2; k++)
01159 pipeline[k] = pipeline[k+1];
01160 pipeline[2] = from[p++];
01161 }
01162 }
01163 to[xhi] = pipeline[3] + pipeline[1] - 2*pipeline[2];
01164 delete[] cache;
01165 if (overwrite) {
01166 for (int x=0 ; x < len; ++x) from[x] = to[x];
01167 delete[] to;
01168 to = from;
01169 }
01170 return 1;
01171 }
01172
01173
01174
01175
01176
01177
01178 float
01179 gevd_float_operators::Orientation(const gevd_bufferxy& smooth,
01180 gevd_bufferxy*& theta, gevd_bufferxy*& coherence,
01181 const int frame)
01182 {
01183 theta = gevd_float_operators::Allocate(theta, smooth);
01184 coherence = gevd_float_operators::Allocate(coherence, smooth);
01185 gevd_bufferxy& thetaI = *theta;
01186 gevd_bufferxy& coherenceI = *coherence;
01187 int highx = smooth.GetSizeX() - frame;
01188 int highy = smooth.GetSizeY() - frame;
01189 float dx, dy;
01190 float p_ij, ox, oy;
01191 for (int j = frame; j < highy; ++j)
01192 for (int i = frame; i < highx; ++i) {
01193 p_ij = floatPixel(smooth, i, j);
01194 dx = floatPixel(smooth, i+1, j) - p_ij;
01195 dy = floatPixel(smooth, i, j+1) - p_ij;
01196 ox = (dy * dy) - (dx * dx);
01197 oy = 2 * dx * dy;
01198 floatPixel(thetaI, i, j) = (float)vcl_atan2(oy, ox);
01199 floatPixel(coherenceI, i, j) = ((ox * ox + oy * oy) /
01200 (dx + dy) * (dx + dy));
01201 }
01202 gevd_float_operators::FillFrameX(thetaI, 0, frame);
01203 gevd_float_operators::FillFrameY(thetaI, 0, frame);
01204 gevd_float_operators::FillFrameX(coherenceI, 0, frame);
01205 gevd_float_operators::FillFrameY(coherenceI, 0, frame);
01206 return 1;
01207 }
01208
01209
01210
01211 inline void
01212 LocalMaximum(const gevd_bufferxy& magnitude,
01213 const gevd_bufferxy& directionx, const gevd_bufferxy& directiony,
01214 const int i, const int j, const float threshold,
01215 float& contour, unsigned char& dir,
01216 float& locx, float& locy)
01217 {
01218 const float tan_pi_8 = (float)vcl_tan(vnl_math::pi_over_4/2);
01219 float strength = floatPixel(magnitude, i, j);
01220 if (strength > threshold) {
01221 float dx = floatPixel(directionx, i, j);
01222 float dy = floatPixel(directiony, i, j);
01223 if (dy < 0) {
01224 dx = -dx, dy = -dy;
01225 dir = DIR4 - DIR0;
01226 }
01227 else
01228 dir = 0;
01229 float sl, sr, r;
01230 if (dx > 0) {
01231 if (dx > dy) {
01232 r = dy / dx;
01233 sl = (r*floatPixel(magnitude, i-1, j-1) +
01234 (1-r)*floatPixel(magnitude, i-1, j));
01235 sr = (r*floatPixel(magnitude, i+1, j+1) +
01236 (1-r)*floatPixel(magnitude, i+1, j));
01237 dx = 1, dy = r;
01238 dir += (r < tan_pi_8)? DIR0 : DIR1;
01239 }
01240 else {
01241 r = dx / dy;
01242 sl = (r*floatPixel(magnitude, i-1, j-1) +
01243 (1-r)*floatPixel(magnitude, i, j-1));
01244 sr = (r*floatPixel(magnitude, i+1, j+1) +
01245 (1-r)*floatPixel(magnitude, i, j+1));
01246 dy = 1, dx = r;
01247 dir += (r < tan_pi_8)? DIR2 : DIR1;
01248 }
01249 }
01250 else {
01251 dx = -dx;
01252 if (dy > dx) {
01253 r = dx / dy;
01254 sl = (r*floatPixel(magnitude, i-1, j+1) +
01255 (1-r)*floatPixel(magnitude, i, j+1));
01256 sr = (r*floatPixel(magnitude, i+1, j-1) +
01257 (1-r)*floatPixel(magnitude, i, j-1));
01258 dy = -1, dx = r;
01259 dir += (r < tan_pi_8)? DIR2 : DIR3;
01260 }
01261 else {
01262 r = dy / dx;
01263 sl = (r*floatPixel(magnitude, i+1, j-1) +
01264 (1-r)*floatPixel(magnitude, i+1, j));
01265 sr = (r*floatPixel(magnitude, i-1, j+1) +
01266 (1-r)*floatPixel(magnitude, i-1, j));
01267 dx = -1, dy = r;
01268 dir += (r < tan_pi_8)? DIR0 : DIR3;
01269 }
01270 }
01271 if (sl < strength &&
01272 strength >= sr) {
01273 r = gevd_float_operators::InterpolateParabola(sl, strength, sr,
01274 contour);
01275 locx = r*dx;
01276 locy = r*dy;
01277 }
01278 else
01279 contour = 0;
01280 }
01281 else
01282 contour = 0;
01283 }
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293 void
01294 gevd_float_operators::NonMaximumSuppression(const gevd_bufferxy& magnitude,
01295 const gevd_bufferxy& directionx,
01296 const gevd_bufferxy& directiony,
01297 const float threshold,
01298 gevd_bufferxy*& contour,
01299 gevd_bufferxy*& direction,
01300 gevd_bufferxy*& locationx,
01301 gevd_bufferxy*& locationy,
01302 const bool xwrap,
01303 const bool ywrap)
01304 {
01305 #ifdef DEBUG
01306 vul_timer t;
01307 vcl_cout << "Non maximum suppression to find edge elements > " << threshold;
01308 #endif
01309 contour = gevd_float_operators::Allocate(contour, magnitude);
01310 direction = gevd_float_operators::Allocate(direction, magnitude, bits_per_byte);
01311 locationx = gevd_float_operators::Allocate(locationx, magnitude);
01312 locationy = gevd_float_operators::Allocate(locationy, magnitude);
01313 locationx->Clear(); locationy->Clear();
01314
01315
01316 const int frame = 1;
01317 const int highx = magnitude.GetSizeX() - frame;
01318 const int highy = magnitude.GetSizeY() - frame;
01319 for (int j = frame; j < highy; ++j)
01320 for (int i = frame; i < highx; ++i)
01321 LocalMaximum(magnitude, directionx, directiony,
01322 i, j, threshold,
01323 floatPixel(*contour, i, j),
01324 bytePixel(*direction, i, j),
01325 floatPixel(*locationx, i, j),
01326 floatPixel(*locationy, i, j));
01327
01328
01329 if (xwrap) {
01330 const int lo = 2, hi = 1;
01331 gevd_bufferxy* mag = gevd_float_operators::WrapAlongX(magnitude);
01332 gevd_bufferxy* dirx = gevd_float_operators::WrapAlongX(directionx);
01333 gevd_bufferxy* diry = gevd_float_operators::WrapAlongX(directiony);
01334 for (int j = 1; j < highy; ++j) {
01335 LocalMaximum(*mag, *dirx, *diry,
01336 lo, j, threshold,
01337 floatPixel(*contour, 0, j),
01338 bytePixel(*direction, 0, j),
01339 floatPixel(*locationx, 0, j),
01340 floatPixel(*locationy, 0, j));
01341 LocalMaximum(*mag, *dirx, *diry,
01342 hi, j, threshold,
01343 floatPixel(*contour, highx, j),
01344 bytePixel(*direction, highx, j),
01345 floatPixel(*locationx, highx, j),
01346 floatPixel(*locationy, highx, j));
01347 }
01348 delete mag; delete dirx; delete diry;
01349 }
01350 else {
01351 gevd_float_operators::FillFrameX(*contour, 0, frame);
01352 for (int j = 1; j < highy; ++j) {
01353 bytePixel(*direction, 0, j) = 0;
01354 bytePixel(*direction, highx, j) = 0;
01355 }
01356 }
01357 if (ywrap) {
01358 const int lo = 2, hi = 1;
01359 gevd_bufferxy* mag = gevd_float_operators::WrapAlongY(magnitude);
01360 gevd_bufferxy* dirx = gevd_float_operators::WrapAlongY(directionx);
01361 gevd_bufferxy* diry = gevd_float_operators::WrapAlongY(directiony);
01362 for (int i = 1; i < highx; ++i) {
01363 LocalMaximum(*mag, *dirx, *diry,
01364 i, lo, threshold,
01365 floatPixel(*contour, i, 0),
01366 bytePixel(*direction, i, 0),
01367 floatPixel(*locationx, i, 0),
01368 floatPixel(*locationy, i, 0));
01369 LocalMaximum(*mag, *dirx, *diry,
01370 i, hi, threshold,
01371 floatPixel(*contour, i, highy),
01372 bytePixel(*direction, i, highy),
01373 floatPixel(*locationx, i, highy),
01374 floatPixel(*locationy, i, highy));
01375 }
01376 delete mag; delete dirx; delete diry;
01377 }
01378 else {
01379 gevd_float_operators::FillFrameY(*contour, 0, frame);
01380 for (int i = 1; i < highx; ++i) {
01381 bytePixel(*direction, i, 0) = 0;
01382 bytePixel(*direction, i, highy) = 0;
01383 }
01384 }
01385 #ifdef DEBUG
01386 vcl_cout << ", in " << t.real() << " msecs.\n";
01387 #endif
01388 }
01389
01390
01391
01392 int
01393 gevd_float_operators::NonMaximumSuppression(const float* data, const int len,
01394 const float threshold,
01395 int*& index, float*& mag, float*& loc,
01396 const bool wrap)
01397 {
01398 if (!index) index = new int[len/2];
01399 if (!mag) mag = new float[len/2];
01400 if (!loc) loc = new float[len/2];
01401 const int xlo = 1, xhi = len - 1;
01402 float *cache, *pipeline;
01403 int p = gevd_float_operators::SetupPipeline(data, len, 1, wrap,
01404 cache, pipeline);
01405 int nmax = 0;
01406 if (pipeline[0] > threshold &&
01407 pipeline[0] > pipeline[+1] &&
01408 pipeline[0] > pipeline[-1]) {
01409 index[nmax] = 0;
01410 loc[nmax] = gevd_float_operators::InterpolateParabola(pipeline[-1], pipeline[0],
01411 pipeline[+1], mag[nmax]);
01412 nmax++;
01413 }
01414 for (int x = xlo; x < xhi; x++) {
01415 if (pipeline[1] > threshold &&
01416 pipeline[1] > pipeline[2] &&
01417 pipeline[1] > pipeline[0]) {
01418 index[nmax] = x;
01419 loc[nmax] = gevd_float_operators::InterpolateParabola(pipeline[0], pipeline[1],
01420 pipeline[2], mag[nmax]);
01421 nmax++;
01422 }
01423 if (p < len) {
01424 for (int k = 0; k < 2; k++)
01425 pipeline[k] = pipeline[k+1];
01426 pipeline[2] = data[p++];
01427 }
01428 }
01429 if (pipeline[2] > threshold &&
01430 pipeline[2] > pipeline[3] &&
01431 pipeline[2] > pipeline[1]) {
01432 index[nmax] = xhi;
01433 loc[nmax] = gevd_float_operators::InterpolateParabola(pipeline[1], pipeline[2],
01434 pipeline[3], mag[nmax]);
01435 nmax++;
01436 }
01437 delete[] cache;
01438 return nmax;
01439 }
01440
01441
01442
01443
01444 float
01445 gevd_float_operators::InterpolateParabola(float y_1, float y_0, float y_2,
01446 float&y)
01447 {
01448 float diff1 = y_2 - y_1;
01449 float diff2 = 2 * y_0 - y_1 - y_2;
01450 y = y_0 + diff1 * diff1 / (8 * diff2);
01451 return diff1 / (2 * diff2);
01452 }
01453
01454
01455
01456 float
01457 gevd_float_operators::BilinearInterpolate(const gevd_bufferxy& buffer,
01458 float x, float y)
01459 {
01460 register int ix = int(x);
01461 register int iy = int(y);
01462 float fx = x - ix;
01463 float fy = y - iy;
01464 float c00 = floatPixel(buffer, ix, iy);
01465 float c01 = floatPixel(buffer, ix, iy+1);
01466 float c10 = floatPixel(buffer, ix+1, iy);
01467 float c11 = floatPixel(buffer, ix+1, iy+1);
01468 float c0 = c00 + fy * (c01 - c00);
01469 float c1 = c10 + fy * (c11 - c10);
01470 return c0 + fx * (c1 - c0);
01471 }
01472
01473
01474
01475
01476 void
01477 gevd_float_operators::SupportAngle(const gevd_bufferxy& dirx, const gevd_bufferxy& diry,
01478 const gevd_bufferxy& magnitude,
01479 gevd_bufferxy*& angLe)
01480 {
01481 angLe = gevd_float_operators::Allocate(angLe, magnitude);
01482 const int highx = magnitude.GetSizeX();
01483 const int highy = magnitude.GetSizeY();
01484 float theta;
01485 for (int j = 0; j < highy; ++j)
01486 for (int i = 0; i < highx; ++i)
01487 if (floatPixel(magnitude, i, j) > 0) {
01488 theta = (float)vcl_atan2(floatPixel(diry, i, j), floatPixel(dirx, i, j));
01489 if (theta < 0) theta += (float)vnl_math::pi;
01490 floatPixel(*angLe, i, j) = theta * float(vnl_math::deg_per_rad);
01491 }
01492 }
01493
01494
01495
01496
01497
01498
01499 void
01500 gevd_float_operators::SurfaceNormal(const gevd_bufferxy& range, gevd_bufferxy*& normal)
01501 {
01502 const int frame = 1;
01503 const int highx = range.GetSizeX()-frame, highy = range.GetSizeY()-frame;
01504 normal = gevd_float_operators::Allocate(normal, range, bits_per_ptr);
01505 normal->Clear();
01506 vnl_float_3 tx(2.f,0.f,0.f), ty(0.f,2.f,0.f);
01507 for (int j = frame; j < highy; j++)
01508 for (int i = frame; i < highx; i++) {
01509 tx[2] = floatPixel(range, i+1, j) - floatPixel(range, i-1, j);
01510 ty[2] = floatPixel(range, i, j+1) - floatPixel(range, i, j-1);
01511
01512 vnl_vector<float> *nz= new vnl_vector<float>(vnl_cross_3d(tx,ty).as_ref());
01513
01514 float mag = nz->magnitude();
01515 if (mag != 0) *nz /= mag;
01516 fvectorPixel(*normal, i, j) = nz;
01517 }
01518 }
01519
01520
01521
01522
01523
01524
01525
01526 void
01527 gevd_float_operators::SurfaceCurvature(const gevd_bufferxy& normal, gevd_bufferxy*& curvature)
01528 {
01529 const int frame = 2;
01530 const int highx = normal.GetSizeX()-frame, highy = normal.GetSizeY()-frame;
01531 curvature = gevd_float_operators::Allocate(curvature, normal, bits_per_float);
01532 for (int j = frame; j < highy; j++)
01533 for (int i = frame; i < highx; i++) {
01534 float max_curv2 =
01535 vnl_cross_3d(*fvectorPixel(normal, i+1, j),
01536 *fvectorPixel(normal, i-1, j)).squared_magnitude();
01537 float curv2 =
01538 vnl_cross_3d(*fvectorPixel(normal, i, j+1),
01539 *fvectorPixel(normal, i, j-1)).squared_magnitude();
01540 if (max_curv2 < curv2) max_curv2 = curv2;
01541 curv2 =
01542 vnl_cross_3d(*fvectorPixel(normal, i+1, j+1),
01543 *fvectorPixel(normal, i-1, j-1)).squared_magnitude()/2;
01544 if (max_curv2 < curv2) max_curv2 = curv2;
01545 curv2 =
01546 vnl_cross_3d(*fvectorPixel(normal, i+1, j-1),
01547 *fvectorPixel(normal, i-1, j+1)).squared_magnitude()/2;
01548 if (max_curv2 < curv2) max_curv2 = curv2;
01549 floatPixel(*curvature, i, j) = vcl_sqrt(max_curv2);
01550 }
01551 gevd_float_operators::FillFrameX(*curvature, 0, frame);
01552 gevd_float_operators::FillFrameY(*curvature, 0, frame);
01553 }
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567 static bool
01568 _TangentComponents(const gevd_bufferxy& range,
01569 int low_x, int low_y,
01570 int x, int y,
01571 int high_x, int high_y,
01572 float no_value,
01573 float & distance,
01574 float & delta_z )
01575 {
01576 float low_z = floatPixel( range, low_x, low_y );
01577 float z = floatPixel( range, x, y );
01578 float high_z = floatPixel( range, high_x, high_y );
01579
01580 if ( z == no_value || ( low_z == no_value && high_z == no_value ) )
01581 return false;
01582
01583 if ( low_z == no_value ) {
01584 distance = 1.0;
01585 delta_z = high_z - z;
01586 #ifdef DEBUG
01587 vcl_cout << "TC low missing: distance = " << distance << ", delta_z = " << delta_z << vcl_endl;
01588 #endif
01589 }
01590 else if ( high_z == no_value ) {
01591 distance = 1.0;
01592 delta_z = z - low_z;
01593 #ifdef DEBUG
01594 vcl_cout << "TC high missing: distance = " << distance << ", delta_z = " << delta_z << vcl_endl;
01595 #endif
01596 }
01597 else {
01598 distance = 2.0;
01599 delta_z = high_z - low_z;
01600 #ifdef DEBUG
01601 vcl_cout << "TC neither missing: distance = " << distance << ", delta_z = " << delta_z << vcl_endl;
01602 #endif
01603 }
01604 return true;
01605 }
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615 void
01616 gevd_float_operators::SurfaceNormalD(const gevd_bufferxy& range,
01617 gevd_bufferxy*& normal,
01618 float no_value,
01619 float pixel_distance)
01620 {
01621 const int frame = 1;
01622 const int highx = range.GetSizeX()-frame, highy = range.GetSizeY()-frame;
01623 normal = gevd_float_operators::Allocate(normal, range, bits_per_ptr);
01624 normal->Clear();
01625
01626 for (int j = frame; j < highy; j++)
01627 for (int i = frame; i < highx; i++) {
01628 float d_x, d_z_x;
01629 float d_y, d_z_y;
01630 if (_TangentComponents(range, i-1, j, i, j, i+1, j, no_value, d_x, d_z_x) &&
01631 _TangentComponents(range, i, j-1, i, j, i, j+1, no_value, d_y, d_z_y) )
01632 {
01633 vnl_float_3 tx(d_x*pixel_distance, 0.f, d_z_x),
01634 ty(0.f, d_y*pixel_distance, d_z_y);
01635 vnl_vector<float>* nz = new vnl_vector<float>(vnl_cross_3d(tx,ty).as_ref());
01636
01637 #ifdef DEBUG
01638 vcl_cout << "Tx = " << tx << ", Ty = " << ty << vcl_endl;
01639 #endif
01640 float mag = nz->magnitude();
01641 if (mag != 0) {
01642 *nz /= mag;
01643 #ifdef DEBUG
01644 vcl_cout << "Normal = " << *nz << vcl_endl;
01645 #endif
01646 fvectorPixel(*normal, i, j) = nz;
01647 }
01648 else {
01649 delete nz;
01650 fvectorPixel(*normal, i, j) = NULL;
01651 }
01652 }
01653 else {
01654 fvectorPixel(*normal, i, j) = NULL;
01655 }
01656 }
01657 }
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677 static bool
01678 _CurvatureInDir(const gevd_bufferxy& normal,
01679 const gevd_bufferxy& surface,
01680 int low_x, int low_y,
01681 int x, int y,
01682 int high_x, int high_y,
01683 float & sq_dist,
01684 float & sq_curve )
01685 {
01686 vnl_vector<float> * low_norm = fvectorPixel( normal, low_x, low_y );
01687 vnl_vector<float> * norm = fvectorPixel( normal, x, y );
01688 vnl_vector<float> * high_norm = fvectorPixel( normal, high_x, high_y );
01689
01690 float zval1, zval2, dz;
01691 int dx, dy;
01692
01693 if ( norm == NULL || ( low_norm == NULL && high_norm == NULL ) )
01694 return false;
01695
01696 if ( low_norm == NULL ) {
01697
01698 zval1 = floatPixel(surface, high_x, high_y);
01699 zval2 = floatPixel(surface, x, y);
01700 dz = zval1 - zval2;
01701 dx = high_x - x;
01702 dy = high_y - y;
01703 sq_dist = (dx*dx) + (dy*dy) + (dz*dz);
01704 sq_curve = vnl_cross_3d( *high_norm, *norm ).squared_magnitude();
01705 #ifdef DEBUG
01706 vcl_cout << "CinDir low missing: sq_dist = " << sq_dist
01707 << ", high = " << *high_norm
01708 << ", norm = " << *norm
01709 << ", sq_curve = " << sq_curve << vcl_endl;
01710 #endif
01711 }
01712 else if ( high_norm == NULL ) {
01713
01714 zval1 = floatPixel(surface, x, y);
01715 zval2 = floatPixel(surface, low_x, low_y);
01716 dz = zval1 - zval2;
01717 dx = x - low_x;
01718 dy = y - low_y;
01719 sq_dist = (dx*dx) + (dy*dy) + (dz*dz);
01720 sq_curve = vnl_cross_3d( *norm, *low_norm ).squared_magnitude();
01721 #ifdef DEBUG
01722 vcl_cout << "CinDir high missing: sq_dist = " << sq_dist
01723 << ", norm = " << *norm
01724 << ", low = " << *low_norm
01725 << ", sq_curve = " << sq_curve << vcl_endl;
01726 #endif
01727 }
01728 else {
01729
01730 zval1 = floatPixel(surface, high_x, high_y);
01731 zval2 = floatPixel(surface, low_x, low_y);
01732 dz = zval1 - zval2;
01733 dx = high_x - low_x;
01734 dy = high_y - low_y;
01735 sq_dist = (dx*dx) + (dy*dy) + (dz*dz);
01736 sq_curve = vnl_cross_3d( *high_norm, *low_norm ).squared_magnitude();
01737 #ifdef DEBUG
01738 vcl_cout << "CinDir neither missing: sq_dist = " << sq_dist
01739 << ", high = " << *high_norm
01740 << ", low = " << *low_norm
01741 << ", sq_curve = " << sq_curve << vcl_endl;
01742 #endif
01743 }
01744 return true;
01745 }
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757 void
01758 gevd_float_operators::SurfaceCurvatureD(const gevd_bufferxy& normal,
01759 const gevd_bufferxy& surface,
01760 gevd_bufferxy*& curvature,
01761 float dflt,
01762 float pixel_distance )
01763 {
01764 const int frame = 2;
01765 const int highx = normal.GetSizeX()-frame, highy = normal.GetSizeY()-frame;
01766 curvature = gevd_float_operators::Allocate(curvature, normal, bits_per_float);
01767 float sq_unit_normalize = 1.0f/(pixel_distance*pixel_distance);
01768
01769 for (int j = frame; j < highy; j++)
01770 for (int i = frame; i < highx; i++) {
01771 if ( fvectorPixel( normal, i, j ) == NULL ) {
01772 floatPixel(*curvature, i, j) = dflt;
01773 continue;
01774 }
01775 #ifdef DEBUG
01776 vcl_cout << "i,j:" << i << ' ' << j << vcl_endl;
01777 #endif
01778 float max_sq_curve = -1;
01779 float sq_dist, sq_curve;
01780 if ( _CurvatureInDir( normal, surface, i-1, j, i, j, i+1, j,
01781 sq_dist, sq_curve ) ) {
01782 sq_curve *= sq_unit_normalize / sq_dist;
01783 #ifdef DEBUG
01784 vcl_cout << " sq_curve(h) = " << sq_curve << vcl_endl;
01785 #endif
01786 if ( sq_curve > max_sq_curve ) max_sq_curve = sq_curve;
01787 }
01788 if ( _CurvatureInDir( normal, surface,i, j-1, i, j, i, j+1,
01789 sq_dist, sq_curve ) ) {
01790 sq_curve *= sq_unit_normalize / sq_dist;
01791 #ifdef DEBUG
01792 vcl_cout << " sq_curve(v) = " << sq_curve << vcl_endl;
01793 #endif
01794 if ( sq_curve > max_sq_curve ) max_sq_curve = sq_curve;
01795 }
01796 if ( _CurvatureInDir( normal, surface, i-1, j-1, i, j, i+1, j+1,
01797 sq_dist, sq_curve ) ) {
01798 sq_curve *= sq_unit_normalize / sq_dist;
01799 #ifdef DEBUG
01800 vcl_cout << " sq_curve(45) = " << sq_curve << vcl_endl;
01801 #endif
01802 if ( sq_curve > max_sq_curve ) max_sq_curve = sq_curve;
01803 }
01804 if ( _CurvatureInDir( normal, surface, i-1, j+1, i, j, i+1, j-1,
01805 sq_dist, sq_curve ) ) {
01806 sq_curve *= sq_unit_normalize / sq_dist;
01807 #ifdef DEBUG
01808 vcl_cout << " sq_curve(135) = " << sq_curve << vcl_endl;
01809 #endif
01810 if ( sq_curve > max_sq_curve ) max_sq_curve = sq_curve;
01811 }
01812 #ifdef DEBUG
01813 vcl_cout << " max_sq_curve = " << max_sq_curve << vcl_endl;
01814 #endif
01815 if ( max_sq_curve < 0 )
01816 floatPixel(*curvature, i, j) = dflt;
01817 else
01818 floatPixel(*curvature, i, j) = vcl_sqrt(max_sq_curve);
01819 #ifdef DEBUG
01820 vcl_cout << "curvature in 1/inches: " << i << ' ' << j << ' ' << floatPixel(*curvature, i, j) << vcl_endl;
01821 #endif
01822 }
01823 gevd_float_operators::FillFrameX(*curvature, dflt, frame);
01824 gevd_float_operators::FillFrameY(*curvature, dflt, frame);
01825 }
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839 float
01840 gevd_float_operators::ShrinkBy2(const gevd_bufferxy& from, gevd_bufferxy*& to,
01841 const float burt_ka)
01842 {
01843 const int sizeX = (from.GetSizeX() + 1) / 2;
01844 const int sizeY = (from.GetSizeY() + 1) / 2;
01845 bool overwrite = to == &from;
01846 gevd_bufferxy*& t = to;
01847 if (overwrite) to=0;
01848 to = gevd_float_operators::Allocate(to, from, 0, sizeX, sizeY);
01849 const float ka = burt_ka;
01850 const float kb = 0.25f;
01851 const float kc = (0.5f - burt_ka) / 2;
01852
01853 int p = 0;
01854 float* yline0 = new float[sizeX];
01855 float* yline1 = new float[sizeX];
01856 float* yline2 = new float[sizeX];
01857 float* yline3 = new float[sizeX];
01858 float* yline4 = new float[sizeX];
01859 gevd_float_operators::ShrinkBy2AlongX(from, p++, yline0, sizeX, ka, kb, kc);
01860 gevd_float_operators::ShrinkBy2AlongX(from, p++, yline1, sizeX, ka, kb, kc);
01861 gevd_float_operators::ShrinkBy2AlongX(from, p++, yline2, sizeX, ka, kb, kc);
01862 gevd_float_operators::ShrinkBy2AlongX(from, p++, yline3, sizeX, ka, kb, kc);
01863 gevd_float_operators::ShrinkBy2AlongX(from, p++, yline4, sizeX, ka, kb, kc);
01864
01865
01866 for (int x = 0; x < sizeX; x++)
01867 floatPixel(*to, x, 0) = (ka * yline0[x] +
01868 2 * (kb * yline1[x] + kc * yline2[x]));
01869 for (int y = 1; y < sizeY; y++) {
01870 for (int x = 0; x < sizeX; x++)
01871 floatPixel(*to, x, y) = (ka * yline2[x] +
01872 kb * (yline1[x] + yline3[x]) +
01873 kc * (yline0[x] + yline4[x]));
01874 float* next0 = yline0;
01875 float* next1 = yline1;
01876 yline0 = yline2;
01877 yline1 = yline3;
01878 yline2 = yline4;
01879 yline3 = next0;
01880 yline4 = next1;
01881 if (y < sizeY-2) {
01882 gevd_float_operators::ShrinkBy2AlongX(from, p++, next0, sizeX,
01883 ka, kb, kc);
01884 gevd_float_operators::ShrinkBy2AlongX(from, p++, next1, sizeX,
01885 ka, kb, kc);
01886 }
01887 else {
01888 vcl_memcpy(next0, yline1, sizeX*sizeof(float));
01889 vcl_memcpy(next1, yline0, sizeX*sizeof(float));
01890 }
01891 }
01892 delete[] yline0; delete[] yline1; delete[] yline2;
01893 delete[] yline3; delete[] yline4;
01894 if (overwrite) { gevd_float_operators::Update(*t,*to); delete to; to = t; }
01895 return 1;
01896 }
01897
01898
01899
01900
01901
01902 float
01903 gevd_float_operators::ShrinkBy2AlongX(const gevd_bufferxy& from, const int y,
01904 float* yline, const int sizeX,
01905 const float ka, const float kb,
01906 const float kc)
01907 {
01908 int p = 0;
01909 float x0 = floatPixel(from, p++, y);
01910 float x1 = floatPixel(from, p++, y);
01911 float x2 = floatPixel(from, p++, y);
01912 float x3 = floatPixel(from, p++, y);
01913 float x4 = floatPixel(from, p++, y);
01914 yline[0] = ka * x0 + 2 * (kb * x1 + kc * x2);
01915 for (int x = 1; x < sizeX; x++) {
01916 yline[x] = (ka * x2 +
01917 kb * (x1 + x3) +
01918 kc * (x0 + x4));
01919 x0 = x2;
01920 x1 = x3;
01921 x2 = x4;
01922 if (x < sizeX-2) {
01923 x3 = floatPixel(from, p++, y);
01924 x4 = floatPixel(from, p++, y);
01925 }
01926 else {
01927 x3 = x1;
01928 x4 = x0;
01929 }
01930 }
01931 return 1;
01932 }
01933
01934
01935 void
01936 PrintAllPipes( float * y_s[],
01937 float * w_s[],
01938 int length )
01939 {
01940 for (int i=0; i<5; i++ ) {
01941 vcl_cout << "\nPipe " << i << vcl_endl;
01942 for (int j=0; j<length; j++ ) {
01943 vcl_cout << j << ", yline[j] = " << y_s[i][j] << ", wline[j] = "
01944 << w_s[i][j] << vcl_endl;
01945 }
01946 }
01947 }
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960 void
01961 gevd_float_operators::ShrinkBy2_D(const gevd_bufferxy& from,
01962 gevd_bufferxy*& to,
01963 float no_value,
01964 float burt_ka )
01965 {
01966 const int sizeX = (from.GetSizeX() + 1) / 2;
01967 const int sizeY = (from.GetSizeY() + 1) / 2;
01968 bool overwrite = to == &from;
01969 gevd_bufferxy*& t = to;
01970 if (overwrite) to=0;
01971 to = gevd_float_operators::Allocate(to, from, 0, sizeX, sizeY);
01972
01973
01974 float kernel[5];
01975 kernel[2] = burt_ka;
01976 kernel[1] = kernel[3] = 0.25f;
01977 kernel[0] = kernel[4] = (0.5f - burt_ka) / 2;
01978
01979
01980
01981
01982
01983
01984
01985 float * yline[5];
01986 for (int i=0; i<5; i++ ) yline[i] = new float[sizeX];
01987 float * wline[5];
01988 for (int i=0; i<5; i++ ) wline[i] = new float[sizeX];
01989 float * y_empty = new float[sizeX];
01990 float * w_empty = new float[sizeX];
01991
01992
01993
01994
01995 for (int i=0; i<sizeX; i++ ) {
01996 y_empty[i] = no_value;
01997 w_empty[i] = 0.0;
01998 }
01999
02000
02001
02002
02003
02004 vcl_memcpy(yline[0], y_empty, sizeX*sizeof(float));
02005 vcl_memcpy(wline[0], w_empty, sizeX*sizeof(float));
02006 vcl_memcpy(yline[1], y_empty, sizeX*sizeof(float));
02007 vcl_memcpy(wline[1], w_empty, sizeX*sizeof(float));
02008
02009
02010
02011
02012 gevd_float_operators::ShrinkBy2AlongX_D(from, from.GetSizeX(), sizeX, 0,
02013 kernel, no_value, yline[2], wline[2]);
02014 gevd_float_operators::ShrinkBy2AlongX_D(from, from.GetSizeX(), sizeX, 1,
02015 kernel, no_value, yline[3], wline[3]);
02016 gevd_float_operators::ShrinkBy2AlongX_D(from, from.GetSizeX(), sizeX, 2,
02017 kernel, no_value, yline[4], wline[4]);
02018 int p = 3;
02019
02020
02021
02022
02023
02024 for (int y=0; y<sizeY; y++ )
02025 {
02026 #ifdef DEBUG
02027 vcl_cout << "\nNew row: y= " << y << "\nHere are the pipes.\n";
02028 PrintAllPipes( yline, wline, sizeX );
02029 #endif
02030 for (int x=0; x<sizeX; x++) {
02031 float sum_w = 0, sum_z = 0;
02032 for (int i=0; i<5; i++ ) {
02033 sum_w += kernel[i] * wline[i][x];
02034 sum_z += kernel[i] * yline[i][x];
02035 }
02036 #ifdef DEBUG
02037 vcl_cout << "Assigning: x,y = " << x << ", " << y << " ";
02038 #endif
02039 floatPixel(*to, x, y) = sum_w < 0.5 ? no_value : sum_z / sum_w;
02040 #ifdef DEBUG
02041 vcl_cout << ", sum_w = " << sum_w << ", value = " << floatPixel(*to, x, y) << vcl_endl;
02042 #endif
02043 }
02044
02045
02046
02047
02048 float* prev_y0 = yline[0];
02049 float* prev_y1 = yline[1];
02050 float* prev_w0 = wline[0];
02051 float* prev_w1 = wline[1];
02052 for (int i=0; i<3; i++ ) {
02053 yline[i] = yline[i+2];
02054 wline[i] = wline[i+2];
02055 }
02056 yline[3] = prev_y0;
02057 wline[3] = prev_w0;
02058 yline[4] = prev_y1;
02059 wline[4] = prev_w1;
02060 if ( p < from.GetSizeY() )
02061 ShrinkBy2AlongX_D(from, from.GetSizeX(), sizeX, p++, kernel,
02062 no_value, yline[3], wline[3] );
02063 else {
02064 vcl_memcpy(yline[3], y_empty, sizeX*sizeof(float));
02065 vcl_memcpy(wline[3], w_empty, sizeX*sizeof(float));
02066 }
02067 if ( p < from.GetSizeY() )
02068 ShrinkBy2AlongX_D(from, from.GetSizeX(), sizeX, p++, kernel,
02069 no_value, yline[4], wline[4] );
02070 else {
02071 vcl_memcpy(yline[4], y_empty, sizeX*sizeof(float));
02072 vcl_memcpy(wline[4], w_empty, sizeX*sizeof(float));
02073 }
02074 }
02075
02076
02077 for (int i=0; i<5; i++ ) {
02078 delete[] yline[i];
02079 delete[] wline[i];
02080 }
02081 delete[] y_empty;
02082 delete[] w_empty;
02083 if (overwrite) { gevd_float_operators::Update(*t,*to); delete to; to = t; }
02084 }
02085
02086 void
02087 PrintPipe( float values[] )
02088 {
02089 for (int i=0; i<4; i++ ) vcl_cout << values[i] << ", ";
02090 vcl_cout << values[4];
02091 }
02092
02093
02094
02095
02096
02097
02098 void
02099 gevd_float_operators::ShrinkBy2AlongX_D(const gevd_bufferxy& from,
02100 int from_sizeX,
02101 int sizeX,
02102 int y,
02103 float kernel[],
02104 float no_value,
02105 float* yline,
02106 float* wline )
02107 {
02108 #ifdef DEBUG
02109 vcl_cout << "\nIn gevd_float_operators::ShrinkBy2AlongX_D:\n";
02110
02111 vcl_cout << "Here is the original data:\n";
02112 for (int xx=0; xx<from.GetSizeX(); xx++ )
02113 vcl_cout << xx << ": " << floatPixel( from, xx, y ) << vcl_endl;
02114 #endif
02115
02116
02117 float xs[5];
02118 xs[0] = no_value;
02119 xs[1] = no_value;
02120 xs[2] = floatPixel( from, 0, y );
02121 xs[3] = floatPixel( from, 1, y );
02122 xs[4] = floatPixel( from, 2, y );
02123 int p = 3;
02124
02125 for (int x = 0; x < sizeX; x++ ) {
02126 #ifdef DEBUG
02127 vcl_cout << "Data pipe: "; PrintPipe( xs ); vcl_cout << vcl_endl;
02128 #endif
02129 wline[x] = yline[x] = 0.0;
02130 for (int i = 0; i<5; i++ ) {
02131 if ( xs[i] != no_value ) {
02132 wline[x] += kernel[i];
02133 yline[x] += kernel[i] * xs[i];
02134 }
02135 }
02136 #ifdef DEBUG
02137 vcl_cout << "x = " << x << ", yline[x] = " << yline[x]
02138 << ", wline[x] = " << wline[x] << vcl_endl;
02139 #endif
02140 for (int i=0; i<3; i++ ) xs[i] = xs[i+2];
02141 xs[3] = (p < from_sizeX) ? floatPixel(from, p++, y) : no_value;
02142 xs[4] = (p < from_sizeX) ? floatPixel(from, p++, y) : no_value;
02143 }
02144 }
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158 float
02159 gevd_float_operators::ExpandBy2(const gevd_bufferxy& from, gevd_bufferxy*& to,
02160 const float burt_ka)
02161 {
02162 const int sizeX = 2 * from.GetSizeX();
02163 const int sizeY = 2 * from.GetSizeY();
02164 bool overwrite = to == &from;
02165 gevd_bufferxy*& t = to;
02166 if (overwrite) to=0;
02167 to = gevd_float_operators::Allocate(to, from, 0, sizeX, sizeY);
02168 const float ka = burt_ka * 2;
02169 const float kb = 0.5f;
02170 const float kc = 0.5f - burt_ka;
02171 int p = 0;
02172 float* yline0 = new float[sizeX];
02173 float* yline1 = new float[sizeX];
02174 float* yline2 = new float[sizeX];
02175 gevd_float_operators::ExpandBy2AlongX(from, p++, yline1, sizeX, ka, kb, kc);
02176 gevd_float_operators::ExpandBy2AlongX(from, p++, yline2, sizeX, ka, kb, kc);
02177 vcl_memcpy(yline0, yline2, sizeX*sizeof(float));
02178
02179
02180 for (int y = 0; y < sizeY; y += 2) {
02181 int yy = y+1;
02182 for (int x = 0; x < sizeX; x++) {
02183 floatPixel(*to, x, y) = (ka * yline1[x] +
02184 kc * (yline0[x] + yline2[x]));
02185 floatPixel(*to, x, yy) = kb * (yline1[x] + yline2[x]);
02186 }
02187 float* next = yline0;
02188 yline0 = yline1;
02189 yline1 = yline2;
02190 yline2 = next;
02191 if (y < sizeY-4)
02192 gevd_float_operators::ExpandBy2AlongX(from, p++, next, sizeX, ka, kb, kc);
02193 else
02194 vcl_memcpy(next, yline0, sizeX*sizeof(float));
02195 }
02196 delete[] yline0;
02197 delete[] yline1;
02198 delete[] yline2;
02199 if (overwrite) { gevd_float_operators::Update(*t,*to); delete to; to = t; }
02200 return 1;
02201 }
02202
02203
02204
02205
02206 float
02207 gevd_float_operators::ExpandBy2AlongX(const gevd_bufferxy& from, const int y,
02208 float* yline, const int sizeX,
02209 const float ka, const float kb,
02210 const float kc)
02211 {
02212 int p = 0;
02213 float x1 = floatPixel(from, p++, y);
02214 float x2 = floatPixel(from, p++, y);
02215 float x0 = x2;
02216 for (int x = 0; x < sizeX; x += 2) {
02217 yline[x] = ka * x1 + kc * (x0 + x2);
02218 yline[x+1] = kb * (x1 + x2);
02219 x0 = x1;
02220 x1 = x2;
02221 if (x < sizeX-4)
02222 x2 = floatPixel(from, p++, y);
02223 else
02224 x2 = x0;
02225 }
02226 return 1;
02227 }
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238 int
02239 gevd_float_operators::Pyramid(const float* data, const int length,
02240 float*& pyramid, int& nlevels, int trim,
02241 const float burt_ka)
02242 {
02243 const int MINLENGTH = 16;
02244 if (!pyramid)
02245 pyramid = new float[length << 1];
02246 int i, ii;
02247 for (ii = 0; ii < length; ii++)
02248 pyramid[ii] = 0;
02249 for (i = 0; i < trim; i++, ii++)
02250 pyramid[ii] = 0;
02251 for ( ; i < length-trim; i++, ii++)
02252 pyramid[ii] = data[i];
02253 for ( ; i < length; i++, ii++)
02254 pyramid[ii] = 0;
02255 int l, len1, len2;
02256 float *from, *to;
02257 for (l = 1, len1 = length, len2 = length >> 1;
02258 l < nlevels && len2 > MINLENGTH; l++) {
02259 from = pyramid + len1, to = pyramid + len2;
02260 len1 = ShrinkBy2(from, len1, to, burt_ka);
02261 len2 = len1 >> 1;
02262 }
02263 nlevels = l;
02264 return len1;
02265 }
02266
02267
02268 int
02269 gevd_float_operators::ShrinkBy2(const float* from, const int length,
02270 float*& to, const float burt_ka)
02271 {
02272 const int slength = length >> 1;
02273 if (!to) to = new float[slength];
02274 const float ka = burt_ka;
02275 const float kb = 0.25f;
02276 const float kc = (0.5f - burt_ka) / 2;
02277 int p = 0;
02278 float x0 = from[p++];
02279 float x1 = from[p++];
02280 float x2 = from[p++];
02281 float x3 = from[p++];
02282 float x4 = from[p++];
02283 to[0] = ka * x0 + 2 * (kb * x1 + kc * x2);
02284 for (int x = 1; x < slength; x++) {
02285 to[x] = (ka * x2 +
02286 kb * (x1 + x3) +
02287 kc * (x0 + x4));
02288 x0 = x2;
02289 x1 = x3;
02290 x2 = x4;
02291 if (x < slength-2) {
02292 x3 = from[p++];
02293 x4 = from[p++];
02294 }
02295 else {
02296 x3 = x1;
02297 x4 = x0;
02298 }
02299 }
02300 return slength;
02301 }
02302
02303
02304 static float haar2 [] =
02305 {
02306 0.7071067811865f,
02307 0.7071067811865f,
02308 0.f
02309 };
02310
02311 static float daubechies4 [] =
02312 {
02313 0.4829629131445341f,
02314 0.8365163037378079f,
02315 0.2241438680420134f,
02316 -0.1294095225512604f,
02317 0
02318 };
02319
02320 static float daubechies6 [] =
02321 {
02322 0.3326705529500825f,
02323 0.8068915093110924f,
02324 0.4598775021184914f,
02325 -0.1350110200102546f,
02326 -0.0854412738820267f,
02327 0.0352262918857095f,
02328 0
02329 };
02330
02331 static float daubechies8 [] =
02332 {
02333 0.2303778133088964f,
02334 0.7148465705529154f,
02335 0.6308807679398587f,
02336 -0.0279837694168599f,
02337 -0.1870348117190931f,
02338 0.0308413818355607f,
02339 0.0328830116668852f,
02340 -0.0105974017850690f,
02341 0
02342 };
02343
02344 static float daubechies10 [] =
02345 {
02346 0.1601023979741929f,
02347 0.6038292697971895f,
02348 0.7243085284377726f,
02349 0.1384281459013203f,
02350 -0.2422948870663823f,
02351 -0.0322448695846381f,
02352 0.0775714938400459f,
02353 -0.0062414902127983f,
02354 -0.0125807519990820f,
02355 0.0033357252854738f,
02356 0
02357 };
02358
02359 static float daubechies12 [] =
02360 {
02361 0.111540743350f,
02362 0.494623890398f,
02363 0.751133908021f,
02364 0.315250351709f,
02365 -0.226264693965f,
02366 -0.129766867567f,
02367 0.097501605587f,
02368 0.027522865530f,
02369 -0.031582039318f,
02370 0.000553842201f,
02371 0.004777257511f,
02372 -0.001077301085f,
02373 0
02374 };
02375
02376 static float daubechies20 [] =
02377 {
02378 0.026670057901f,
02379 0.188176800078f,
02380 0.527201188932f,
02381 0.688459039454f,
02382 0.281172343661f,
02383 -0.249846424327f,
02384 -0.195946274377f,
02385 0.127369340336f,
02386 0.093057364604f,
02387 -0.071394147166f,
02388 -0.029457536822f,
02389 0.033212674059f,
02390 0.003606553567f,
02391 -0.010733175483f,
02392 0.001395351747f,
02393 0.001992405295f,
02394 -0.000685856695f,
02395 -0.000116466855f,
02396 0.000093588670f,
02397 -0.000013264203f,
02398 0
02399 };
02400
02401 static float coifman9 [] =
02402 {
02403 0.019849565349356158f,
02404 -0.04309091740554781f,
02405 -0.05188793647806494f,
02406 0.2932311998087948f,
02407 0.5637961774509238f,
02408 0.2932311998087948f,
02409 -0.05188793647806494f,
02410 -0.04309091740554781f,
02411 0.019849565349356158f,
02412 0
02413 };
02414
02415 static float coifman11 [] =
02416 {
02417 0.007987761489921101f,
02418 0.02011649866148413f,
02419 -0.05015758257647976f,
02420 -0.12422330961337678f,
02421 0.29216982108655865f,
02422 0.7082136219037853f,
02423 0.29216982108655865f,
02424 -0.12422330961337678f,
02425 -0.05015758257647976f,
02426 0.02011649866148413f,
02427 0.007987761489921101f,
02428 0
02429 };
02430
02431 static float coifman15 [] =
02432 {
02433 -0.0012475221f,
02434 -0.0024950907f,
02435 0.0087309530f,
02436 0.0199579580f,
02437 -0.0505290000f,
02438 -0.1205509700f,
02439 0.2930455800f,
02440 0.7061761600f,
02441 0.2930455800f,
02442 -0.1205509700f,
02443 -0.0505290000f,
02444 0.0199579580f,
02445 0.0087309530f,
02446 -0.0024950907f,
02447 -0.0012475221f,
02448 0
02449 };
02450
02451 static float dual_wavelet [20] = {0};
02452
02453
02454
02455
02456
02457 bool
02458 gevd_float_operators::FindWavelet(const int waveletno,
02459 float*& lo_filter, float*& hi_filter, int& ncof)
02460 {
02461 ncof = waveletno;
02462 switch (waveletno)
02463 {
02464 case 2:
02465 lo_filter = haar2;
02466 break;
02467 case 4:
02468 lo_filter = daubechies4;
02469 break;
02470 case 6:
02471 lo_filter = daubechies6;
02472 break;
02473 case 8:
02474 lo_filter = daubechies8;
02475 break;
02476 case 10:
02477 lo_filter = daubechies10;
02478 break;
02479 case 12:
02480 lo_filter = daubechies12;
02481 break;
02482 case 20:
02483 lo_filter = daubechies20;
02484 break;
02485 case 9:
02486 lo_filter = coifman9;
02487 break;
02488 case 11:
02489 lo_filter = coifman11;
02490 break;
02491 case 15:
02492 lo_filter = coifman15;
02493 break;
02494 default:
02495 ncof = 0;
02496 lo_filter = hi_filter = NULL;
02497 vcl_cerr << "Unknown wavelet: " << waveletno << vcl_endl;
02498 return false;
02499 }
02500
02501 if (lo_filter)
02502 {
02503 hi_filter = dual_wavelet;
02504 if ((waveletno%2) == 0) {
02505 int sign = -1;
02506 for (int k = 0; k < ncof; k++) {
02507 hi_filter[ncof-1-k] = sign * lo_filter[k];
02508 sign = - sign;
02509 }
02510 }
02511 else {
02512 int sign = 1;
02513 int ctr = ncof/2;
02514 for (int k = 0; k <= ncof/2; k++) {
02515 hi_filter[ctr+k] = sign * lo_filter[ctr-k];
02516 hi_filter[ctr-k] = sign * lo_filter[ctr+k];
02517 sign = - sign;
02518 }
02519 vcl_cerr << "Scale factor need to be fixed up too!!!\n";
02520 }
02521
02522 float lo_area = 0;
02523 float hi_area = 0;
02524 for (int k = 0; k < ncof; k++) {
02525 lo_area += lo_filter[k];
02526 hi_area += hi_filter[k];
02527 }
02528 lo_filter[ncof] = lo_area;
02529 hi_filter[ncof] = hi_area;
02530 }
02531 #ifdef DEBUG
02532 vcl_cout << "lo-filter wavelet " << waveletno << ':';
02533 for (int i = 0; i < ncof; i++)
02534 vcl_cout << ' ' << lo_filter[i];
02535 vcl_cout << "\nhi-filter wavelet " << waveletno << ':';
02536 for (int i = 0; i < ncof; i++)
02537 vcl_cout << ' ' << hi_filter[i];
02538 vcl_cout << vcl_endl;
02539 #endif
02540 return true;
02541 }
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551 void
02552 gevd_float_operators::WaveletTransformStep(float* array, const int n,
02553 const bool forwardp,
02554 const float* lo_filter,
02555 const float* hi_filter,
02556 const int ncof,
02557 float* wksp)
02558 {
02559 for (int j = 0; j < n; j++)
02560 wksp[j] = 0;
02561 int nmid = n / 2;
02562 int nmod = nmid * 2;
02563 if (forwardp) {
02564 for (int i=0, ii=0; i < nmod; i +=2, ++ii)
02565 for (int k = 0; k < ncof; k++) {
02566 int j = (i + k) % nmod;
02567
02568 wksp[ii] += lo_filter[k] * array[j];
02569 wksp[ii+nmid] += hi_filter[k] * array[j];
02570 }
02571 float scale = vcl_max(lo_filter[ncof], hi_filter[ncof]);
02572 for (int j = 0; j < nmod; j++)
02573 wksp[j] /= scale;
02574 }
02575 else {
02576 for (int i=0, ii=0; i < nmod; i+=2, ++ii) {
02577 float lo = array[ii];
02578 float hi = array[ii+nmid];
02579 for (int k = 0; k < ncof; k++) {
02580 int j = (i + k) % nmod;
02581
02582 wksp[j] += (lo_filter[k] * lo +
02583 hi_filter[k] * hi);
02584 }
02585 }
02586 float scale = vcl_max(lo_filter[ncof], hi_filter[ncof]);
02587 for (int j = 0; j < nmod; j++)
02588 wksp[j] *= scale;
02589 }
02590 for (int j = 0; j < nmod; j++)
02591 array[j] = wksp[j];
02592 }
02593
02594
02595
02596
02597
02598
02599 bool
02600 gevd_float_operators::WaveletTransform(float* array, const int n,
02601 const bool forwardp, int nlevels,
02602 const int waveletno)
02603 {
02604 if (n >= 4) {
02605 float* lo_filter = NULL;
02606 float* hi_filter = NULL;
02607 int ncof = 0;
02608 FindWavelet(waveletno, lo_filter, hi_filter, ncof);
02609 #ifdef DEBUG
02610 vcl_cout << "Input:";
02611 for (int i = 0; i < n; i++)
02612 vcl_cout << ' ' << array[i];
02613 vcl_cout << vcl_endl;
02614 #endif
02615
02616 float* wksp = new float[n];
02617 if (forwardp) {
02618 for (int nn = n; nn >= 4 && nlevels > 0; nn /= 2, nlevels--)
02619 WaveletTransformStep(array, nn, forwardp,
02620 lo_filter, hi_filter, ncof,
02621 wksp);
02622 }
02623 else {
02624 const int sz = int(vcl_log(double(n))/vcl_log(2.0));
02625 int* sizes = new int[sz];
02626 int s = 0;
02627 for (int nn = n; nn >= 4 && nlevels > 0; nn /= 2, nlevels--, s++)
02628 sizes[s] = nn;
02629 for (s--; s >= 0; s--)
02630 WaveletTransformStep(array, sizes[s], forwardp,
02631 lo_filter, hi_filter, ncof,
02632 wksp);
02633 delete[] sizes;
02634 }
02635 delete[] wksp;
02636 #ifdef DEBUG
02637 vcl_cout << "Output:";
02638 for (int i = 0; i < n; i++)
02639 vcl_cout << ' ' << array[i];
02640 vcl_cout << vcl_endl;
02641 #endif
02642 }
02643 return true;
02644 }
02645
02646
02647
02648 void
02649 gevd_float_operators::LowHighPyramid(float* highPass, float* lowPass,
02650 int n, int nlevels,
02651 const float* lo_filter,
02652 const float* hi_filter,
02653 int ncof,
02654 float* wksp)
02655 {
02656 const bool forwardp = true;
02657 int nn = n;
02658 for (int l = nlevels;
02659 nn >= 4 && l > 0; nn /= 2, l--) {
02660 gevd_float_operators::WaveletTransformStep(highPass, nn, forwardp,
02661 lo_filter, hi_filter, ncof,
02662 wksp);
02663 int m = nn / 2;
02664 float* lows = lowPass + m;
02665 for (int j = 0; j < m; j++)
02666 lows[j] = highPass[j];
02667 if ((nn % 2) == 1) {
02668 int bound = nn-1;
02669 highPass[bound] = highPass[bound-1];
02670 lowPass[bound] = lowPass[bound-1];
02671 }
02672 }
02673 const float LO = lowPass[nn];
02674 for (int j = 0; j < nn; j++) {
02675 highPass[j] = 0;
02676 lowPass[j] = LO;
02677 }
02678 }
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690 bool
02691 gevd_float_operators::WaveletTransformByIndex(float* array,
02692 const int* dims, const int ndim,
02693 const bool forwardp, int nlevels,
02694 const int waveletno)
02695 {
02696 int ntot = 1, maxn = 0;
02697 {for (int d = 0; d < ndim; d++) {
02698 int dim = dims[d];
02699 ntot *= dim;
02700 if (dim > maxn) maxn = dim;
02701 }}
02702 float* lo_filter = NULL;
02703 float* hi_filter = NULL;
02704 int ncof = 0;
02705 if (!FindWavelet(waveletno, lo_filter, hi_filter, ncof))
02706 return false;
02707 float* buffer = new float[maxn];
02708 float* wksp = new float[maxn];
02709 const int sz = int(vcl_log(double(maxn))/vcl_log(2.0));
02710 int* sizes = new int[sz];
02711
02712 #ifdef DEBUG
02713 vcl_cout << "Input:";
02714 for (int i = 0; i < ntot; i++)
02715 vcl_cout << ' ' << array[i];
02716 vcl_cout << vcl_endl;
02717 #endif
02718
02719 int nprev = 1;
02720 for (int d = ndim-1; d >= 0; d--) {
02721 int n = dims[d];
02722 int nnew = n * nprev;
02723 if (n >= 4)
02724 {
02725 for (int i2 = 0; i2 < ntot; i2 += nnew)
02726 for (int i1 = 0; i1 < nprev; i1++)
02727 {
02728 int i3 = i1 + i2;
02729 for (int k = 0; k < n; k++) {
02730 buffer[k] = array[i3];
02731 i3 += nprev;
02732 }
02733 if (forwardp) {
02734 for (int nn = n, l = nlevels;
02735 nn >= 4 && l > 0;
02736 nn /= 2, l--)
02737 WaveletTransformStep(buffer, nn, forwardp,
02738 lo_filter, hi_filter, ncof,
02739 wksp);
02740 }
02741 else {
02742 int s = 0;
02743 for (int nn = n, l = nlevels;
02744 nn >= 4 && l > 0;
02745 nn /= 2, l--, s++)
02746 sizes[s] = nn;
02747 for (s--; s >= 0; s--)
02748 WaveletTransformStep(buffer, sizes[s], forwardp,
02749 lo_filter, hi_filter, ncof,
02750 wksp);
02751 }
02752 i3 = i1 + i2;
02753 for (int k = 0; k < n; k++) {
02754 array[i3] = buffer[k];
02755 i3 += nprev;
02756 }
02757 }
02758 }
02759 nprev = nnew;
02760 }
02761 delete[] buffer;
02762 delete[] wksp;
02763 delete[] sizes;
02764 #ifdef DEBUG
02765 vcl_cout << "Output:";
02766 for (int i = 0; i < ntot; i++)
02767 vcl_cout << ' ' << array[i];
02768 vcl_cout << vcl_endl;
02769 #endif
02770 return true;
02771 }
02772
02773
02774
02775 void
02776 gevd_float_operators::WaveletTransformStep(float* array,
02777 const int* dims, const int ndim,
02778 const bool forwardp,
02779 const float* lo_filter,
02780 const float* hi_filter,
02781 const int ncof,
02782 float* buffer, float* wksp)
02783 {
02784 int ntot = dims[ndim];
02785 int nprev = 1;
02786 for (int d = ndim-1; d >= 0; d--) {
02787 int n = dims[d];
02788 int nnew = n * nprev;
02789 if (n >= 4) {
02790 for (int i2 = 0; i2 < ntot; i2 += nnew)
02791 for (int i1 = 0; i1 < nprev; i1++) {
02792 int i3 = i1 + i2;
02793 {for (int k = 0; k < n; k++) {
02794 buffer[k] = array[i3];
02795 i3 += nprev;
02796 }}
02797 WaveletTransformStep(buffer, n, forwardp,
02798 lo_filter, hi_filter, ncof,
02799 wksp);
02800 i3 = i1 + i2;
02801 for (int k = 0; k < n; k++) {
02802 array[i3] = buffer[k];
02803 i3 += nprev;
02804 }
02805 }
02806 }
02807 nprev = nnew;
02808 }
02809 }
02810
02811
02812
02813
02814
02815
02816
02817 void
02818 gevd_float_operators::CopyNdRecursive(const float* from_array,
02819 const int from_size, const int* from_dims,
02820 float* to_array,
02821 const int to_size, const int* to_dims,
02822 const int ndim,
02823 const bool fullp)
02824 {
02825 if (ndim == 1) {
02826 int size = vcl_min(from_size, to_size);
02827 for (int i = 0; i < size; i++)
02828 to_array[i] = from_array[i];
02829 }
02830 else {
02831 int from_n = from_dims[0], to_n = to_dims[0];
02832 int from_nsize = from_size / from_n;
02833 int to_nsize = to_size / to_n;
02834 int n = vcl_min(from_n, to_n);
02835 for (int i = 0; i < n; i++) {
02836 CopyNdRecursive(from_array, from_nsize, from_dims+1,
02837 to_array, to_nsize, to_dims+1,
02838 ndim-1, fullp);
02839 if (fullp) {
02840 from_array += from_nsize;
02841 to_array += to_nsize;
02842 }
02843 else {
02844 int block_size = vcl_max(from_nsize, to_nsize);
02845 from_array += block_size;
02846 to_array += block_size;
02847 }
02848 }
02849 }
02850 }
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862 bool
02863 gevd_float_operators::WaveletTransformByBlock(float* array,
02864 const int* dims, const int ndim,
02865 const bool forwardp, int nlevels,
02866 const int waveletno)
02867 {
02868 int ntot = 1, maxn = 0;
02869 {for (int d = 0; d < ndim; d++) {
02870 int dim = dims[d];
02871 ntot *= dim;
02872 if (dim > maxn) maxn = dim;
02873 }}
02874
02875 float* lo_filter = NULL;
02876 float* hi_filter = NULL;
02877 int ncof = 0;
02878 if (!FindWavelet(waveletno, lo_filter, hi_filter, ncof))
02879 return false;
02880
02881 int** level_dims = new int*[nlevels];
02882 level_dims[0] = new int[ndim+1];
02883 for (int d = 0; d < ndim; d++)
02884 level_dims[0][d] = dims[d];
02885 level_dims[0][ndim] = ntot;
02886 for (int l = 1; l < nlevels; l++) {
02887 level_dims[l] = new int[ndim+1];
02888 int n = 1;
02889 for (int d = 0; d < ndim; d++) {
02890 int nd = level_dims[l-1][d];
02891 if (nd >= 4)
02892 nd /= 2;
02893 level_dims[l][d] = nd;
02894 n *= nd;
02895 }
02896 level_dims[l][ndim] = n;
02897 }
02898 if (!forwardp) {
02899 int * swap;
02900 for (int l = 0; l < nlevels/2; l++) {
02901 swap = level_dims[l];
02902 level_dims[l] = level_dims[nlevels-1-l];
02903 level_dims[nlevels-1-l] = swap;
02904 }
02905 }
02906 float* sub_array = new float[ntot];
02907 float* buffer = new float[maxn];
02908 float* wksp = new float[maxn];
02909 {for (int l = 0; l < nlevels; l++) {
02910 int* sub_dims = level_dims[l];
02911 int n = sub_dims[ndim];
02912 CopyNdRecursive(array, ntot, dims,
02913 sub_array, n, sub_dims,
02914 ndim);
02915 WaveletTransformStep(sub_array, sub_dims, ndim,
02916 forwardp,
02917 lo_filter, hi_filter, ncof,
02918 buffer, wksp);
02919 CopyNdRecursive(sub_array, n, sub_dims,
02920 array, ntot, dims,
02921 ndim);
02922 }}
02923 delete[] sub_array;
02924 for (int l = 0; l < nlevels; l++)
02925 delete[] level_dims[l];
02926 delete[] level_dims;
02927 delete[] buffer;
02928 delete[] wksp;
02929 return true;
02930 }
02931
02932 #if 0 // unimplemented - TODO
02933 int
02934 gevd_float_operators::DeleteMixedComponents
02935 (float* wave,
02936 const int* dims, const int ndim,
02937 const int nlevels)
02938 {
02939 }
02940
02941 int
02942 gevd_float_operators::TruncateHighFrequencies
02943 (float* wave,
02944 const int* dims, const int ndim,
02945 const int nlevels,
02946 const float threshold=0.1)
02947 {
02948 }
02949
02950 int
02951 gevd_float_operators::TruncateLowestFrequency
02952 (float* wave,
02953 const int* dims, const int ndim,
02954 const int nlevels,
02955 float& average)
02956 {
02957 }
02958 #endif
02959
02960
02961 void
02962 gevd_float_operators::TestWavelets()
02963 {
02964 #if 0 // 1d testing commented out
02965 vcl_cout << "Testing wavelet transforms on 1d buffers\n";
02966 for (int n = 2; n <= 16; n++) {
02967 float* data = new float[n];
02968 for (int k = 2; k <= 12; k+=2) {
02969 for (int i = 0; i < n; i++)
02970 data[i] = i+1;
02971 wavelet_transform(data, n, true, k, 2);
02972 wavelet_transform(data, n, false, k, 2);
02973 float max_err = 0;
02974 for (int i = 0; i < n; i++) {
02975 float err = vcl_fabs(data[i] - i-1);
02976 if (err > max_err)
02977 max_err = err;
02978 }
02979 vcl_cout << " |data| = " << n
02980 << " |wavelet| = " << k
02981 << " |error| = " << max_err << vcl_endl;
02982 }
02983 delete[] data;
02984 }
02985 #endif
02986
02987 vcl_cout << "Testing wavelet transforms on nd buffers\n";
02988 for (int ndim = 1; ndim <= 4; ndim++)
02989 for (int s = 3; s <= 8; s++)
02990 {
02991 int* dims = new int[ndim+1];
02992 int ntot = 1;
02993 for (int d = 0; d < ndim; d++) {
02994 dims[d] = s;
02995 ntot *= s;
02996 }
02997 dims[ndim] = ntot;
02998 float* data = new float[ntot];
02999 for (int k = 2; k <= 12; k+=2)
03000 {
03001 for (int i = 0; i < ntot; i++) data[i] = float(i);
03002 int nlevels = 2;
03003 WaveletTransformByBlock(data, dims, ndim, true, nlevels, k);
03004 WaveletTransformByBlock(data, dims, ndim, false, nlevels, k);
03005 float max_err = 0;
03006 for (int i = 0; i < ntot; i++) {
03007 float err = (float)vcl_fabs(data[i] - i);
03008 if (err > max_err)
03009 max_err = err;
03010 }
03011 vcl_cout << " |dims| = " << ndim
03012 << " |data| = " << ntot
03013 << " |wavelet| = " << k
03014 << " |error| = " << max_err << vcl_endl;
03015 }
03016 delete[] data;
03017 delete[] dims;
03018 }
03019 }
03020
03021
03022
03023
03024
03025
03026
03027
03028 bool
03029 gevd_float_operators::WaveletTransformByIndex(const gevd_bufferxy& from, gevd_bufferxy*& to,
03030 const bool forwardp,
03031 int nlevels,
03032 const int waveletno)
03033 {
03034 to = gevd_float_operators::Allocate(to, from);
03035 int dims[3];
03036 dims[0] = to->GetSizeY();
03037 dims[1] = to->GetSizeX();
03038 dims[2] = dims[0] * dims[1];
03039 const float* from_array = (const float*) from.GetBuffer();
03040 float* to_array = (float*) to->GetBuffer();
03041 for (int i = 0; i < dims[2]; i++)
03042 to_array[i] = from_array[i];
03043 return gevd_float_operators::WaveletTransformByIndex(to_array,
03044 dims, 2,
03045 forwardp, nlevels,
03046 waveletno);
03047 }
03048
03049
03050
03051
03052
03053
03054
03055 bool
03056 gevd_float_operators::WaveletTransformByBlock(const gevd_bufferxy& from, gevd_bufferxy*& to,
03057 const bool forwardp,
03058 int nlevels,
03059 const int waveletno)
03060 {
03061 to = gevd_float_operators::Allocate(to, from);
03062 int dims[3];
03063 dims[0] = to->GetSizeY();
03064 dims[1] = to->GetSizeX();
03065 dims[2] = dims[0] * dims[1];
03066 const float* from_array = (const float*) from.GetBuffer();
03067 float* to_array = (float*) to->GetBuffer();
03068 for (int i = 0; i < dims[2]; i++)
03069 to_array[i] = from_array[i];
03070 return gevd_float_operators::WaveletTransformByBlock(to_array,
03071 dims, 2,
03072 forwardp, nlevels,
03073 waveletno);
03074 }
03075
03076
03077
03078
03079
03080
03081
03082 int
03083 gevd_float_operators::DeleteMixedComponents(gevd_bufferxy& wave,
03084 const int nlevels)
03085 {
03086 int sx = wave.GetSizeX(), sy = wave.GetSizeY(), count = 0;
03087 for (int l = 0; l < nlevels; l++) {
03088 int ssx = sx / 2, ssy = sy / 2;
03089 for (int y = ssy; y < sy; y++)
03090 for (int x = ssx; x < sx; x++)
03091 if (floatPixel(wave, x, y) != 0) {
03092 floatPixel(wave, x, y) = 0;
03093 count++;
03094 }
03095 sx = ssx; sy = ssy;
03096 }
03097 return count;
03098 }
03099
03100
03101
03102
03103
03104
03105
03106
03107 int
03108 gevd_float_operators::TruncateHighFrequencies(gevd_bufferxy& wave,
03109 const int nlevels,
03110 const float threshold)
03111 {
03112 int sx = wave.GetSizeX(), sy = wave.GetSizeY(), count = 0;
03113 for (int l = 0; l < nlevels; l++) {
03114 int ssx = sx / 2, ssy = sy / 2;
03115 float low = gevd_float_operators::Maximum(wave, sx-ssx, ssy, ssx, 0) * threshold;
03116 for (int y = 0; y < ssy; y++)
03117 for (int x = ssx; x < sx; x++)
03118 if (floatPixel(wave, x, y) < low) {
03119 floatPixel(wave, x, y) = 0;
03120 count++;
03121 }
03122 low = gevd_float_operators::Maximum(wave, ssx, sy-ssy, 0, ssy) * threshold;
03123 for (int y = ssy; y < sy; y++)
03124 for (int x = 0; x < ssx; x++)
03125 if (floatPixel(wave, x, y) < low) {
03126 floatPixel(wave, x, y) = 0;
03127 count++;
03128 }
03129 sx = ssx; sy = ssy;
03130 }
03131 return count;
03132 }
03133
03134
03135
03136
03137
03138 int
03139 gevd_float_operators::TruncateLowestFrequency(gevd_bufferxy& wave,
03140 const int nlevels)
03141 {
03142 int s = 1 << nlevels;
03143 int sx = wave.GetSizeX() / s, sy = wave.GetSizeY() / s;
03144 float average = gevd_float_operators::Sum(wave, sx, sy, 0, 0) / (sx * sy);
03145 int count = 0;
03146 for (int y = 0; y < sy; y++)
03147 for (int x = 0; x < sx; x++)
03148 if (floatPixel(wave, x, y) != average) {
03149 floatPixel(wave, x, y) = average;
03150 count++;
03151 }
03152 return count;
03153 }
03154
03155
03156
03157
03158
03159 int
03160 gevd_float_operators::DeleteBoundaryArtifacts(float* wave, const int n,
03161 const int nlevels)
03162 {
03163 if (nlevels == 0)
03164 return 0;
03165 else {
03166 int s = n, count = 0;
03167 for (int l = 0; l < nlevels; l++) {
03168 int ns = s / 2;
03169 int ss = ns * 2;
03170 if (ss < s) {
03171 wave[ss] = 0;
03172 count += 1;
03173 }
03174 s = ns;
03175 }
03176 return count;
03177 }
03178 }
03179
03180
03181
03182
03183
03184 int
03185 gevd_float_operators::DeleteBoundaryArtifacts(gevd_bufferxy& wave, const int nlevels)
03186 {
03187 if (nlevels == 0)
03188 return 0;
03189 else {
03190 int sx = wave.GetSizeX(), sy = wave.GetSizeY(), count = 0;
03191 for (int l = 0; l < nlevels; l++) {
03192 int ssx = sx / 2, ssy = sy / 2;
03193 int xx = ssx * 2, yy = ssy * 2;
03194 if (xx < sx) {
03195 for (int y = 0; y < sy; y++)
03196 floatPixel(wave, xx, y) = 0;
03197 count += sy;
03198 }
03199 if (yy < sy) {
03200 for (int x = 0; x < sx; x++)
03201 floatPixel(wave, x, yy) = 0;
03202 count += sx;
03203 }
03204 sx = ssx; sy = ssy;
03205 }
03206 return count;
03207 }
03208 }
03209
03210
03211
03212
03213 void
03214 gevd_float_operators::ProjectWaveOntoX(const gevd_bufferxy& wave,
03215 float*& proj, const int nlevels)
03216 {
03217 if (nlevels == 0)
03218 gevd_float_operators::ProjectOntoX(wave, proj);
03219 else {
03220 int sx = wave.GetSizeX(), sy = wave.GetSizeY();
03221 for (int l = 0; l < nlevels; l++) {
03222 int ssx = sx / 2, ssy = sy / 2;
03223 gevd_float_operators::ProjectOntoX(wave, proj, sx-ssx, ssy, ssx, 0);
03224 sx = ssx; sy = ssy;
03225 }
03226 }
03227 }
03228
03229 void
03230 gevd_float_operators::ProjectWaveOntoY(const gevd_bufferxy& wave, float*& proj,
03231 const int nlevels)
03232 {
03233 if (nlevels == 0)
03234 gevd_float_operators::ProjectOntoY(wave, proj);
03235 else {
03236 int sx = wave.GetSizeX(), sy = wave.GetSizeY();
03237 for (int l = 0; l < nlevels; l++) {
03238 int ssx = sx / 2, ssy = sy / 2;
03239 gevd_float_operators::ProjectOntoY(wave, proj, ssx, sy-ssy, 0, ssy);
03240 sx = ssx; sy = ssy;
03241 }
03242 }
03243 }
03244
03245
03246
03247
03248
03249
03250
03251 void
03252 gevd_float_operators::ProjectOntoX(const gevd_bufferxy& buf, float*& proj,
03253 int sizeX, int sizeY, int origX, int origY)
03254 {
03255 if (sizeX == 0)
03256 sizeX = buf.GetSizeX();
03257 if (sizeY == 0)
03258 sizeY = buf.GetSizeY();
03259 if (proj == NULL)
03260 proj = new float [buf.GetSizeX()];
03261 int hiX = origX + sizeX, hiY = origY + sizeY;
03262 for (int x = origX; x < hiX; x++) {
03263 float projx = 0;
03264 for (int y = origY; y < hiY; y++)
03265 projx += floatPixel(buf, x, y);
03266 proj[x] = projx / sizeY;
03267 }
03268 }
03269
03270 void
03271 gevd_float_operators::ProjectOntoY(const gevd_bufferxy& buf, float*& proj,
03272 int sizeX, int sizeY, int origX, int origY)
03273 {
03274 if (sizeX == 0)
03275 sizeX = buf.GetSizeX();
03276 if (sizeY == 0)
03277 sizeY = buf.GetSizeY();
03278 if (proj == NULL)
03279 proj = new float [buf.GetSizeY()];
03280 int hiX = origX + sizeX, hiY = origY + sizeY;
03281 for (int y = origY; y < hiY; y++) {
03282 float projy = 0;
03283 for (int x = origX; x < hiX; x++)
03284 projy += floatPixel(buf, x, y);
03285 proj[y] = projy / sizeX;
03286 }
03287 }
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298 float
03299 gevd_float_operators::Correlation(const float* data, const int length,
03300 const float* pattern, const int radius,
03301 const int index)
03302 {
03303 int xmin = index-radius, xmax = index+radius+1;
03304 int ymin = 0;
03305
03306 if (xmin < 0) { ymin = -xmin; xmin = 0; }
03307 if (xmax > length) xmax = length;
03308 int sum1 = xmax - xmin;
03309 if (sum1 < radius)
03310 return 0;
03311 else {
03312 register double sumx=0, sumy=0, sumxx=0, sumyy=0, sumxy=0, xval, yval;
03313 for (register int x = xmin, y = ymin; x < xmax; x++, y++) {
03314 xval = data[x]; yval = pattern[y];
03315 sumxy += xval * yval;
03316 sumx += xval;
03317 sumy += yval;
03318 sumxx += xval * xval;
03319 sumyy += yval * yval;
03320 }
03321 double varx = sum1 * sumxx - sumx * sumx;
03322 double vary = sum1 * sumyy - sumy * sumy;
03323 double cvar = sum1 * sumxy - sumx * sumy;
03324 if (varx!=0 && vary!=0) cvar /= vcl_sqrt(varx * vary);
03325 return (float)cvar / (float)vcl_sqrt(varx * vary);
03326 }
03327 }
03328
03329
03330
03331
03332
03333
03334
03335 float*
03336 gevd_float_operators::Correlations(const float* data, const int length,
03337 const float* pattern, const int radius,
03338 const int index, const int search)
03339 {
03340 int ns = 2*search + 1;
03341 float* result = new float[ns];
03342 result[search] = gevd_float_operators::Correlation(data, length,
03343 pattern, radius,
03344 index);
03345 for (int s = 1; s <= search; s++) {
03346 result[search+s] = gevd_float_operators::Correlation(data, length,
03347 pattern, radius,
03348 index+s);
03349 result[search-s] = gevd_float_operators::Correlation(data, length,
03350 pattern, radius,
03351 index-s);
03352 }
03353 #ifdef DEBUG
03354 vcl_cout << "correlations =";
03355 for (int s = 0; s < ns; s++)
03356 vcl_cout << ' ' << result[s];
03357 vcl_cout << vcl_endl;
03358 #endif
03359 return result;
03360 }
03361
03362
03363
03364
03365 float
03366 gevd_float_operators::BestCorrelation(const float* data, const int length,
03367 const float* pattern, const int radius,
03368 int& shift, const int search)
03369 {
03370 float* cors = gevd_float_operators::Correlations(data, length,
03371 pattern, radius,
03372 (length/2) + shift,
03373 search);
03374 int index = 0; float peak = 0;
03375 bool found = gevd_float_operators::Maximum(cors, 2*search+1, index, peak);
03376 delete[] cors;
03377 if (found) {
03378 shift += index - search;
03379 return peak;
03380 }
03381 return 0;
03382 }
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397 float
03398 gevd_float_operators::CoarseFineCorrelation(const float* dataPyr, const int dlength,
03399 const float* patternPyr, const int plength,
03400 float& shift,
03401 const int coarse, const int fine,
03402 const float cutoff,
03403 const float overlap,
03404 float* matches)
03405 {
03406 const float NOISE = 0.2f;
03407
03408
03409
03410 #ifdef DEBUG
03411 vcl_cout << "shift0 = " << shift << vcl_endl;
03412 #endif
03413 if (shift != 0)
03414 shift /= (1 << coarse);
03415 shift = (float)rint(shift);
03416 int dlen = dlength >> coarse, plen = plength >> coarse;
03417 int rmax = int((1 - overlap) * dlen + 0.5);
03418 if (rmax < 1) rmax = 1;
03419 float* cors = Correlations(dataPyr+dlen, dlen,
03420 patternPyr+plen, plen,
03421 int(shift), rmax);
03422 const int NOMATCH = -1;
03423 float match = NOISE; int mi = NOMATCH;
03424 const int lmax = (rmax << 1);
03425 for (int i = 1; i < lmax; i++) {
03426 float cor = cors[i];
03427 if (cor > match &&
03428 cors[i-1] < cor && cor > cors[i+1]) {
03429 match = cor;
03430 mi = i;
03431 }
03432 }
03433 if (mi == NOMATCH)
03434 match = cors[rmax];
03435 else {
03436 float left = cors[mi-1], mid = cors[mi], right = cors[mi+1];
03437 shift += (mi - rmax) + InterpolateParabola(left, mid, right, match);
03438 #ifdef DEBUG
03439 vcl_cout << left << ' ' << mid << ' ' << right << vcl_endl
03440 << "level = " << coarse
03441 << " shift = " << shift * (1 << coarse)
03442 << " match = " << match << vcl_endl;
03443 #endif
03444 }
03445 delete[] cors;
03446
03447
03448 const int SEARCH = 1, RMAX = 3;
03449 int k = coarse-1;
03450 for (; ; k--) {
03451 shift = (float)rint(2*shift);
03452 dlen = dlength >> k, plen = plength >> k;
03453 cors = Correlations(dataPyr+dlen, dlen,
03454 patternPyr+plen, plen,
03455 int(shift), SEARCH);
03456 float local = 0;
03457 int r = 0;
03458 for (; r < RMAX; r++) {
03459 float left = cors[0], mid = cors[1], right = cors[2];
03460 #ifdef DEBUG
03461 vcl_cout << left << ' ' << mid << ' ' << right << vcl_endl;
03462 #endif
03463 if (left <= mid && mid >= right && mid > NOISE) {
03464 local += InterpolateParabola(left, mid, right, match);
03465 if (matches) matches[k] += match;
03466 break;
03467 }
03468 if (r < RMAX-1) {
03469 if (right > left) {
03470 local += 1;
03471 cors[0] = cors[1];
03472 cors[1] = cors[2];
03473 cors[2] = Correlation(dataPyr+dlen, dlen,
03474 patternPyr+plen, plen,
03475 int(local)+SEARCH);
03476 }
03477 if (left > right) {
03478 local -= 1;
03479 cors[2] = cors[1];
03480 cors[1] = cors[0];
03481 cors[0] = Correlation(dataPyr+dlen, dlen,
03482 patternPyr+plen, plen,
03483 int(local)-SEARCH);
03484 }
03485 }
03486 }
03487 delete[] cors;
03488 if (r == RMAX)
03489 break;
03490 shift += local;
03491 #ifdef DEBUG
03492 vcl_cout << "level = " << k
03493 << " shift = " << shift * (1 << k)
03494 << " match = " << match << vcl_endl;
03495 #endif
03496 if (match <= cutoff || k == fine)
03497 break;
03498 }
03499 if (k > 0) shift *= (1 << k);
03500 if (k > fine)
03501 match *= float(coarse - k + 1) / (coarse - fine + 1);
03502 return match;
03503 }
03504
03505
03506
03507
03508 void
03509 gevd_float_operators::Apply(gevd_bufferxy& buf, float (*func)(float))
03510 {
03511 int size = buf.GetSizeX() * buf.GetSizeY();
03512 float* data = (float*) buf.GetBuffer();
03513 for (int i = 1; i < size; i++)
03514 data[i] = func(data[i]);
03515 }
03516
03517
03518
03519
03520 gevd_bufferxy*
03521 gevd_float_operators::Allocate(gevd_bufferxy* space, const gevd_bufferxy& model,
03522 int bits_per_pixel, int sizeX, int sizeY)
03523 {
03524 if (!bits_per_pixel)
03525 bits_per_pixel = model.GetBitsPixel();
03526 if (!sizeX)
03527 sizeX = model.GetSizeX();
03528 if (!sizeY)
03529 sizeY = model.GetSizeY();
03530 if (space == NULL ||
03531 space->GetBitsPixel() != bits_per_pixel ||
03532 space->GetSizeX() < sizeX || space->GetSizeY() < sizeY) {
03533 delete space;
03534 space = new gevd_bufferxy(sizeX, sizeY, bits_per_pixel);
03535 }
03536 return space;
03537 }
03538
03539
03540
03541 gevd_bufferxy*
03542 gevd_float_operators::SimilarBuffer(const gevd_bufferxy& buf,
03543 int bits_per_pixel,
03544 int sizeX, int sizeY)
03545 {
03546 if (bits_per_pixel == 0)
03547 bits_per_pixel = buf.GetBitsPixel();
03548 if (sizeX == 0)
03549 sizeX = buf.GetSizeX();
03550 if (sizeY == 0)
03551 sizeY = buf.GetSizeY();
03552 return new gevd_bufferxy(sizeX, sizeY, bits_per_pixel);
03553 }
03554
03555
03556
03557
03558 bool
03559 gevd_float_operators::IsSimilarBuffer(const gevd_bufferxy& buf1,
03560 const gevd_bufferxy& buf2)
03561 {
03562 return buf1.GetSizeX() == buf2.GetSizeX() &&
03563 buf1.GetSizeY() == buf2.GetSizeY() &&
03564 buf1.GetBitsPixel() == buf2.GetBitsPixel();
03565 }
03566
03567
03568
03569
03570
03571
03572
03573 gevd_bufferxy*
03574 gevd_float_operators::Extract(const gevd_bufferxy & buf,
03575 int sizeX, int sizeY, int origX, int origY)
03576 {
03577 if (sizeX == 0)
03578 sizeX = buf.GetSizeX();
03579 if (sizeY == 0)
03580 sizeY = buf.GetSizeY();
03581 gevd_bufferxy& sub = *gevd_float_operators::SimilarBuffer(buf, 0, sizeX, sizeY);
03582 for (int y = 0; y < sizeY; y++)
03583 for (int x = 0; x < sizeX; x++)
03584 floatPixel(sub, x, y) = floatPixel(buf, origX+x, origY+y);
03585 return ⊂
03586 }
03587
03588
03589
03590
03591 void
03592 gevd_float_operators::Update(gevd_bufferxy& buf, const gevd_bufferxy& sub,
03593 int origX, int origY)
03594 {
03595 int sizeX = sub.GetSizeX(), sizeY = sub.GetSizeY();
03596 for (int y = 0; y < sizeY; y++)
03597 for (int x = 0; x < sizeX; x++)
03598 floatPixel(buf, origX+x, origY+y) = floatPixel(sub, x, y);
03599 }
03600
03601
03602
03603 void
03604 gevd_float_operators::Fill(gevd_bufferxy& buf, const float value,
03605 int sizeX, int sizeY,
03606 int origX, int origY)
03607 {
03608 if (sizeX == 0)
03609 sizeX = buf.GetSizeX();
03610 if (sizeY == 0)
03611 sizeY = buf.GetSizeY();
03612 int endX = origX + sizeX, endY = origY + sizeY;
03613 for (int y = origY; y < endY; y++)
03614 for (int x = origX; x < endX; x++)
03615 floatPixel(buf, x, y) = value;
03616 }
03617
03618
03619
03620
03621
03622
03623 void
03624 gevd_float_operators::FillFrameX(gevd_bufferxy& buf, const float value, const int width)
03625 {
03626 const int hix = buf.GetSizeX(), hiy = buf.GetSizeY();
03627 const int framelox = width, framehix = hix - width;
03628 for (int y = 0; y < hiy; ++y)
03629 for (int x = 0; x < framelox; ++x)
03630 floatPixel(buf, x, y) = value;
03631 for (int y = 0; y < hiy; ++y)
03632 for (int x = framehix; x < hix; ++x)
03633 floatPixel(buf, x, y) = value;
03634 }
03635
03636
03637
03638 void
03639 gevd_float_operators::FillFrameY(gevd_bufferxy& buf, const float value, const int width)
03640 {
03641 int lox = 0, hix = buf.GetSizeX();
03642 int loy = 0, hiy = buf.GetSizeY();
03643 int frameloy = width, framehiy = hiy - width;
03644 for (int y = loy; y < frameloy; y++)
03645 for (int x = lox; x < hix; x++)
03646 floatPixel(buf, x, y) = value;
03647 for (int y = framehiy; y < hiy; y++)
03648 for (int x = lox; x < hix; x++)
03649 floatPixel(buf, x, y) = value;
03650 }
03651
03652
03653
03654
03655 void
03656 gevd_float_operators::DrawFrame(gevd_bufferxy& buf, const int loc, const float value)
03657 {
03658 const int hix = buf.GetSizeX()-loc-1;
03659 const int hiy = buf.GetSizeY()-loc-1;
03660 for (int x = loc; x <= hix; x++) {
03661 floatPixel(buf, x, loc) = value;
03662 floatPixel(buf, x, hiy) = value;
03663 }
03664 for (int y = loc; y <= hiy; y++) {
03665 floatPixel(buf, loc, y) = value;
03666 floatPixel(buf, hix, y) = value;
03667 }
03668 }
03669
03670
03671
03672 float
03673 gevd_float_operators::Maximum(const gevd_bufferxy& buf,
03674 int sizeX, int sizeY, int origX, int origY)
03675 {
03676 if (sizeX == 0)
03677 sizeX = buf.GetSizeX();
03678 if (sizeY == 0)
03679 sizeY = buf.GetSizeY();
03680 int maxx = origX + sizeX, maxy = origY + sizeY;
03681 float hi = floatPixel(buf, origX, origY), f;
03682 for (int y = origY; y < maxy; y++)
03683 for (int x = origX; x < maxx; x++) {
03684 f = floatPixel(buf, x, y);
03685 if (f > hi) hi = f;
03686 }
03687 return hi;
03688 }
03689
03690
03691
03692 float
03693 gevd_float_operators::Minimum(const gevd_bufferxy& buf,
03694 int sizeX, int sizeY, int origX, int origY)
03695 {
03696 if (sizeX == 0)
03697 sizeX = buf.GetSizeX();
03698 if (sizeY == 0)
03699 sizeY = buf.GetSizeY();
03700 int maxx = origX + sizeX, maxy = origY + sizeY;
03701 float lo = floatPixel(buf, origX, origY), f;
03702 for (int y = origY; y < maxy; y++)
03703 for (int x = origX; x < maxx; x++) {
03704 f = floatPixel(buf, x, y);
03705 if (f < lo) lo = f;
03706 }
03707 return lo;
03708 }
03709
03710
03711
03712 float
03713 gevd_float_operators::Sum(const gevd_bufferxy& buf,
03714 int sizeX, int sizeY, int origX, int origY)
03715 {
03716 if (sizeX == 0)
03717 sizeX = buf.GetSizeX();
03718 if (sizeY == 0)
03719 sizeY = buf.GetSizeY();
03720 int maxx = origX + sizeX, maxy = origY + sizeY;
03721 float sum = 0;
03722 for (int y = origY; y < maxy; y++)
03723 for (int x = origX; x < maxx; x++)
03724 sum += floatPixel(buf, x, y);
03725 return sum;
03726 }
03727
03728
03729
03730
03731 int
03732 gevd_float_operators::Threshold(gevd_bufferxy& buf, float noise,
03733 int sizeX, int sizeY,
03734 int origX, int origY)
03735 {
03736 if (sizeX == 0)
03737 sizeX = buf.GetSizeX();
03738 if (sizeY == 0)
03739 sizeY = buf.GetSizeY();
03740 int maxx = origX + sizeX, maxy = origY + sizeY;
03741 int count = 0; float pix;
03742 for (int y = origY; y < maxy; y++)
03743 for (int x = origX; x < maxx; x++)
03744 if ((pix = floatPixel(buf, x, y)) && pix < noise) {
03745 floatPixel(buf, x, y) = 0;
03746 count++;
03747 }
03748 return count;
03749 }
03750
03751
03752
03753
03754
03755
03756
03757
03758 void
03759 gevd_float_operators::Normalize(gevd_bufferxy& buf, const float lo, const float hi)
03760 {
03761 int size = (buf.GetSizeX() * buf.GetSizeY());
03762 float* data = (float*) buf.GetBuffer();
03763 float flo, fhi, f;
03764 flo = fhi = data[0];
03765 for (int i = 1; i < size; i++) {
03766 f = data[i];
03767 if (f < flo) flo = f;
03768 if (f > fhi) fhi = f;
03769 }
03770 if (fhi == flo)
03771 for (int i = 0; i < size; i++)
03772 data[i] = lo;
03773 else {
03774 float scale = (hi - lo) / (fhi - flo);
03775 for (int i = 0; i < size; i++)
03776 data[i] = scale * (data[i] - flo) + lo;
03777 }
03778 }
03779
03780
03781
03782
03783 void
03784 gevd_float_operators::ShiftToPositive(gevd_bufferxy& buf)
03785 {
03786 const float zero = 30000, lo = 0, hi = 60000;
03787 int size = (buf.GetSizeX() * buf.GetSizeY());
03788 float* data = (float*) buf.GetBuffer();
03789 for (int i = 0; i < size; i++) {
03790 float f = data[i] + zero;
03791 if (f < lo)
03792 f = lo;
03793 else if (f > hi)
03794 f = hi;
03795 data[i] = f;
03796 }
03797 }
03798
03799
03800
03801
03802 float
03803 gevd_float_operators::TruncateToPositive(gevd_bufferxy& buf)
03804 {
03805 int size = (buf.GetSizeX() * buf.GetSizeY());
03806 float* data = (float*) buf.GetBuffer();
03807 float diff = 0, d;
03808 for (int i = 0; i < size; i++) {
03809 d = data[i];
03810 if (d < 0) {
03811 data[i] = 0;
03812 d = - d;
03813 if (d > diff) diff = d;
03814 }
03815 }
03816 return diff;
03817 }
03818
03819
03820
03821 void
03822 gevd_float_operators::Scale(gevd_bufferxy& buf, float factor)
03823 {
03824 if (factor != 0) {
03825 int size = (buf.GetSizeX() * buf.GetSizeY());
03826 float* data = (float*) buf.GetBuffer();
03827 for (int i = 0; i < size; i++)
03828 data[i] *= factor;
03829 }
03830 }
03831
03832
03833
03834 void
03835 gevd_float_operators::Absolute(gevd_bufferxy& buf)
03836 {
03837 int size = (buf.GetSizeX() * buf.GetSizeY());
03838 float* data = (float*) buf.GetBuffer();
03839 for (int i = 0; i < size; i++)
03840 if (data[i] < 0)
03841 data[i] = - data[i];
03842 }
03843
03844
03845
03846 void
03847 gevd_float_operators::Negate(gevd_bufferxy& buf)
03848 {
03849 int size = (buf.GetSizeX() * buf.GetSizeY());
03850 float* data = (float*) buf.GetBuffer();
03851 for (int i = 0; i < size; i++)
03852 data[i] = - data[i];
03853 }
03854
03855
03856 float
03857 gevd_float_operators::TruncateToCeiling(gevd_bufferxy& buf, float ceilng)
03858 {
03859 int size = (buf.GetSizeX() * buf.GetSizeY());
03860 float* data = (float*) buf.GetBuffer();
03861 float diff = 0, d;
03862 for (int i = 0; i < size; i++) {
03863 d = data[i];
03864 if (d > ceilng) {
03865 data[i] = ceilng;
03866 d -= ceilng;
03867 if (d > diff) diff = d;
03868 }
03869 }
03870 return diff;
03871 }
03872
03873
03874
03875
03876
03877
03878
03879 bool
03880 gevd_float_operators::BufferToFloat(const gevd_bufferxy& from, gevd_bufferxy& to)
03881 {
03882 assert (&to != &from);
03883 assert (from.GetSizeX() == to.GetSizeX() && from.GetSizeY() == to.GetSizeY());
03884 assert (to.GetBytesPixel() == sizeof(float));
03885 int size = (to.GetSizeX() * to.GetSizeY());
03886 switch (from.GetBytesPixel())
03887 {
03888 case sizeof(unsigned char): {
03889 const unsigned char* frombuf = (const unsigned char*) from.GetBuffer();
03890 float* tobuf = (float*) to.GetBuffer();
03891 for (int i = 0; i < size; i++)
03892 tobuf[i] = (float) frombuf[i];
03893 break;
03894 }
03895 case sizeof(short): {
03896 const short* frombuf = (const short*) from.GetBuffer();
03897 float* tobuf = (float*) to.GetBuffer();
03898 for (int i = 0; i < size; i++)
03899 tobuf[i] = (float) frombuf[i];
03900 break;
03901 }
03902 case 3*sizeof(unsigned char): {
03903 vcl_cerr << "gevd_float_operators::BufferToFloat: taking luminance of RGB buffer\n";
03904 const unsigned char* frombuf = (const unsigned char*) from.GetBuffer();
03905 float* tobuf = (float*) to.GetBuffer();
03906 for (int i = 0; i < size; i++)
03907 tobuf[i] = 0.299f*frombuf[3*i]+0.587f*frombuf[3*i+1]+0.114f*frombuf[3*i+2];
03908 break;
03909 }
03910 case sizeof(int): {
03911 const unsigned int* frombuf = (const unsigned int*) from.GetBuffer();
03912 float* tobuf = (float*) to.GetBuffer();
03913 for (int i = 0; i < size; i++)
03914 tobuf[i] = (float)frombuf[i];
03915 break;
03916 }
03917 default:
03918 vcl_cerr << "Can only convert unsigned char/short/int/RGB buffer to float\n";
03919 return false;
03920 }
03921 return true;
03922 }
03923
03924 bool
03925 gevd_float_operators::FloatToBuffer (const gevd_bufferxy& from, gevd_bufferxy& to)
03926 {
03927 assert (&to != &from);
03928 assert (from.GetSizeX() == to.GetSizeX() && from.GetSizeY() == to.GetSizeY());
03929 assert (from.GetBytesPixel() == sizeof(float));
03930 int size = (to.GetSizeX() * to.GetSizeY());
03931 switch (to.GetBytesPixel())
03932 {
03933 case sizeof(unsigned char): {
03934 const float* frombuf = (const float*) from.GetBuffer();
03935 unsigned char* tobuf = (unsigned char*) to.GetBuffer();
03936 for (int i = 0; i < size; i++)
03937 tobuf[i] = (unsigned char) int(frombuf[i]);
03938 return true;
03939 }
03940 case sizeof(short): {
03941 const float* frombuf = (const float*) from.GetBuffer();
03942 short* tobuf = (short*) to.GetBuffer();
03943 for (int i = 0; i < size; i++)
03944 tobuf[i] = (short) int(frombuf[i]);
03945 return true;
03946 }
03947 case 3*sizeof(unsigned char): {
03948 const float* frombuf = (const float*) from.GetBuffer();
03949 unsigned char* tobuf = (unsigned char*) to.GetBuffer();
03950 for (int i = 0; i < size; i++)
03951 tobuf[3*i] = tobuf[3*i+1] = tobuf[3*i+2] = (unsigned char) int(frombuf[i]);
03952 return true;
03953 }
03954 default:
03955 vcl_cerr << "Can only convert float to unsigned char/short/RGB buffer\n";
03956 return false;
03957 }
03958 }
03959
03960
03961
03962
03963 bool
03964 gevd_float_operators::Maximum(const float* data, const int length,
03965 int& index, float& value)
03966 {
03967 index = 0;
03968 float left, mid = data[0], right = data[1];
03969 for (int r = 2; r < length; r++) {
03970 left = mid;
03971 mid = right;
03972 right = data[r];
03973 if (mid > left && mid > right) {
03974 if (index) {
03975 if (mid > value) {
03976 value = mid;
03977 index = r-1;
03978 }
03979 }
03980 else {
03981 value = mid;
03982 index = r-1;
03983 }
03984 }
03985 }
03986 return !(index == 0);
03987 }
03988
03989
03990
03991
03992
03993
03994
03995 gevd_bufferxy*
03996 gevd_float_operators::PadToPowerOf2(gevd_bufferxy& buf)
03997 {
03998 int sizeX = buf.GetSizeX();
03999 int sizeY = buf.GetSizeY();
04000 int newSizeX = sizeX, newSizeY = sizeY;
04001 {
04002 double exptX = vcl_log(double(sizeX))/vcl_log(2.0),
04003 exptY = vcl_log(double(sizeY))/vcl_log(2.0);
04004 double ceilX = vcl_ceil(exptX), ceilY = vcl_ceil(exptY);
04005 if (exptX < ceilX)
04006 newSizeX = 1 << int(ceilX);
04007 if (exptY < ceilY)
04008 newSizeY = 1 << int(ceilY);
04009 }
04010 if (newSizeX == sizeX && newSizeY == sizeY)
04011 return &buf;
04012 int lpadX = (newSizeX - sizeX) / 2, lpadY = (newSizeY - sizeY) / 2;
04013 gevd_bufferxy& padded = *gevd_float_operators::SimilarBuffer(buf, bits_per_float,
04014 newSizeX, newSizeY);
04015 padded.Clear();
04016 gevd_float_operators::Update(padded, buf, lpadX, lpadY);
04017 int hpadX = newSizeX-lpadX-sizeX, hpadY = newSizeY-lpadY-sizeY;
04018 lpadX++; lpadY++;
04019 hpadX++; hpadY++;
04020 float corner = (2*floatPixel(buf, 0, 0) +
04021 floatPixel(buf, 1, 0) + floatPixel(buf, 0, 1)) / 4;
04022 gevd_float_operators::Fill(padded, corner,
04023 lpadX, lpadY, 0, 0);
04024 corner = (2*floatPixel(buf, sizeX-1, 0) +
04025 floatPixel(buf, sizeX-2, 0) + floatPixel(buf, sizeX-1, 1)) / 4;
04026 gevd_float_operators::Fill(padded, corner,
04027 hpadX, lpadY, newSizeX-hpadX, 0);
04028 corner = (2*floatPixel(buf, 0, sizeY-1) +
04029 floatPixel(buf, 1, sizeY-1) + floatPixel(buf, 0, sizeY-2)) / 4;
04030 gevd_float_operators::Fill(padded, corner,
04031 lpadX, hpadY, 0, newSizeY-hpadY);
04032 corner = (2*floatPixel(buf, sizeX-1, sizeY-1) +
04033 floatPixel(buf, sizeX-2, sizeY-1) +
04034 floatPixel(buf, sizeX-1, sizeY-2)) / 4;
04035 gevd_float_operators::Fill(padded, corner,
04036 hpadX, hpadY, newSizeX-hpadX, newSizeY-hpadY);
04037 int x_1, x_2, y_1, y_2;
04038 x_1 = lpadX; x_2 = newSizeX-hpadX;
04039 for (int x = x_1; x < x_2; x++) {
04040 float top = (floatPixel(buf, x-lpadX, 0) +
04041 2*floatPixel(buf, x-lpadX+1, 0) +
04042 floatPixel(buf, x-lpadX+2, 0)) / 4;
04043 y_1 = 0; y_2 = lpadY-1;
04044 for (int y = y_1; y < y_2; y++)
04045 floatPixel(padded, x, y) = top;
04046 float bottom = (floatPixel(buf, x-lpadX, sizeY-1) +
04047 2*floatPixel(buf, x-lpadX+1, sizeY-1) +
04048 floatPixel(buf, x-lpadX+2, sizeY-1)) / 4;
04049 y_1 = newSizeY-hpadY+1; y_2 = newSizeY;
04050 for (int y = y_1; y < y_2; y++)
04051 floatPixel(padded, x, y) = bottom;
04052 }
04053 y_1 = lpadY; y_2 = newSizeY-hpadY;
04054 for (int y = y_1; y < y_2; y++) {
04055 float left = (floatPixel(buf, 0, y-lpadY) +
04056 2*floatPixel(buf, 0, y-lpadY+1) +
04057 floatPixel(buf, 0, y-lpadY+2)) / 4;
04058 x_1 = 0; x_2 = lpadX-1;
04059 for (int x = x_1; x < x_2; x++)
04060 floatPixel(padded, x, y) = left;
04061 float right = (floatPixel(buf, sizeX-1, y-lpadY) +
04062 2*floatPixel(buf, sizeX-1, y-lpadY+1) +
04063 floatPixel(buf, sizeX-1, y-lpadY+2)) / 4;
04064 x_1 = newSizeX-hpadX+1; x_2 = newSizeX;
04065 for (int x = x_1; x < x_2; x++)
04066 floatPixel(padded, x, y) = right;
04067 }
04068 return &padded;
04069 }
04070
04071
04072
04073 gevd_bufferxy*
04074 gevd_float_operators::UnpadFromPowerOf2(gevd_bufferxy& padded, int sizeX, int sizeY)
04075 {
04076 int newSizeX = padded.GetSizeX();
04077 int newSizeY = padded.GetSizeY();
04078 if (newSizeX == sizeX && newSizeY == sizeY)
04079 return &padded;
04080 else
04081 return gevd_float_operators::Extract(padded,
04082 sizeX, sizeY,
04083 (newSizeX - sizeX)/2,
04084 (newSizeY - sizeY)/2);
04085 }
04086
04087 gevd_bufferxy*
04088 gevd_float_operators::TransposeExtract(const gevd_bufferxy & buf,
04089 int sizeX, int sizeY, int origX, int origY)
04090 {
04091 gevd_bufferxy& sub = *gevd_float_operators::SimilarBuffer(buf, 0, sizeY, sizeX);
04092 for (int y = 0; y < sizeY; y++)
04093 for (int x = 0; x < sizeX; x++)
04094 floatPixel(sub, y, x) = floatPixel(buf, origX+x, origY+y);
04095 return ⊂
04096 }
04097
04098 void
04099 gevd_float_operators::TransposeUpdate(gevd_bufferxy& buf, const gevd_bufferxy& sub,
04100 int origX, int origY)
04101 {
04102 int sizeX = sub.GetSizeY(), sizeY = sub.GetSizeX();
04103 for (int y = 0; y < sizeY; y++)
04104 for (int x = 0; x < sizeX; x++)
04105 floatPixel(buf, origX+x, origY+y) = floatPixel(sub, y, x);
04106 }
04107
04108
04109 gevd_bufferxy*
04110 gevd_float_operators::AbsoluteDifference(const gevd_bufferxy& buf1,
04111 const gevd_bufferxy& buf2)
04112 {
04113 if (!IsSimilarBuffer(buf1, buf2))
04114 return NULL;
04115 else {
04116 int sizeX = buf1.GetSizeX(), sizeY = buf1.GetSizeY();
04117 gevd_bufferxy& buf = *gevd_float_operators::SimilarBuffer(buf1);
04118 for (int y = 0; y < sizeY; y++)
04119 for (int x = 0; x < sizeX; x++) {
04120 float diff = floatPixel(buf1, x, y) - floatPixel(buf2, x, y);
04121 if (diff < 0) diff = -diff;
04122 floatPixel(buf, x, y) = diff;
04123 }
04124 return &buf;
04125 }
04126 }