00001
00002 #ifndef vil_math_h_
00003 #define vil_math_h_
00004
00005
00006
00007
00008
00009 #include <vcl_cassert.h>
00010 #include <vcl_vector.h>
00011 #include <vcl_cmath.h>
00012 #include <vcl_algorithm.h>
00013 #include <vil/vil_image_view.h>
00014 #include <vil/vil_view_as.h>
00015 #include <vil/vil_plane.h>
00016 #include <vil/vil_transform.h>
00017
00018
00019
00020 template<class T>
00021 inline void vil_math_value_range(const vil_image_view<T>& view, T& min_value, T& max_value)
00022 {
00023 if (view.size()==0)
00024 {
00025 min_value = 0;
00026 max_value = 0;
00027 return;
00028 }
00029
00030 min_value = *(view.top_left_ptr());
00031 max_value = min_value;
00032
00033 unsigned ni = view.ni();
00034 unsigned nj = view.nj();
00035 unsigned np = view.nplanes();
00036
00037 for (unsigned p=0;p<np;++p)
00038 for (unsigned j=0;j<nj;++j)
00039 for (unsigned i=0;i<ni;++i)
00040 {
00041 const T pixel = view(i,j,p);
00042 if (pixel<min_value)
00043 min_value=pixel;
00044 else if (pixel>max_value)
00045 max_value=pixel;
00046 }
00047 }
00048
00049
00050 VCL_DEFINE_SPECIALIZATION
00051 inline void vil_math_value_range(const vil_image_view<vil_rgb<vxl_byte> >& rgb_view,
00052 vil_rgb<vxl_byte>& min_value, vil_rgb<vxl_byte>& max_value)
00053 {
00054 vil_image_view<vxl_byte> plane_view = vil_view_as_planes(rgb_view);
00055
00056 vil_math_value_range(vil_plane(plane_view,0),min_value.r,max_value.r);
00057 vil_math_value_range(vil_plane(plane_view,1),min_value.g,max_value.g);
00058 vil_math_value_range(vil_plane(plane_view,2),min_value.b,max_value.b);
00059 }
00060
00061
00062 VCL_DEFINE_SPECIALIZATION
00063 inline void vil_math_value_range(const vil_image_view<vil_rgb<float> >& rgb_view,
00064 vil_rgb<float>& min_value, vil_rgb<float>& max_value)
00065 {
00066 vil_image_view<float> plane_view = vil_view_as_planes(rgb_view);
00067
00068 vil_math_value_range(vil_plane(plane_view,0),min_value.r,max_value.r);
00069 vil_math_value_range(vil_plane(plane_view,1),min_value.g,max_value.g);
00070 vil_math_value_range(vil_plane(plane_view,2),min_value.b,max_value.b);
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 template <class T>
00083 inline void vil_math_value_range_percentiles(const vil_image_view<T>& im,
00084 const vcl_vector<double>& fraction,
00085 vcl_vector<T>& value)
00086 {
00087 value.clear();
00088
00089
00090 if (im.size()==0)
00091 {
00092 return;
00093 }
00094 const unsigned nfrac = fraction.size();
00095 for (unsigned f=0; f<nfrac; ++f)
00096 {
00097 if (fraction[f]<0.0 || fraction[f]>1.0)
00098 return;
00099 }
00100
00101
00102 unsigned ni = im.ni();
00103 unsigned nj = im.nj();
00104 unsigned np = im.nplanes();
00105 vcl_ptrdiff_t istep = im.istep();
00106 vcl_ptrdiff_t jstep = im.jstep();
00107 vcl_ptrdiff_t pstep = im.planestep();
00108 vcl_vector<T> data(ni*nj*np);
00109
00110 typename vcl_vector<T>::iterator it = data.begin();
00111 const T* plane = im.top_left_ptr();
00112 for (unsigned int p=0; p<np; ++p, plane+=pstep)
00113 {
00114 const T* row = plane;
00115 for (unsigned int j=0; j<nj; ++j, row+=jstep)
00116 {
00117 const T* pixel = row;
00118 for (unsigned int i=0; i<ni; ++i, pixel+=istep)
00119 {
00120 *it = *pixel;
00121 it++;
00122 }
00123 }
00124 }
00125 const unsigned npix = data.size();
00126
00127
00128 value.resize(nfrac);
00129 for (unsigned f=0; f<nfrac; ++f)
00130 {
00131 unsigned index = static_cast<unsigned>(fraction[f]*npix - 0.5);
00132 typename vcl_vector<T>::iterator index_it = data.begin() + index;
00133 vcl_nth_element(data.begin(), index_it, data.end());
00134 value[f] = *index_it;
00135 }
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 template <class T>
00148 inline void vil_math_value_range_percentile(const vil_image_view<T>& im,
00149 const double fraction,
00150 T& value)
00151 {
00152 vcl_vector<double> fractions(1, fraction);
00153 vcl_vector<T> values;
00154 vil_math_value_range_percentiles(im, fractions, values);
00155 if (values.size() > 0)
00156 value = values[0];
00157 }
00158
00159
00160
00161
00162 template <class imT, class sumT>
00163 inline sumT vil_math_ssd(const vil_image_view<imT>& imA, const vil_image_view<imT>& imB, sumT )
00164 {
00165 assert(imA.ni() == imB.ni() && imB.nj() == imB.nj() && imA.nplanes() == imB.nplanes());
00166 sumT ssd=0;
00167 for (unsigned p=0;p<imA.nplanes();++p)
00168 for (unsigned j=0;j<imA.nj();++j)
00169 for (unsigned i=0;i<imA.ni();++i)
00170 {
00171 const sumT v = ((sumT)imA(i,j,p) - (sumT)imB(i,j,p));
00172 ssd += v*v;
00173 }
00174 return ssd;
00175 }
00176
00177
00178
00179 template <class imT, class sumT>
00180 inline sumT
00181 vil_math_ssd_complex(const vil_image_view<vcl_complex<imT> >& imA,
00182 const vil_image_view<vcl_complex<imT> >& imB,
00183 sumT )
00184 {
00185 assert(imA.ni() == imB.ni() && imB.nj() == imB.nj() && imA.nplanes() == imB.nplanes());
00186 sumT ssd=0;
00187 for (unsigned p=0;p<imA.nplanes();++p)
00188 for (unsigned j=0;j<imA.nj();++j)
00189 for (unsigned i=0;i<imA.ni();++i)
00190 {
00191 const vcl_complex<imT> d = imA(i,j,p) - imB(i,j,p);
00192 ssd += sumT( d.real()*d.real() + d.imag()*d.imag() );
00193 }
00194 return ssd;
00195 }
00196
00197
00198
00199 template<class aT, class sumT>
00200 inline void vil_math_mean_over_planes(const vil_image_view<aT>& src,
00201 vil_image_view<sumT>& dest)
00202 {
00203 if (src.nplanes()==1 && src.is_a()==dest.is_a())
00204 {
00205 dest.deep_copy(src);
00206 return;
00207 }
00208 dest.set_size(src.ni(), src.nj(), 1);
00209 for (unsigned j=0;j<src.nj();++j)
00210 for (unsigned i=0;i<src.ni();++i)
00211 {
00212 sumT sum=0;
00213 for (unsigned p=0;p<src.nplanes();++p)
00214 sum += (sumT) src(i,j,p);
00215 dest(i,j) = sum / src.nplanes();
00216 }
00217 }
00218
00219
00220
00221 template<class inT, class outT, class sumT>
00222 inline void vil_math_mean_over_planes(const vil_image_view<inT>& src,
00223 vil_image_view<outT>& dest,
00224 sumT )
00225 {
00226 dest.set_size(src.ni(), src.nj(), 1);
00227 for (unsigned j=0;j<src.nj();++j)
00228 for (unsigned i=0;i<src.ni();++i)
00229 {
00230 sumT sum=0;
00231 for (unsigned p=0;p<src.nplanes();++p)
00232 sum += static_cast<sumT>(src(i,j,p));
00233 dest(i,j) = static_cast<outT>(sum / src.nplanes());
00234 }
00235 }
00236
00237
00238
00239 template<class imT, class sumT>
00240 inline void vil_math_sum(sumT& sum, const vil_image_view<imT>& im, unsigned p)
00241 {
00242 const imT* row = im.top_left_ptr()+p*im.planestep();
00243 vcl_ptrdiff_t istep = im.istep(),jstep=im.jstep();
00244 const imT* row_end = row + im.nj()*jstep;
00245 vcl_ptrdiff_t row_len = im.ni()*im.istep();
00246 sum = 0;
00247 for (;row!=row_end;row+=jstep)
00248 {
00249 const imT* v_end = row + row_len;
00250 for (const imT* v = row;v!=v_end;v+=istep) sum+=*v;
00251 }
00252 }
00253
00254
00255
00256 template<class imT, class sumT>
00257 inline void vil_math_mean(sumT& mean, const vil_image_view<imT>& im, unsigned p)
00258 {
00259 if (im.size()==0) { mean=0; return; }
00260 vil_math_sum(mean,im,p);
00261 mean/=(im.ni()*im.nj());
00262 }
00263
00264
00265
00266 void vil_math_median_unimplemented();
00267
00268
00269
00270
00271
00272
00273
00274 template<class imT>
00275 inline void vil_math_median(imT& median, const vil_image_view<imT>& im, unsigned p)
00276 {
00277 vil_math_median_unimplemented();
00278 }
00279
00280
00281
00282
00283 VCL_DEFINE_SPECIALIZATION
00284 void vil_math_median(vxl_byte& median, const vil_image_view<vxl_byte>& im, unsigned p);
00285
00286
00287
00288
00289 template<class imT, class sumT>
00290 inline void vil_math_sum_squares(sumT& sum, sumT& sum_sq, const vil_image_view<imT>& im, unsigned p)
00291 {
00292 const imT* row = im.top_left_ptr()+p*im.planestep();
00293 vcl_ptrdiff_t istep = im.istep(),jstep=im.jstep();
00294 const imT* row_end = row + im.nj()*jstep;
00295 vcl_ptrdiff_t row_len = im.ni()*im.istep();
00296 sum = 0; sum_sq = 0;
00297 for (;row!=row_end;row+=jstep)
00298 {
00299 const imT* v_end = row + row_len;
00300 for (const imT* v = row;v!=v_end;v+=istep) { sum+=*v; sum_sq+=sumT(*v)*sumT(*v); }
00301 }
00302 }
00303
00304
00305
00306 template<class imT, class sumT>
00307 inline void vil_math_mean_and_variance(sumT& mean, sumT& var, const vil_image_view<imT>& im, unsigned p)
00308 {
00309 if (im.size()==0) { mean=0; var=0; return; }
00310 sumT sum,sum_sq;
00311 vil_math_sum_squares(sum,sum_sq,im,p);
00312 mean = sum/(im.ni()*im.nj());
00313 var = sum_sq/(im.ni()*im.nj()) - mean*mean;
00314 }
00315
00316
00317 class vil_math_sqrt_functor
00318 {
00319 public:
00320 vxl_byte operator()(vxl_byte x) const { return static_cast<vxl_byte>(0.5+vcl_sqrt(double(x))); }
00321 unsigned operator()(unsigned x) const { return static_cast<unsigned int>(0.5+vcl_sqrt(double(x))); }
00322 int operator()(int x) const { return x>0?static_cast<int>(0.5+vcl_sqrt(double(x))):0; }
00323 short operator()(short x) const { return x>0?static_cast<short>(0.5+vcl_sqrt(double(x))):0; }
00324 float operator()(float x) const { return x>0?vcl_sqrt(x):0.0f; }
00325 double operator()(double x) const { return x>0?vcl_sqrt(x):0.0; }
00326 };
00327
00328
00329
00330 template<class T>
00331 inline void vil_math_sqrt(vil_image_view<T>& image)
00332 {
00333 vil_transform(image,vil_math_sqrt_functor());
00334 }
00335
00336
00337
00338
00339
00340
00341 template<class T>
00342 inline void vil_math_truncate_range(vil_image_view<T>& image, T min_v, T max_v)
00343 {
00344 unsigned ni = image.ni(),nj = image.nj(),np = image.nplanes();
00345 vcl_ptrdiff_t istep=image.istep(),jstep=image.jstep(),pstep = image.planestep();
00346 T* plane = image.top_left_ptr();
00347 for (unsigned p=0;p<np;++p,plane += pstep)
00348 {
00349 T* row = plane;
00350 for (unsigned j=0;j<nj;++j,row += jstep)
00351 {
00352 T* pixel = row;
00353 for (unsigned i=0;i<ni;++i,pixel+=istep)
00354 {
00355 if (*pixel<min_v) *pixel=min_v;
00356 else if (*pixel>max_v) *pixel=max_v;
00357 }
00358 }
00359 }
00360 }
00361
00362
00363 class vil_math_scale_functor
00364 {
00365 private:
00366 double s_;
00367 public:
00368 vil_math_scale_functor(double s) : s_(s) {}
00369 vxl_byte operator()(vxl_byte x) const { return vxl_byte(0.5+s_*x); }
00370 unsigned operator()(unsigned x) const { return unsigned(0.5+s_*x); }
00371 short operator()(short x) const { double r=s_*x; return short(r<0?r-0.5:r+0.5); }
00372 int operator()(int x) const { double r=s_*x; return int(r<0?r-0.5:r+0.5); }
00373 float operator()(float x) const { return float(s_*x); }
00374 double operator()(double x) const { return s_*x; }
00375 vcl_complex<double> operator()(vcl_complex<double> x) const { return s_*x; }
00376 };
00377
00378
00379
00380
00381
00382 class vil_math_scale_and_translate_functor
00383 {
00384 public:
00385
00386
00387
00388 vil_math_scale_and_translate_functor(const double s, const double t)
00389 : s_(s), t_(t) {}
00390
00391 vxl_byte operator()(vxl_byte x) const { return vxl_byte(0.5+s_*x+t_); }
00392 unsigned operator()(unsigned x) const { return unsigned(0.5+s_*x+t_); }
00393 short operator()(short x) const { double r=s_*x+t_; return short(r<0?r-0.5:r+0.5); }
00394 int operator()(int x) const { double r=s_*x+t_; return int(r<0?r-0.5:r+0.5); }
00395 float operator()(float x) const { return float(s_*x+t_); }
00396 double operator()(double x) const { return s_*x+t_; }
00397 vcl_complex<double> operator()(vcl_complex<double> x) const { return s_*x+t_; }
00398
00399 private:
00400 double s_;
00401 double t_;
00402 };
00403
00404
00405
00406 class vil_math_log_functor
00407 {
00408 public:
00409 vxl_byte operator()(vxl_byte x) const { return static_cast<vxl_byte>(0.5+vcl_log(double(x))); }
00410 unsigned operator()(unsigned x) const { return static_cast<unsigned int>(0.5+vcl_log(double(x))); }
00411 int operator()(int x) const { return x>0?static_cast<int>(0.5+vcl_log(double(x))):0; }
00412 short operator()(short x) const { return x>0?static_cast<short>(0.5+vcl_log(double(x))):0; }
00413 float operator()(float x) const { return x>0?vcl_log(x):0.0f; }
00414 double operator()(double x) const { return x>0?vcl_log(x):0.0; }
00415 };
00416
00417
00418
00419
00420 template<class T>
00421 inline void vil_math_scale_values(vil_image_view<T>& image, double scale)
00422 {
00423 vil_transform(image,vil_math_scale_functor(scale));
00424 }
00425
00426
00427
00428 template<class imT, class offsetT>
00429 inline void vil_math_scale_and_offset_values(vil_image_view<imT>& image, double scale, offsetT offset)
00430 {
00431 unsigned ni = image.ni(),nj = image.nj(),np = image.nplanes();
00432 vcl_ptrdiff_t istep=image.istep(),jstep=image.jstep(),pstep = image.planestep();
00433 imT* plane = image.top_left_ptr();
00434 for (unsigned p=0;p<np;++p,plane += pstep)
00435 {
00436 imT* row = plane;
00437 for (unsigned j=0;j<nj;++j,row += jstep)
00438 {
00439 imT* pixel = row;
00440 for (unsigned i=0;i<ni;++i,pixel+=istep) *pixel = imT(scale*(*pixel)+offset);
00441 }
00442 }
00443 }
00444
00445
00446
00447 template<class imT>
00448 inline void vil_math_normalise(vil_image_view<imT>& image)
00449 {
00450 assert(image.nplanes()==1);
00451 double mean,var;
00452 vil_math_mean_and_variance(mean,var,image,0);
00453 double s=0;
00454 if (var>0) s = 1.0/vcl_sqrt(var);
00455 vil_math_scale_and_offset_values(image,s,-s*mean);
00456 }
00457
00458
00459
00460
00461 template<class srcT, class destT>
00462 inline
00463 void vil_math_rms(const vil_image_view<srcT>& src,
00464 vil_image_view<destT>& dest)
00465 {
00466 unsigned ni = src.ni(),nj = src.nj(),np = src.nplanes();
00467 dest.set_size(ni,nj,1);
00468
00469 vcl_ptrdiff_t istepA=src.istep(),jstepA=src.jstep(),pstepA = src.planestep();
00470 vcl_ptrdiff_t istepB=dest.istep(),jstepB=dest.jstep();
00471 const srcT* rowA = src.top_left_ptr();
00472 destT* rowB = dest.top_left_ptr();
00473 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00474 {
00475 const srcT* pixelA = rowA;
00476 const srcT* end_pixelA = rowA+ni*istepA;
00477 destT* pixelB = rowB;
00478
00479 if (np==1)
00480 {
00481 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00482 *pixelB = vcl_fabs(destT(*pixelA));
00483 }
00484 else if (np==2)
00485 {
00486 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00487 {
00488 destT sum2 = destT(*pixelA)*(*pixelA)
00489 + destT(pixelA[pstepA])*(pixelA[pstepA]);
00490 *pixelB = destT(vcl_sqrt(sum2/2));
00491 }
00492 }
00493 else
00494 {
00495 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00496 {
00497 *pixelB = destT(*pixelA)*destT(*pixelA);
00498 const srcT* p=pixelA+pstepA;
00499 const srcT* end_p=pixelA+np*pstepA;
00500 for (;p!=end_p;p+=pstepA) *pixelB += destT(*p)*destT(*p);
00501 *pixelB = destT(vcl_sqrt(*pixelB/np));
00502 }
00503 }
00504 }
00505 }
00506
00507
00508
00509
00510
00511 template<class srcT, class destT>
00512 inline
00513 void vil_math_rss(const vil_image_view<srcT>& src,
00514 vil_image_view<destT>& dest)
00515 {
00516 unsigned ni = src.ni(),nj = src.nj(),np = src.nplanes();
00517 dest.set_size(ni,nj,1);
00518
00519 vcl_ptrdiff_t istepA=src.istep(),jstepA=src.jstep(),pstepA = src.planestep();
00520 vcl_ptrdiff_t istepB=dest.istep(),jstepB=dest.jstep();
00521 const srcT* rowA = src.top_left_ptr();
00522 destT* rowB = dest.top_left_ptr();
00523 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00524 {
00525 const srcT* pixelA = rowA;
00526 const srcT* end_pixelA = rowA+ni*istepA;
00527 destT* pixelB = rowB;
00528
00529 if (np==1)
00530 {
00531 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00532 *pixelB = vcl_fabs(destT(*pixelA));
00533 }
00534 else if (np==2)
00535 {
00536 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00537 {
00538 destT sum2 = destT(*pixelA)*(*pixelA)
00539 + destT(pixelA[pstepA])*(pixelA[pstepA]);
00540 *pixelB = destT(vcl_sqrt(sum2));
00541 }
00542 }
00543 else
00544 {
00545 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00546 {
00547 *pixelB = destT(*pixelA)*destT(*pixelA);
00548 const srcT* p=pixelA+pstepA;
00549 const srcT* end_p=pixelA+np*pstepA;
00550 for (;p!=end_p;p+=pstepA) *pixelB += destT(*p)*destT(*p);
00551 *pixelB = destT(vcl_sqrt(*pixelB));
00552 }
00553 }
00554 }
00555 }
00556
00557
00558
00559
00560
00561 template<class srcT, class destT>
00562 inline
00563 void vil_math_sum_sqr(const vil_image_view<srcT>& src,
00564 vil_image_view<destT>& dest)
00565 {
00566 unsigned ni = src.ni(),nj = src.nj(),np = src.nplanes();
00567 dest.set_size(ni,nj,1);
00568
00569 vcl_ptrdiff_t istepA=src.istep(),jstepA=src.jstep(),pstepA = src.planestep();
00570 vcl_ptrdiff_t istepB=dest.istep(),jstepB=dest.jstep();
00571 const srcT* rowA = src.top_left_ptr();
00572 destT* rowB = dest.top_left_ptr();
00573 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00574 {
00575 const srcT* pixelA = rowA;
00576 const srcT* end_pixelA = rowA+ni*istepA;
00577 destT* pixelB = rowB;
00578 if (np==1)
00579 {
00580 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00581 *pixelB = destT(*pixelA)*(*pixelA);
00582 }
00583 else if (np==2)
00584 {
00585 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00586 *pixelB = destT(*pixelA)*(*pixelA)
00587 + destT(pixelA[pstepA])*(pixelA[pstepA]);
00588 }
00589 else
00590 {
00591 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00592 {
00593 *pixelB = destT(*pixelA)*destT(*pixelA);
00594 const srcT* p=pixelA+pstepA;
00595 const srcT* end_p=pixelA+np*pstepA;
00596 for (;p!=end_p;p+=pstepA) *pixelB += destT(*p)*destT(*p);
00597 }
00598 }
00599 }
00600 }
00601
00602
00603
00604 template<class aT, class bT, class sumT>
00605 inline void vil_math_image_sum(const vil_image_view<aT>& imA,
00606 const vil_image_view<bT>& imB,
00607 vil_image_view<sumT>& im_sum)
00608 {
00609 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00610 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00611 im_sum.set_size(ni,nj,np);
00612
00613 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00614 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00615 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep(),pstepS = im_sum.planestep();
00616 const aT* planeA = imA.top_left_ptr();
00617 const bT* planeB = imB.top_left_ptr();
00618 sumT* planeS = im_sum.top_left_ptr();
00619 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00620 {
00621 const aT* rowA = planeA;
00622 const bT* rowB = planeB;
00623 sumT* rowS = planeS;
00624 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00625 {
00626 const aT* pixelA = rowA;
00627 const bT* pixelB = rowB;
00628 sumT* pixelS = rowS;
00629 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00630 *pixelS = sumT(*pixelA)+sumT(*pixelB);
00631 }
00632 }
00633 }
00634
00635
00636
00637
00638
00639
00640 template<class aT, class bT, class sumT>
00641 inline void vil_math_image_product(const vil_image_view<aT>& imA,
00642 const vil_image_view<bT>& imB,
00643 vil_image_view<sumT>& im_product)
00644 {
00645 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00646 assert(imB.ni()==ni && imB.nj()==nj);
00647 assert(imB.nplanes()==1 || imB.nplanes()==np);
00648 im_product.set_size(ni,nj,np);
00649
00650 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00651 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00652 vcl_ptrdiff_t istepP=im_product.istep(),jstepP=im_product.jstep(),
00653 pstepP = im_product.planestep();
00654
00655
00656 if (imB.nplanes()==1) pstepB=0;
00657
00658 const aT* planeA = imA.top_left_ptr();
00659 const bT* planeB = imB.top_left_ptr();
00660 sumT* planeP = im_product.top_left_ptr();
00661 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeP += pstepP)
00662 {
00663 const aT* rowA = planeA;
00664 const bT* rowB = planeB;
00665 sumT* rowP = planeP;
00666 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowP += jstepP)
00667 {
00668 const aT* pixelA = rowA;
00669 const bT* pixelB = rowB;
00670 sumT* pixelP = rowP;
00671 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelP+=istepP)
00672 *pixelP = sumT(*pixelA)*sumT(*pixelB);
00673 }
00674 }
00675 }
00676
00677
00678
00679 template<class aT, class bT, class maxT>
00680 inline void vil_math_image_max(const vil_image_view<aT>& imA,
00681 const vil_image_view<bT>& imB,
00682 vil_image_view<maxT>& im_max)
00683 {
00684 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00685 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00686 im_max.set_size(ni,nj,np);
00687
00688 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00689 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00690 vcl_ptrdiff_t istepS=im_max.istep(),jstepS=im_max.jstep(),pstepS = im_max.planestep();
00691 const aT* planeA = imA.top_left_ptr();
00692 const bT* planeB = imB.top_left_ptr();
00693 maxT* planeS = im_max.top_left_ptr();
00694 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00695 {
00696 const aT* rowA = planeA;
00697 const bT* rowB = planeB;
00698 maxT* rowS = planeS;
00699 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00700 {
00701 const aT* pixelA = rowA;
00702 const bT* pixelB = rowB;
00703 maxT* pixelS = rowS;
00704 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00705 *pixelS = maxT(vcl_max(*pixelA, *pixelB));
00706 }
00707 }
00708 }
00709
00710
00711
00712 template<class aT, class bT, class minT>
00713 inline void vil_math_image_min(const vil_image_view<aT>& imA,
00714 const vil_image_view<bT>& imB,
00715 vil_image_view<minT>& im_min)
00716 {
00717 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00718 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00719 im_min.set_size(ni,nj,np);
00720
00721 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00722 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00723 vcl_ptrdiff_t istepS=im_min.istep(),jstepS=im_min.jstep(),pstepS = im_min.planestep();
00724 const aT* planeA = imA.top_left_ptr();
00725 const bT* planeB = imB.top_left_ptr();
00726 minT* planeS = im_min.top_left_ptr();
00727 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00728 {
00729 const aT* rowA = planeA;
00730 const bT* rowB = planeB;
00731 minT* rowS = planeS;
00732 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00733 {
00734 const aT* pixelA = rowA;
00735 const bT* pixelB = rowB;
00736 minT* pixelS = rowS;
00737 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00738 *pixelS = minT(vcl_min(*pixelA, *pixelB));
00739 }
00740 }
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 template<class aT, class bT, class sumT>
00752 inline void vil_math_image_ratio(const vil_image_view<aT>& imA,
00753 const vil_image_view<bT>& imB,
00754 vil_image_view<sumT>& im_ratio)
00755 {
00756 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00757 assert(imB.ni()==ni && imB.nj()==nj);
00758 assert(imB.ni()==ni && imB.nj()==nj);
00759 assert(imB.nplanes()==1 || imB.nplanes()==np);
00760 im_ratio.set_size(ni,nj,np);
00761
00762 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00763 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00764 vcl_ptrdiff_t istepR=im_ratio.istep(),jstepR=im_ratio.jstep(),
00765 pstepR = im_ratio.planestep();
00766
00767
00768 if (imB.nplanes()==1) pstepB=0;
00769
00770 const aT* planeA = imA.top_left_ptr();
00771 const bT* planeB = imB.top_left_ptr();
00772 sumT* planeR = im_ratio.top_left_ptr();
00773 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeR += pstepR)
00774 {
00775 const aT* rowA = planeA;
00776 const bT* rowB = planeB;
00777 sumT* rowR = planeR;
00778 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowR += jstepR)
00779 {
00780 const aT* pixelA = rowA;
00781 const bT* pixelB = rowB;
00782 sumT* pixelR = rowR;
00783 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelR+=istepR)
00784 if (*pixelB==0) *pixelR=0;
00785 else *pixelR = sumT(*pixelA)/sumT(*pixelB);
00786 }
00787 }
00788 }
00789
00790
00791
00792 template<class aT, class bT, class sumT>
00793 inline void vil_math_image_difference(const vil_image_view<aT>& imA,
00794 const vil_image_view<bT>& imB,
00795 vil_image_view<sumT>& im_sum)
00796 {
00797 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00798 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00799 im_sum.set_size(ni,nj,np);
00800
00801 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00802 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00803 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep(),pstepS = im_sum.planestep();
00804 const aT* planeA = imA.top_left_ptr();
00805 const bT* planeB = imB.top_left_ptr();
00806 sumT* planeS = im_sum.top_left_ptr();
00807 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00808 {
00809 const aT* rowA = planeA;
00810 const bT* rowB = planeB;
00811 sumT* rowS = planeS;
00812 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00813 {
00814 const aT* pixelA = rowA;
00815 const bT* pixelB = rowB;
00816 sumT* pixelS = rowS;
00817 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00818 *pixelS = sumT(*pixelA)-sumT(*pixelB);
00819 }
00820 }
00821 }
00822
00823
00824
00825 template<class aT, class bT, class sumT>
00826 inline void vil_math_image_abs_difference(const vil_image_view<aT>& imA,
00827 const vil_image_view<bT>& imB,
00828 vil_image_view<sumT>& im_sum)
00829 {
00830 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00831 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00832 im_sum.set_size(ni,nj,np);
00833
00834 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00835 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00836 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep(),pstepS = im_sum.planestep();
00837 const aT* planeA = imA.top_left_ptr();
00838 const bT* planeB = imB.top_left_ptr();
00839 sumT* planeS = im_sum.top_left_ptr();
00840 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00841 {
00842 const aT* rowA = planeA;
00843 const bT* rowB = planeB;
00844 sumT* rowS = planeS;
00845 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00846 {
00847 const aT* pixelA = rowA;
00848 const bT* pixelB = rowB;
00849 sumT* pixelS = rowS;
00850 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00851 {
00852
00853 *pixelS = (sumT)(*pixelA>*pixelB?(*pixelA-*pixelB):(*pixelB-*pixelA));
00854 }
00855 }
00856 }
00857 }
00858
00859
00860
00861 template<class aT, class bT>
00862 inline double vil_math_image_abs_difference(const vil_image_view<aT>& imA,
00863 const vil_image_view<bT>& imB)
00864 {
00865 double sum=0.0;
00866 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00867 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00868
00869 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00870 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00871 const aT* planeA = imA.top_left_ptr();
00872 const bT* planeB = imB.top_left_ptr();
00873 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB)
00874 {
00875 const aT* rowA = planeA;
00876 const bT* rowB = planeB;
00877 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00878 {
00879 const aT* pixelA = rowA;
00880 const bT* pixelB = rowB;
00881 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB)
00882 {
00883
00884 sum += (*pixelA>*pixelB?(*pixelA-*pixelB):(*pixelB-*pixelA));
00885 }
00886 }
00887 }
00888 return sum;
00889 }
00890
00891
00892
00893 template<class aT, class bT, class magT>
00894 inline void vil_math_image_vector_mag(const vil_image_view<aT>& imA,
00895 const vil_image_view<bT>& imB,
00896 vil_image_view<magT>& im_mag)
00897 {
00898 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00899 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00900 im_mag.set_size(ni,nj,np);
00901
00902 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00903 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00904 vcl_ptrdiff_t istepM=im_mag.istep(),jstepM=im_mag.jstep(),pstepM = im_mag.planestep();
00905 const aT* planeA = imA.top_left_ptr();
00906 const bT* planeB = imB.top_left_ptr();
00907 magT* planeM = im_mag.top_left_ptr();
00908 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeM += pstepM)
00909 {
00910 const aT* rowA = planeA;
00911 const bT* rowB = planeB;
00912 magT* rowM = planeM;
00913 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowM += jstepM)
00914 {
00915 const aT* pixelA = rowA;
00916 const bT* pixelB = rowB;
00917 magT* pixelM = rowM;
00918 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelM+=istepM)
00919 {
00920
00921 magT mag_sqr = static_cast<magT>((*pixelA)*(*pixelA) + (*pixelB)*(*pixelB));
00922 magT mag = vil_math_sqrt_functor()(mag_sqr);
00923 *pixelM = mag;
00924 }
00925 }
00926 }
00927 }
00928
00929
00930
00931
00932
00933 template<class aT, class bT, class scaleT>
00934 inline void vil_math_add_image_fraction(vil_image_view<aT>& imA, scaleT fa,
00935 const vil_image_view<bT>& imB, scaleT fb)
00936 {
00937 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00938 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00939
00940 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00941 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00942 aT* planeA = imA.top_left_ptr();
00943 const bT* planeB = imB.top_left_ptr();
00944 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB)
00945 {
00946 aT* rowA = planeA;
00947 const bT* rowB = planeB;
00948 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00949 {
00950 aT* pixelA = rowA;
00951 const bT* pixelB = rowB;
00952 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB)
00953 *pixelA = aT(fa*(*pixelA)+fb*(*pixelB));
00954 }
00955 }
00956 }
00957
00958
00959
00960
00961
00962
00963
00964 template<class aT, class sumT>
00965 inline void vil_math_integral_image(const vil_image_view<aT>& imA,
00966 vil_image_view<sumT>& im_sum)
00967 {
00968 assert(imA.nplanes()==1);
00969 unsigned ni = imA.ni(),nj = imA.nj();
00970 unsigned ni1=ni+1;
00971 unsigned nj1=nj+1;
00972 im_sum.set_size(ni1,nj1,1);
00973
00974
00975
00976 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep();
00977 sumT* rowS = im_sum.top_left_ptr();
00978 sumT* pixelS = rowS;
00979 for (unsigned i=0;i<ni1;++i,pixelS+=istepS)
00980 *pixelS=0;
00981
00982
00983 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep();
00984 const aT* rowA = imA.top_left_ptr();
00985
00986 sumT sum;
00987 vcl_ptrdiff_t prev_j = -jstepS;
00988 rowS += jstepS;
00989
00990 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowS += jstepS)
00991 {
00992 const aT* pixelA = rowA;
00993 pixelS = rowS;
00994 sum = 0;
00995
00996 *pixelS = 0;
00997 pixelS+=istepS;
00998 for (unsigned i=1;i<ni1;++i,pixelA+=istepA,pixelS+=istepS)
00999 { sum+= *pixelA; *pixelS=sum + pixelS[prev_j];}
01000 }
01001 }
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014 template<class aT, class sumT>
01015 inline void vil_math_integral_sqr_image(const vil_image_view<aT>& imA,
01016 vil_image_view<sumT>& im_sum,
01017 vil_image_view<sumT>& im_sum_sq)
01018 {
01019 assert(imA.nplanes()==1);
01020 unsigned ni = imA.ni(),nj = imA.nj();
01021 unsigned ni1=ni+1;
01022 unsigned nj1=nj+1;
01023 im_sum.set_size(ni1,nj1,1);
01024 im_sum_sq.set_size(ni1,nj1,1);
01025
01026
01027
01028 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep();
01029 vcl_ptrdiff_t istepS2=im_sum_sq.istep(),jstepS2=im_sum_sq.jstep();
01030 sumT* rowS = im_sum.top_left_ptr();
01031 sumT* rowS2 = im_sum_sq.top_left_ptr();
01032
01033 sumT* pixelS = rowS;
01034 for (unsigned i=0;i<ni1;++i,pixelS+=istepS)
01035 *pixelS=0;
01036
01037
01038 sumT* pixelS2 = rowS2;
01039 for (unsigned i=0;i<ni1;++i,pixelS2+=istepS2)
01040 *pixelS2=0;
01041
01042
01043 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep();
01044 const aT* rowA = imA.top_left_ptr();
01045
01046 sumT sum,sum2;
01047 vcl_ptrdiff_t prev_j = -jstepS;
01048 vcl_ptrdiff_t prev_j2 = -jstepS2;
01049 rowS += jstepS;
01050 rowS2 += jstepS2;
01051
01052 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowS += jstepS,rowS2 += jstepS2)
01053 {
01054 const aT* pixelA = rowA;
01055 pixelS = rowS;
01056 pixelS2 = rowS2;
01057 sum = 0;
01058 sum2 = 0;
01059
01060 *pixelS = 0;
01061 *pixelS2 = 0;
01062 pixelS+=istepS;
01063 pixelS2+=istepS2;
01064 for (unsigned i=1;i<ni1;++i,pixelA+=istepA,pixelS+=istepS,pixelS2+=istepS2)
01065 {
01066 sum+= *pixelA;
01067 *pixelS=sum + pixelS[prev_j];
01068 sum2+=sumT(*pixelA)*sumT(*pixelA);
01069 *pixelS2 = sum2 + pixelS2[prev_j2];
01070 }
01071 }
01072 }
01073
01074 #endif // vil_math_h_