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