00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "Image/Kernels.H"
00037 #include "Image/MathOps.H"
00038 #include "Image/LowPass.H"
00039 #include "Image/LowPassLpt.H"
00040
00041 #include "ModelNeuron/Weights.H"
00042
00043
00044
00045
00046 namespace WeightFilter
00047 {
00048
00049 Image<double>
00050 convolveHmax(const Image<double>& src, const Image<double>& filter)
00051 {
00052 ASSERT(src.initialized());
00053 const int Nx = filter.getWidth(), Ny = filter.getHeight();
00054 ASSERT((Nx & 1) && (Ny & 1));
00055
00056 const int w = src.getWidth(), h = src.getHeight();
00057
00058 Image<double> result(w, h, NO_INIT);
00059 Image<double>::const_iterator sptr = src.begin();
00060 Image<double>::iterator dptr = result.beginw();
00061 Image<double>::const_iterator const filt = filter.begin();
00062
00063 int kkk = Nx * Ny - 1;
00064 int Nx2 = (Nx - 1) / 2, Ny2 = (Ny - 1) / 2;
00065
00066
00067 for (int j = 0; j < h; ++j)
00068 for (int i = 0; i < w; ++i)
00069 {
00070 double sum = 0.0, sumw = 0.0;
00071 for (int kj = 0; kj < Ny; ++kj)
00072 {
00073 int kjj = kj + j - Ny2;
00074 if (kjj >= 0 && kjj < h)
00075 for (int ki = 0; ki < Nx; ++ki)
00076 {
00077 int kii = ki + i - Nx2;
00078 if (kii >= 0 && kii < w)
00079 {
00080 double fil = filt[kkk - ki - Nx*kj];
00081 double img = sptr[kii + w * kjj];
00082 sum += img * fil; sumw += img * img;
00083 }
00084 }
00085 }
00086
00087 if (sumw > 0.0) sum = fabs(sum)/sqrt(sumw);
00088 *dptr++ = sum;
00089 }
00090 return result;
00091 }
00092
00093
00094 Image<double>
00095 optConvolve(const Image<double>& src, const Image<double>& f)
00096 {
00097 ASSERT(src.initialized());
00098
00099 const int src_w = src.getWidth();
00100 const int src_h = src.getHeight();
00101
00102 Image<double>::const_iterator filter = f.begin();
00103 const int fil_w = f.getWidth();
00104 const int fil_h = f.getHeight();
00105
00106 ASSERT((fil_w & 1) && (fil_h & 1));
00107
00108 Image<double> result(src_w, src_h, NO_INIT);
00109 Image<double>::const_iterator sptr = src.begin();
00110 Image<double>::iterator dptr = result.beginw();
00111
00112 const int fil_end = fil_w * fil_h - 1;
00113 const int Nx2 = (fil_w - 1) / 2;
00114 const int Ny2 = (fil_h - 1) / 2;
00115
00116 const int srow_skip = src_w-fil_w;
00117
00118 for (int dst_y = 0; dst_y < src_h; ++dst_y)
00119 {
00120
00121 const bool y_clean = dst_y >= Ny2 && dst_y < (src_h - Nx2);
00122
00123 for (int dst_x = 0; dst_x < src_w; ++dst_x, ++dptr)
00124 {
00125
00126 const bool x_clean = dst_x >= Nx2 && dst_x < (src_w - Nx2);
00127
00128
00129
00130
00131
00132
00133 if (x_clean && y_clean)
00134 {
00135 double dst_val = 0.0;
00136
00137 Image<double>::const_iterator fptr = filter+fil_end;
00138
00139 Image<double>::const_iterator srow_ptr =
00140 sptr + src_w*(dst_y-Nx2) + dst_x - Nx2;
00141
00142 for (int f_y = 0; f_y < fil_h; ++f_y)
00143 {
00144 for (int f_x = 0; f_x < fil_w; ++f_x)
00145 dst_val += (*srow_ptr++) * (*fptr--);
00146
00147 srow_ptr += srow_skip;
00148 }
00149 *dptr = dst_val;
00150 continue;
00151 }
00152 else
00153 {
00154
00155
00156
00157
00158
00159
00160
00161 double dst_val = 0.0;
00162 double src_sum = 0.0;
00163 int src_cnt = 0;
00164 double fil_sum_skipped = 0.0;
00165
00166 for (int f_y = 0; f_y < fil_h; ++f_y)
00167 {
00168 const int src_y = f_y + dst_y - Ny2;
00169 if (src_y >= 0 && src_y < src_h)
00170 {
00171 for (int f_x = 0; f_x < fil_w; ++f_x)
00172 {
00173 const double fil = filter[fil_end - f_x - fil_w*f_y];
00174
00175 const int src_x = f_x + dst_x - Nx2;
00176 if (src_x >= 0 && src_x < src_w)
00177 {
00178 const double src_val = sptr[src_x + src_w * src_y];
00179 dst_val += src_val * fil;
00180 src_sum += src_val;
00181 ++src_cnt;
00182 }
00183 else
00184 {
00185 fil_sum_skipped += fil;
00186 }
00187 }
00188 }
00189 else
00190 {
00191 for (int f_x = 0; f_x < fil_w; ++f_x)
00192 fil_sum_skipped += filter[fil_end - f_x - fil_w*f_y];
00193 }
00194 }
00195 const double src_avg = src_sum / src_cnt;
00196 *dptr = dst_val + (fil_sum_skipped * src_avg);
00197 }
00198 }
00199 }
00200 return result;
00201 }
00202
00203
00204 static Image<double>
00205 xFilter(const Image<double>& src, const double* hFilt, const int hfs,
00206 ConvolutionBoundaryStrategy boundary)
00207 {
00208 const int w = src.getWidth(), h = src.getHeight();
00209
00210 if (hfs == 0) return src;
00211 Image<double> result(w, h, NO_INIT);
00212 Image<double>::const_iterator sptr = src.begin();
00213 Image<double>::iterator dptr = result.beginw();
00214
00215 const int hfs2 = (hfs - 1) / 2;
00216
00217
00218 double *hFilter = new double[hfs]; double sumh = 0.0;
00219 for (int x = 0; x < hfs; x ++)
00220 { sumh += hFilt[x]; hFilter[hfs-1-x] = hFilt[x]; }
00221
00222
00223 if (w < hfs)
00224 {
00225 switch (boundary)
00226 {
00227 case CONV_BOUNDARY_ZERO:
00228 {
00229 for (int j = 0; j < h; j ++)
00230 for (int i = 0; i < w; i ++)
00231 {
00232 double val = 0;
00233 for (int k = 0; k < hfs; k ++)
00234 if (i + k - hfs2 >= 0 && i + k - hfs2 < w)
00235 {
00236 val += sptr[k - hfs2] * hFilter[k];
00237 }
00238 *dptr++ = val; sptr ++;
00239 }
00240 }
00241 break;
00242 case CONV_BOUNDARY_CLEAN:
00243 {
00244 for (int j = 0; j < h; j ++)
00245 for (int i = 0; i < w; i ++)
00246 {
00247 double val = 0.0; double sum = 0.0;
00248 for (int k = 0; k < hfs; k ++)
00249 if (i + k - hfs2 >= 0 && i + k - hfs2 < w)
00250 {
00251 val += sptr[k - hfs2] * hFilter[k];
00252 sum += hFilter[k];
00253 }
00254 *dptr++ = val * sumh / sum; sptr ++;
00255 }
00256 }
00257 break;
00258 case CONV_BOUNDARY_REPLICATE:
00259 {
00260 for (int j = 0; j < h; j ++)
00261 for (int i = 0; i < w; i ++)
00262 {
00263 double val = 0.0;
00264 for (int k = 0; k < hfs; k ++)
00265 if (i + k - hfs2 < 0)
00266 {
00267 val += sptr[-i] * hFilter[k];
00268 }
00269 else if (i + k - hfs2 >= w)
00270 {
00271 val += sptr[w-1-i] * hFilter[k];
00272 }
00273 else
00274 {
00275 val += sptr[k - hfs2] * hFilter[k];
00276 }
00277 *dptr++ = val; sptr ++;
00278 }
00279 }
00280 break;
00281 default:
00282 LFATAL("invalid convolution boundary strategy %d",
00283 (int) boundary);
00284 }
00285 }
00286 else
00287 for (int jj = 0; jj < h; jj ++)
00288 {
00289
00290 switch (boundary)
00291 {
00292 case CONV_BOUNDARY_ZERO:
00293 {
00294 for (int j = hfs2; j > 0; --j)
00295 {
00296 double val = 0.0;
00297 for (int k = j; k < hfs; ++k)
00298 {
00299 val += sptr[k - j] * hFilter[k];
00300 }
00301 *dptr++ = val;
00302 }
00303 }
00304 break;
00305 case CONV_BOUNDARY_CLEAN:
00306 {
00307 for (int j = hfs2; j > 0; --j)
00308 {
00309 double val = 0.0; double sum = 0.0;
00310 for (int k = j; k < hfs; ++k)
00311 {
00312 val += sptr[k - j] * hFilter[k];
00313 sum += hFilter[k];
00314 }
00315 *dptr++ = val * sumh / sum;
00316 }
00317 }
00318 break;
00319 case CONV_BOUNDARY_REPLICATE:
00320 {
00321 for (int j = hfs2; j > 0; --j)
00322 {
00323 double val = 0.0;
00324 for (int k = 0; k < j; ++k)
00325 {
00326 val += sptr[0] * hFilter[k];
00327 }
00328 for (int k = j; k < hfs; ++k)
00329 {
00330 val += sptr[k - j] * hFilter[k];
00331 }
00332 *dptr++ = val;
00333 }
00334 }
00335 break;
00336 default:
00337 LFATAL("invalid convolution boundary strategy %d",
00338 (int) boundary);
00339 }
00340
00341 for (int i = 0; i < w - hfs + 1; i ++)
00342 {
00343 double val = 0.0;
00344 for (int k = 0; k < hfs; k ++) val += sptr[k] * hFilter[k];
00345 *dptr++ = val; sptr++;
00346 }
00347
00348 switch (boundary)
00349 {
00350 case CONV_BOUNDARY_ZERO:
00351 {
00352 for (int j = hfs - 1; j > hfs2; --j)
00353 {
00354 double val = 0.0;
00355 for (int k = 0; k < j; ++k)
00356 {
00357 val += sptr[k] * hFilter[k];
00358 }
00359 *dptr++ = val;
00360 sptr++;
00361 }
00362 }
00363 break;
00364 case CONV_BOUNDARY_CLEAN:
00365 {
00366 for (int j = hfs - 1; j > hfs2; --j)
00367 {
00368 double val = 0.0; double sum = 0.0;
00369 for (int k = 0; k < j; ++k)
00370 {
00371 val += sptr[k] * hFilter[k];
00372 sum += hFilter[k];
00373 }
00374 *dptr++ = val * sumh / sum;
00375 sptr++;
00376 }
00377 }
00378 break;
00379 case CONV_BOUNDARY_REPLICATE:
00380 {
00381 for (int j = hfs - 1; j > hfs2; --j)
00382 {
00383 double val = 0.0;
00384 for (int k = 0; k < j; ++k)
00385 {
00386 val += sptr[k] * hFilter[k];
00387 }
00388 for (int k = j; k < hfs; ++k)
00389 {
00390 val += sptr[j-1] * hFilter[k];
00391 }
00392 *dptr++ = val;
00393 sptr++;
00394 }
00395 }
00396 break;
00397 default:
00398 LFATAL("invalid convolution boundary strategy %d",
00399 (int) boundary);
00400 }
00401 sptr += hfs2;
00402 }
00403 delete [] hFilter;
00404 return result;
00405 }
00406
00407
00408 static Image<double>
00409 yFilter(const Image<double>& src, const double* vFilt, const int vfs,
00410 ConvolutionBoundaryStrategy boundary)
00411 {
00412 const int w = src.getWidth(), h = src.getHeight();
00413
00414 if (vfs == 0) return src;
00415 Image<double> result(w, h, NO_INIT);
00416 Image<double>::const_iterator sptr = src.begin();
00417 Image<double>::iterator dptr = result.beginw();
00418
00419 const int vfs2 = (vfs - 1) / 2;
00420
00421
00422 double *vFilter = new double[vfs]; double sumv = 0.0;
00423 for (int x = 0; x < vfs; x ++)
00424 { sumv += vFilt[x]; vFilter[vfs-1-x] = vFilt[x]; }
00425
00426 int ww[vfs];
00427 for (int i = 0; i < vfs; i ++) ww[i] = w * i;
00428
00429 if (h < vfs)
00430 {
00431 switch (boundary)
00432 {
00433 case CONV_BOUNDARY_ZERO:
00434 {
00435 for (int j = 0; j < h; j ++)
00436 for (int i = 0; i < w; i ++)
00437 {
00438 double val = 0.0;
00439 for (int k = 0; k < vfs; k ++)
00440 if (j + k - vfs2 >= 0 && j + k - vfs2 < h)
00441 {
00442 val += sptr[w * (k - vfs2)] * vFilter[k];
00443 }
00444 *dptr++ = val; sptr ++;
00445 }
00446 }
00447 break;
00448 case CONV_BOUNDARY_CLEAN:
00449 {
00450 for (int j = 0; j < h; j ++)
00451 for (int i = 0; i < w; i ++)
00452 {
00453 double val = 0.0; double sum = 0.0;
00454 for (int k = 0; k < vfs; k ++)
00455 if (j + k - vfs2 >= 0 && j + k - vfs2 < h)
00456 {
00457 val += sptr[w * (k - vfs2)] * vFilter[k];
00458 sum += vFilter[k];
00459 }
00460 *dptr++ = val * sumv / sum; sptr ++;
00461 }
00462 }
00463 break;
00464 case CONV_BOUNDARY_REPLICATE:
00465 {
00466 for (int j = 0; j < h; j ++)
00467 for (int i = 0; i < w; i ++)
00468 {
00469 double val = 0.0;
00470 for (int k = 0; k < vfs; k ++)
00471 if (j + k - vfs2 < 0)
00472 {
00473 val += sptr[w * (-j)] * vFilter[k];
00474 }
00475 else if (j + k - vfs2 >= h)
00476 {
00477 val += sptr[w * (h-1-j)] * vFilter[k];
00478 }
00479 else
00480 {
00481 val += sptr[w * (k - vfs2)] * vFilter[k];
00482 }
00483 *dptr++ = val; sptr ++;
00484 }
00485 }
00486 break;
00487 default:
00488 LFATAL("invalid convolution boundary strategy %d",
00489 (int) boundary);
00490 }
00491 }
00492 else
00493 {
00494
00495 switch (boundary)
00496 {
00497 case CONV_BOUNDARY_ZERO:
00498 {
00499 for (int j = vfs2; j > 0; --j)
00500 {
00501 for (int i = 0; i < w; ++i)
00502 {
00503 double val = 0.0;
00504 for (int k = j; k < vfs; ++k)
00505 {
00506 val += sptr[ww[k - j]] * vFilter[k];
00507 }
00508 *dptr++ = val;
00509 sptr++;
00510 }
00511 sptr -= w;
00512 }
00513 }
00514 break;
00515 case CONV_BOUNDARY_CLEAN:
00516 {
00517 for (int j = vfs2; j > 0; --j)
00518 {
00519 for (int i = 0; i < w; ++i)
00520 {
00521 double val = 0.0; double sum = 0.0;
00522 for (int k = j; k < vfs; ++k)
00523 {
00524 val += sptr[ww[k - j]] * vFilter[k];
00525 sum += vFilter[k];
00526 }
00527 *dptr++ = val * sumv / sum;
00528 sptr++;
00529 }
00530 sptr -= w;
00531 }
00532 }
00533 break;
00534 case CONV_BOUNDARY_REPLICATE:
00535 {
00536 for (int j = vfs2; j > 0; --j)
00537 {
00538 for (int i = 0; i < w; ++i)
00539 {
00540 double val = 0.0;
00541 for (int k = 0; k < j; ++k)
00542 {
00543 val += sptr[ww[0]] * vFilter[k];
00544 }
00545 for (int k = j; k < vfs; ++k)
00546 {
00547 val += sptr[ww[k - j]] * vFilter[k];
00548 }
00549 *dptr++ = val;
00550 sptr++;
00551 }
00552 sptr -= w;
00553 }
00554 }
00555 break;
00556 default:
00557 LFATAL("invalid convolution boundary strategy %d",
00558 (int) boundary);
00559 }
00560
00561 for (int j = 0; j < h - vfs + 1; j ++)
00562 for (int i = 0; i < w; i ++)
00563 {
00564 double val = 0.0;
00565 for (int k = 0; k < vfs; k ++) val += sptr[ww[k]] * vFilter[k];
00566 *dptr++ = val; sptr ++;
00567 }
00568
00569 switch (boundary)
00570 {
00571 case CONV_BOUNDARY_ZERO:
00572 {
00573 for (int j = vfs - 1; j > vfs2; --j)
00574 for (int i = 0; i < w; ++i)
00575 {
00576 double val = 0.0;
00577 for (int k = 0; k < j; ++k)
00578 {
00579 val += sptr[ww[k]] * vFilter[k];
00580 }
00581 *dptr++ = val;
00582 sptr ++;
00583 }
00584 }
00585 break;
00586 case CONV_BOUNDARY_CLEAN:
00587 {
00588 for (int j = vfs - 1; j > vfs2; --j)
00589 for (int i = 0; i < w; ++i)
00590 {
00591 double val = 0.0; double sum = 0.0;
00592 for (int k = 0; k < j; ++k)
00593 {
00594 val += sptr[ww[k]] * vFilter[k];
00595 sum += vFilter[k];
00596 }
00597 *dptr++ = val * sumv / sum;
00598 sptr ++;
00599 }
00600 }
00601 break;
00602 case CONV_BOUNDARY_REPLICATE:
00603 {
00604 for (int j = vfs - 1; j > vfs2; --j)
00605 for (int i = 0; i < w; ++i)
00606 {
00607 double val = 0.0;
00608 for (int k = 0; k < j; ++k)
00609 {
00610 val += sptr[ww[k]] * vFilter[k];
00611 }
00612 for (int k = j; k < vfs; ++k)
00613 {
00614 val += sptr[ww[j-1]] * vFilter[k];
00615 }
00616 *dptr++ = val;
00617 sptr ++;
00618 }
00619 }
00620 break;
00621 default:
00622 LFATAL("invalid convolution boundary strategy %d",
00623 (int) boundary);
00624 }
00625 }
00626 delete [] vFilter;
00627 return result;
00628 }
00629
00630
00631 Image<double>
00632 sepFilter(const Image<double>& src, const Image<double>& hFilter,
00633 const Image<double>& vFilter,
00634 ConvolutionBoundaryStrategy boundary)
00635 {
00636 ASSERT(hFilter.is1D() || hFilter.getSize() == 0);
00637 ASSERT(vFilter.is1D() || vFilter.getSize() == 0);
00638
00639 Image<double> result = src;
00640 const int hfs = hFilter.getSize();
00641 const int vfs = vFilter.getSize();
00642 if (hfs > 0) result = xFilter(result, hFilter.getArrayPtr(),
00643 hfs, boundary);
00644 if (vfs > 0) result = yFilter(result, vFilter.getArrayPtr(),
00645 vfs, boundary);
00646
00647 return result;
00648 }
00649 }
00650
00651
00652
00653
00654 WeightsAll::WeightsAll() : WeightsDerived<WeightsAll>(), itsW(0.0) { };
00655
00656
00657 WeightsAll::WeightsAll(const double& weight) : WeightsDerived<WeightsAll>(),
00658 itsW(weight) { itsInit = true; }
00659
00660
00661 Image<double> WeightsAll::compute(const Image<double>& in)
00662 {
00663 double s = sum(in);
00664 s *= itsW;
00665 Image<double> out(in.getDims(), NO_INIT);
00666 out.clear(s);
00667 return out;
00668 }
00669
00670
00671
00672
00673 WeightsUniform::WeightsUniform() : WeightsDerived<WeightsUniform>(), itsW(0.0) { };
00674
00675
00676 WeightsUniform::WeightsUniform(const double& weight) : WeightsDerived<WeightsUniform>(), itsW(weight)
00677 { itsInit = true; }
00678
00679
00680 Image<double> WeightsUniform::compute(const Image<double>& in)
00681 {
00682 Image<double> out = in * itsW;
00683 return out;
00684 }
00685
00686
00687
00688
00689 WeightsBinomial::WeightsBinomial() : WeightsDerived<WeightsBinomial>(),
00690 itsTaps(0), itsIter(0), subCenter(false),
00691 itsCenter(0.0), itsWeight(0.0),
00692 itsBp(NONE), itsSetup(false) { };
00693
00694
00695 WeightsBinomial::WeightsBinomial(const double& std, const double& weight,
00696 const bool doSubCenter, const BorderPolicy bp,
00697 const uint taps) :
00698 itsTaps(taps), itsIter(0), subCenter(doSubCenter), itsCenter(0.0),
00699 itsWeight(weight), itsBp(bp), itsSetup(false)
00700 {
00701
00702 itsIter = uint((std*std) / (double(taps - 1)/4.0));
00703 itsInit = true;
00704 }
00705
00706
00707 Image<double> WeightsBinomial::compute(const Image<double>& in)
00708 {
00709 Image<double> out = in;
00710 if (!itsSetup)
00711 {
00712 Image<double> impulse(in.getDims(), ZEROS);
00713 uint cx = (uint) (in.getWidth() / 2) - 1;
00714 uint cy = (uint) (in.getHeight() / 2) - 1;
00715 impulse.setVal(cx, cy, 1.0);
00716 impulse = filterBinomial(impulse,itsIter, itsTaps, itsBp);
00717 itsCenter = 1.0 / impulse.getVal(cx,cy);
00718 if (!subCenter)
00719 itsCenter*= itsWeight;
00720
00721 itsSetup = true;
00722 }
00723
00724
00725 out = filterBinomial(out, itsIter, itsTaps, itsBp);
00726
00727
00728 if (subCenter)
00729 {
00730 out *= itsCenter;
00731 out -= in;
00732 out *= itsWeight;
00733 }
00734 else
00735 out *= itsCenter;
00736
00737 return out;
00738 }
00739
00740
00741
00742
00743 WeightsCS::WeightsCS() : WeightsDerived<WeightsCS>(), itsW(0.0, 0.0, false, NONE, 0),
00744 itsInh(0.0) { };
00745
00746
00747 WeightsCS::WeightsCS(const double& estd, const double& eweight,
00748 const double& inhibit, const bool doSubCenter,
00749 const BorderPolicy bp, const uint taps) :
00750 WeightsDerived<WeightsCS>(), itsW(estd, eweight, doSubCenter, bp, taps), itsInh(inhibit)
00751 { itsInit = true; }
00752
00753
00754 Image<double> WeightsCS::compute(const Image<double>& in)
00755 {
00756 Image<double> e = itsW.compute(in);
00757 const double s = sum(in) * itsInh;
00758 e -= s;
00759 return e;
00760 }
00761
00762
00763
00764
00765 WeightsDoG::WeightsDoG() : WeightsDerived<WeightsDoG>(), itsE(0.0, 0.0, false, NONE, 0),
00766 itsI(0.0, 0.0, false, NONE, 0) { };
00767
00768
00769 WeightsDoG::WeightsDoG(const double& estd, const double& istd,
00770 const double& ew, const double& iw,
00771 const bool subCenter, const BorderPolicy bp,
00772 const uint taps) : WeightsDerived<WeightsDoG>(),
00773 itsE(estd, ew, subCenter, bp, taps),
00774 itsI(istd, iw, subCenter, bp, taps)
00775 {
00776 itsInit = true;
00777 }
00778
00779
00780 Image<double> WeightsDoG::compute(const Image<double>& in)
00781 {
00782 Image<double> e = itsE.compute(in);
00783 const Image<double> i = itsI.compute(in);
00784 e -= i;
00785 return e;
00786 }
00787
00788
00789
00790
00791 Weights1D::Weights1D() : WeightsDerived<Weights1D>(), subCenter(false), itsCenter(0.0),
00792 itsStrat(CONV_BOUNDARY_CLEAN), itsX(), itsY(),
00793 itsSetup(false) { }
00794
00795
00796 Weights1D::Weights1D(const bool doSubCenter,
00797 const ConvolutionBoundaryStrategy strat) :
00798 WeightsDerived<Weights1D>(),
00799 subCenter(doSubCenter), itsCenter(0.0), itsStrat(strat),
00800 itsX(), itsY(), itsSetup(false) { }
00801
00802
00803 void Weights1D::addWeight(const Image<double>& wxy)
00804 {
00805 itsX.push_back(wxy);
00806 itsY.push_back(wxy);
00807 itsInit = true;
00808 }
00809
00810
00811 void Weights1D::addWeight(const Image<double>& wx, const Image<double>& wy)
00812 {
00813 itsX.push_back(wx);
00814 itsY.push_back(wy);
00815 itsInit = true;
00816 }
00817
00818
00819 void Weights1D::clear()
00820 {
00821 itsX.clear();
00822 itsY.clear();
00823 itsCenter = 0.0;
00824 itsSetup = false;
00825 }
00826
00827
00828 Image<double> Weights1D::compute(const Image<double>& in)
00829 {
00830
00831 if (~itsSetup && subCenter)
00832 {
00833 Image<double> impulse(in.getDims(), ZEROS);
00834 uint cx = (uint) (in.getWidth() / 2) - 1;
00835 uint cy = (uint) (in.getHeight() / 2) - 1;
00836 impulse.setVal(cx, cy, 1.0);
00837
00838 for (uint jj = 0; jj < itsX.size(); ++jj)
00839 impulse = WeightFilter::sepFilter(impulse,itsX[jj],itsY[jj],itsStrat);
00840 itsCenter = impulse.getVal(cx,cy);
00841 itsSetup = true;
00842 }
00843
00844 Image<double> out = in;
00845
00846 for (uint jj = 0; jj < itsX.size(); ++jj)
00847 out = WeightFilter::sepFilter(out, itsX[jj], itsY[jj], itsStrat);
00848
00849
00850 if (subCenter)
00851 out = out - (in * itsCenter);
00852
00853 return out;
00854 }
00855
00856
00857
00858
00859 Weights2D::Weights2D(const ConvolutionBoundaryStrategy strat)
00860 : WeightsDerived<Weights2D>(), itsStrat(strat), itsW()
00861 {
00862 }
00863
00864
00865 void Weights2D::addWeight(const Image<double>& w)
00866 {
00867 if (w.is1D())
00868 LFATAL("Filter needs to be 2D for this Weights type");
00869 else
00870 itsW.push_back(w);
00871 itsInit = true;
00872 }
00873
00874
00875 void Weights2D::clear()
00876 {
00877 itsW.clear();
00878 itsInit = false;
00879 }
00880
00881
00882 Image<double> Weights2D::compute(const Image<double>& in)
00883 {
00884 Image<double> out = in;
00885
00886 if (itsStrat == CONV_BOUNDARY_CLEAN)
00887 for (uint jj = 0; jj < itsW.size(); ++jj)
00888 out = WeightFilter::convolveHmax(out, itsW[jj]);
00889 else
00890 for (uint jj = 0; jj < itsW.size(); ++jj)
00891 out = WeightFilter::optConvolve(out, itsW[jj]);
00892
00893 return out;
00894 }
00895
00896
00897
00898
00899 WeightsMask::WeightsMask() : WeightsDerived<WeightsMask>()
00900 {
00901 }
00902
00903
00904 void WeightsMask::addWeight(const Image<double>& w)
00905 {
00906 itsW.push_back(w);
00907 itsInit = true;
00908 }
00909
00910
00911 void WeightsMask::clear()
00912 {
00913 itsW.clear();
00914 itsInit = false;
00915 }
00916
00917
00918 Image<double> WeightsMask::compute(const Image<double>& in)
00919 {
00920 ASSERT((itsW.size() == in.size()) && in.size() > 0);
00921
00922 Image<double> out(in.getDims(), ZEROS);
00923 std::vector<Image<double> >::const_iterator iter(itsW.begin()), end(itsW.end());
00924 Image<double>::iterator outiter(out.beginw());
00925
00926 while (iter != end)
00927 {
00928 ASSERT(iter->size() == in.size());
00929 (*outiter++) = sum(in * (*iter++));
00930 }
00931
00932 return Image<double>(in.getDims(),ZEROS);
00933 }
00934
00935
00936
00937
00938 Image<double> filterBinomial(const Image<double>& in, const uint iter,
00939 const uint taps, const BorderPolicy bp)
00940 {
00941 Image<double> out = in;
00942 if (bp == NONE)
00943 switch(taps)
00944 {
00945 case 3:
00946 for (uint i = 0; i < iter; ++i)
00947 out = lowPass3(out);
00948 break;
00949 case 5:
00950 for (uint i = 0; i < iter; ++i)
00951 out = lowPass5(out);
00952 break;
00953 default:
00954 {
00955 Image<double> k = binomialKernel(taps);
00956 for (uint i = 0; i < iter; ++i)
00957 out = WeightFilter::sepFilter(out, k, k, CONV_BOUNDARY_CLEAN);
00958 }
00959 }
00960 else
00961 for (uint i = 0; i < iter; ++i)
00962 out = lowPassLpt(out, taps, bp);
00963
00964 return out;
00965 }
00966
00967
00968 template <class W>
00969 void printImpulse(const uint w, const uint h, W& weights)
00970 {
00971 Image<double> in(w,h,ZEROS);
00972 int cx = in.getWidth() / 2 -1;
00973 int cy = in.getHeight() / 2 -1;
00974 in.setVal(cx,cy,1.0);
00975 in = weights.compute(in);
00976 printImage(in);
00977 }
00978
00979
00980 void printImage(const Image<double>& in)
00981 {
00982 int cx = in.getWidth() / 2 - 1;
00983
00984 Image<double>::const_iterator iter(in.begin() + cx);
00985 for (int i = 0; i < in.getHeight(); ++i)
00986 {
00987 LINFO("%3.5f", *iter);
00988 iter += in.getWidth();
00989 }
00990 }
00991
00992 template
00993 void printImpulse(const uint w, const uint h, WeightsUniform& weights);
00994 template
00995 void printImpulse(const uint w, const uint h, WeightsBinomial& weights);
00996 template
00997 void printImpulse(const uint w, const uint h, WeightsCS& weights);
00998 template
00999 void printImpulse(const uint w, const uint h, WeightsDoG& weights);
01000 template
01001 void printImpulse(const uint w, const uint h, Weights1D& weights);
01002 template
01003 void printImpulse(const uint w, const uint h, Weights2D& weights);
01004 template
01005 void printImpulse(const uint w, const uint h, WeightsMask& weights);
01006
01007
01008
01009
01010