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 vcl_size_t nfrac = fraction.size();
00095 for (vcl_size_t 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 vcl_size_t 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) = (sumT)( 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+=(sumT)(*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/=(sumT)(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/float(im.ni()*im.nj());
00313 var = sum_sq/float(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 double s_;
00366 public:
00367 vil_math_scale_functor(double s) : s_(s) {}
00368 vxl_byte operator()(vxl_byte x) const { return vxl_byte(0.5+s_*x); }
00369 unsigned operator()(unsigned x) const { return unsigned(0.5+s_*x); }
00370 short operator()(short x) const { double r=s_*x; return short(r<0?r-0.5:r+0.5); }
00371 int operator()(int x) const { double r=s_*x; return int(r<0?r-0.5:r+0.5); }
00372 float operator()(float x) const { return float(s_*x); }
00373 double operator()(double x) const { return s_*x; }
00374 vcl_complex<double> operator()(vcl_complex<double> x) const { return s_*x; }
00375 };
00376
00377
00378
00379
00380
00381 class vil_math_scale_and_translate_functor
00382 {
00383 public:
00384
00385
00386
00387 vil_math_scale_and_translate_functor(const double s, const double t)
00388 : s_(s), t_(t) {}
00389
00390 vxl_byte operator()(vxl_byte x) const { return vxl_byte(0.5+s_*x+t_); }
00391 unsigned operator()(unsigned x) const { return unsigned(0.5+s_*x+t_); }
00392 short operator()(short x) const { double r=s_*x+t_; return short(r<0?r-0.5:r+0.5); }
00393 int operator()(int x) const { double r=s_*x+t_; return int(r<0?r-0.5:r+0.5); }
00394 float operator()(float x) const { return float(s_*x+t_); }
00395 double operator()(double x) const { return s_*x+t_; }
00396 vcl_complex<double> operator()(vcl_complex<double> x) const { return s_*x+t_; }
00397
00398 private:
00399 double s_;
00400 double t_;
00401 };
00402
00403
00404
00405 class vil_math_log_functor
00406 {
00407 public:
00408 vxl_byte operator()(vxl_byte x) const { return static_cast<vxl_byte>(0.5+vcl_log(double(x))); }
00409 unsigned operator()(unsigned x) const { return static_cast<unsigned int>(0.5+vcl_log(double(x))); }
00410 int operator()(int x) const { return x>0?static_cast<int>(0.5+vcl_log(double(x))):0; }
00411 short operator()(short x) const { return x>0?static_cast<short>(0.5+vcl_log(double(x))):0; }
00412 float operator()(float x) const { return x>0?vcl_log(x):0.0f; }
00413 double operator()(double x) const { return x>0?vcl_log(x):0.0; }
00414 };
00415
00416
00417
00418
00419 template<class T>
00420 inline void vil_math_scale_values(vil_image_view<T>& image, double scale)
00421 {
00422 vil_transform(image,vil_math_scale_functor(scale));
00423 }
00424
00425
00426
00427 template<class imT, class offsetT>
00428 inline void vil_math_scale_and_offset_values(vil_image_view<imT>& image, double scale, offsetT offset)
00429 {
00430 unsigned ni = image.ni(),nj = image.nj(),np = image.nplanes();
00431 vcl_ptrdiff_t istep=image.istep(),jstep=image.jstep(),pstep = image.planestep();
00432 imT* plane = image.top_left_ptr();
00433 for (unsigned p=0;p<np;++p,plane += pstep)
00434 {
00435 imT* row = plane;
00436 for (unsigned j=0;j<nj;++j,row += jstep)
00437 {
00438 imT* pixel = row;
00439 for (unsigned i=0;i<ni;++i,pixel+=istep) *pixel = imT(scale*(*pixel)+offset);
00440 }
00441 }
00442 }
00443
00444
00445
00446 template<class imT>
00447 inline void vil_math_normalise(vil_image_view<imT>& image)
00448 {
00449 assert(image.nplanes()==1);
00450 double mean,var;
00451 vil_math_mean_and_variance(mean,var,image,0);
00452 double s=0;
00453 if (var>0) s = 1.0/vcl_sqrt(var);
00454 vil_math_scale_and_offset_values(image,s,-s*mean);
00455 }
00456
00457
00458
00459
00460 template<class srcT, class destT>
00461 inline
00462 void vil_math_rms(const vil_image_view<srcT>& src,
00463 vil_image_view<destT>& dest)
00464 {
00465 unsigned ni = src.ni(),nj = src.nj(),np = src.nplanes();
00466 dest.set_size(ni,nj,1);
00467
00468 vcl_ptrdiff_t istepA=src.istep(),jstepA=src.jstep(),pstepA = src.planestep();
00469 vcl_ptrdiff_t istepB=dest.istep(),jstepB=dest.jstep();
00470 const srcT* rowA = src.top_left_ptr();
00471 destT* rowB = dest.top_left_ptr();
00472 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00473 {
00474 const srcT* pixelA = rowA;
00475 const srcT* end_pixelA = rowA+ni*istepA;
00476 destT* pixelB = rowB;
00477
00478 if (np==1)
00479 {
00480 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00481 *pixelB = vcl_fabs(destT(*pixelA));
00482 }
00483 else if (np==2)
00484 {
00485 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00486 {
00487 destT sum2 = destT(*pixelA)*(*pixelA)
00488 + destT(pixelA[pstepA])*(pixelA[pstepA]);
00489 *pixelB = destT(vcl_sqrt(sum2/2));
00490 }
00491 }
00492 else
00493 {
00494 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00495 {
00496 *pixelB = destT(*pixelA)*destT(*pixelA);
00497 const srcT* p=pixelA+pstepA;
00498 const srcT* end_p=pixelA+np*pstepA;
00499 for (;p!=end_p;p+=pstepA) *pixelB += destT(*p)*destT(*p);
00500 *pixelB = destT(vcl_sqrt(*pixelB/np));
00501 }
00502 }
00503 }
00504 }
00505
00506
00507
00508
00509
00510 template<class srcT, class destT>
00511 inline
00512 void vil_math_rss(const vil_image_view<srcT>& src,
00513 vil_image_view<destT>& dest)
00514 {
00515 unsigned ni = src.ni(),nj = src.nj(),np = src.nplanes();
00516 dest.set_size(ni,nj,1);
00517
00518 vcl_ptrdiff_t istepA=src.istep(),jstepA=src.jstep(),pstepA = src.planestep();
00519 vcl_ptrdiff_t istepB=dest.istep(),jstepB=dest.jstep();
00520 const srcT* rowA = src.top_left_ptr();
00521 destT* rowB = dest.top_left_ptr();
00522 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00523 {
00524 const srcT* pixelA = rowA;
00525 const srcT* end_pixelA = rowA+ni*istepA;
00526 destT* pixelB = rowB;
00527
00528 if (np==1)
00529 {
00530 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00531 *pixelB = vcl_fabs(destT(*pixelA));
00532 }
00533 else if (np==2)
00534 {
00535 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00536 {
00537 destT sum2 = destT(*pixelA)*(*pixelA)
00538 + destT(pixelA[pstepA])*(pixelA[pstepA]);
00539 *pixelB = destT(vcl_sqrt(sum2));
00540 }
00541 }
00542 else
00543 {
00544 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00545 {
00546 *pixelB = destT(*pixelA)*destT(*pixelA);
00547 const srcT* p=pixelA+pstepA;
00548 const srcT* end_p=pixelA+np*pstepA;
00549 for (;p!=end_p;p+=pstepA) *pixelB += destT(*p)*destT(*p);
00550 *pixelB = destT(vcl_sqrt(*pixelB));
00551 }
00552 }
00553 }
00554 }
00555
00556
00557
00558
00559
00560 template<class srcT, class destT>
00561 inline
00562 void vil_math_sum_sqr(const vil_image_view<srcT>& src,
00563 vil_image_view<destT>& dest)
00564 {
00565 unsigned ni = src.ni(),nj = src.nj(),np = src.nplanes();
00566 dest.set_size(ni,nj,1);
00567
00568 vcl_ptrdiff_t istepA=src.istep(),jstepA=src.jstep(),pstepA = src.planestep();
00569 vcl_ptrdiff_t istepB=dest.istep(),jstepB=dest.jstep();
00570 const srcT* rowA = src.top_left_ptr();
00571 destT* rowB = dest.top_left_ptr();
00572 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00573 {
00574 const srcT* pixelA = rowA;
00575 const srcT* end_pixelA = rowA+ni*istepA;
00576 destT* pixelB = rowB;
00577 if (np==1)
00578 {
00579 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00580 *pixelB = destT(*pixelA)*(*pixelA);
00581 }
00582 else if (np==2)
00583 {
00584 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00585 *pixelB = destT(*pixelA)*(*pixelA)
00586 + destT(pixelA[pstepA])*(pixelA[pstepA]);
00587 }
00588 else
00589 {
00590 for (;pixelA!=end_pixelA; pixelA+=istepA,pixelB+=istepB)
00591 {
00592 *pixelB = destT(*pixelA)*destT(*pixelA);
00593 const srcT* p=pixelA+pstepA;
00594 const srcT* end_p=pixelA+np*pstepA;
00595 for (;p!=end_p;p+=pstepA) *pixelB += destT(*p)*destT(*p);
00596 }
00597 }
00598 }
00599 }
00600
00601
00602
00603 template<class aT, class bT, class sumT>
00604 inline void vil_math_image_sum(const vil_image_view<aT>& imA,
00605 const vil_image_view<bT>& imB,
00606 vil_image_view<sumT>& im_sum)
00607 {
00608 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00609 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00610 im_sum.set_size(ni,nj,np);
00611
00612 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00613 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00614 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep(),pstepS = im_sum.planestep();
00615 const aT* planeA = imA.top_left_ptr();
00616 const bT* planeB = imB.top_left_ptr();
00617 sumT* planeS = im_sum.top_left_ptr();
00618 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00619 {
00620 const aT* rowA = planeA;
00621 const bT* rowB = planeB;
00622 sumT* rowS = planeS;
00623 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00624 {
00625 const aT* pixelA = rowA;
00626 const bT* pixelB = rowB;
00627 sumT* pixelS = rowS;
00628 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00629 *pixelS = sumT(*pixelA)+sumT(*pixelB);
00630 }
00631 }
00632 }
00633
00634
00635
00636
00637
00638
00639 template<class aT, class bT, class sumT>
00640 inline void vil_math_image_product(const vil_image_view<aT>& imA,
00641 const vil_image_view<bT>& imB,
00642 vil_image_view<sumT>& im_product)
00643 {
00644 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00645 assert(imB.ni()==ni && imB.nj()==nj);
00646 assert(imB.nplanes()==1 || imB.nplanes()==np);
00647 im_product.set_size(ni,nj,np);
00648
00649 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00650 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00651 vcl_ptrdiff_t istepP=im_product.istep(),jstepP=im_product.jstep(),
00652 pstepP = im_product.planestep();
00653
00654
00655 if (imB.nplanes()==1) pstepB=0;
00656
00657 const aT* planeA = imA.top_left_ptr();
00658 const bT* planeB = imB.top_left_ptr();
00659 sumT* planeP = im_product.top_left_ptr();
00660 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeP += pstepP)
00661 {
00662 const aT* rowA = planeA;
00663 const bT* rowB = planeB;
00664 sumT* rowP = planeP;
00665 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowP += jstepP)
00666 {
00667 const aT* pixelA = rowA;
00668 const bT* pixelB = rowB;
00669 sumT* pixelP = rowP;
00670 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelP+=istepP)
00671 *pixelP = sumT(*pixelA)*sumT(*pixelB);
00672 }
00673 }
00674 }
00675
00676
00677
00678 template<class aT, class bT, class maxT>
00679 inline void vil_math_image_max(const vil_image_view<aT>& imA,
00680 const vil_image_view<bT>& imB,
00681 vil_image_view<maxT>& im_max)
00682 {
00683 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00684 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00685 im_max.set_size(ni,nj,np);
00686
00687 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00688 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00689 vcl_ptrdiff_t istepS=im_max.istep(),jstepS=im_max.jstep(),pstepS = im_max.planestep();
00690 const aT* planeA = imA.top_left_ptr();
00691 const bT* planeB = imB.top_left_ptr();
00692 maxT* planeS = im_max.top_left_ptr();
00693 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00694 {
00695 const aT* rowA = planeA;
00696 const bT* rowB = planeB;
00697 maxT* rowS = planeS;
00698 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00699 {
00700 const aT* pixelA = rowA;
00701 const bT* pixelB = rowB;
00702 maxT* pixelS = rowS;
00703 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00704 *pixelS = maxT(vcl_max(*pixelA, *pixelB));
00705 }
00706 }
00707 }
00708
00709
00710
00711 template<class aT, class bT, class minT>
00712 inline void vil_math_image_min(const vil_image_view<aT>& imA,
00713 const vil_image_view<bT>& imB,
00714 vil_image_view<minT>& im_min)
00715 {
00716 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00717 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00718 im_min.set_size(ni,nj,np);
00719
00720 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00721 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00722 vcl_ptrdiff_t istepS=im_min.istep(),jstepS=im_min.jstep(),pstepS = im_min.planestep();
00723 const aT* planeA = imA.top_left_ptr();
00724 const bT* planeB = imB.top_left_ptr();
00725 minT* planeS = im_min.top_left_ptr();
00726 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00727 {
00728 const aT* rowA = planeA;
00729 const bT* rowB = planeB;
00730 minT* rowS = planeS;
00731 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00732 {
00733 const aT* pixelA = rowA;
00734 const bT* pixelB = rowB;
00735 minT* pixelS = rowS;
00736 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00737 *pixelS = minT(vcl_min(*pixelA, *pixelB));
00738 }
00739 }
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 template<class aT, class bT, class sumT>
00751 inline void vil_math_image_ratio(const vil_image_view<aT>& imA,
00752 const vil_image_view<bT>& imB,
00753 vil_image_view<sumT>& im_ratio)
00754 {
00755 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00756 assert(imB.ni()==ni && imB.nj()==nj);
00757 assert(imB.ni()==ni && imB.nj()==nj);
00758 assert(imB.nplanes()==1 || imB.nplanes()==np);
00759 im_ratio.set_size(ni,nj,np);
00760
00761 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00762 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00763 vcl_ptrdiff_t istepR=im_ratio.istep(),jstepR=im_ratio.jstep(),
00764 pstepR = im_ratio.planestep();
00765
00766
00767 if (imB.nplanes()==1) pstepB=0;
00768
00769 const aT* planeA = imA.top_left_ptr();
00770 const bT* planeB = imB.top_left_ptr();
00771 sumT* planeR = im_ratio.top_left_ptr();
00772 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeR += pstepR)
00773 {
00774 const aT* rowA = planeA;
00775 const bT* rowB = planeB;
00776 sumT* rowR = planeR;
00777 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowR += jstepR)
00778 {
00779 const aT* pixelA = rowA;
00780 const bT* pixelB = rowB;
00781 sumT* pixelR = rowR;
00782 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelR+=istepR)
00783 if (*pixelB==0) *pixelR=0;
00784 else *pixelR = sumT(*pixelA)/sumT(*pixelB);
00785 }
00786 }
00787 }
00788
00789
00790
00791 template<class aT, class bT, class sumT>
00792 inline void vil_math_image_difference(const vil_image_view<aT>& imA,
00793 const vil_image_view<bT>& imB,
00794 vil_image_view<sumT>& im_sum)
00795 {
00796 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00797 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00798 im_sum.set_size(ni,nj,np);
00799
00800 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00801 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00802 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep(),pstepS = im_sum.planestep();
00803 const aT* planeA = imA.top_left_ptr();
00804 const bT* planeB = imB.top_left_ptr();
00805 sumT* planeS = im_sum.top_left_ptr();
00806 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00807 {
00808 const aT* rowA = planeA;
00809 const bT* rowB = planeB;
00810 sumT* rowS = planeS;
00811 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00812 {
00813 const aT* pixelA = rowA;
00814 const bT* pixelB = rowB;
00815 sumT* pixelS = rowS;
00816 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00817 *pixelS = sumT(*pixelA)-sumT(*pixelB);
00818 }
00819 }
00820 }
00821
00822
00823
00824 template<class aT, class bT, class sumT>
00825 inline void vil_math_image_abs_difference(const vil_image_view<aT>& imA,
00826 const vil_image_view<bT>& imB,
00827 vil_image_view<sumT>& im_sum)
00828 {
00829 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00830 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00831 im_sum.set_size(ni,nj,np);
00832
00833 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00834 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00835 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep(),pstepS = im_sum.planestep();
00836 const aT* planeA = imA.top_left_ptr();
00837 const bT* planeB = imB.top_left_ptr();
00838 sumT* planeS = im_sum.top_left_ptr();
00839 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00840 {
00841 const aT* rowA = planeA;
00842 const bT* rowB = planeB;
00843 sumT* rowS = planeS;
00844 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00845 {
00846 const aT* pixelA = rowA;
00847 const bT* pixelB = rowB;
00848 sumT* pixelS = rowS;
00849 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00850 {
00851
00852 *pixelS = (*pixelA>*pixelB)?(sumT)(*pixelA-*pixelB):(sumT)(*pixelB-*pixelA);
00853 }
00854 }
00855 }
00856 }
00857
00858
00859
00860 template<class aT, class bT>
00861 inline double vil_math_image_abs_difference(const vil_image_view<aT>& imA,
00862 const vil_image_view<bT>& imB)
00863 {
00864 double sum=0.0;
00865 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00866 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00867
00868 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00869 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00870 const aT* planeA = imA.top_left_ptr();
00871 const bT* planeB = imB.top_left_ptr();
00872 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB)
00873 {
00874 const aT* rowA = planeA;
00875 const bT* rowB = planeB;
00876 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00877 {
00878 const aT* pixelA = rowA;
00879 const bT* pixelB = rowB;
00880 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB)
00881 {
00882
00883 sum += (*pixelA>*pixelB?(*pixelA-*pixelB):(*pixelB-*pixelA));
00884 }
00885 }
00886 }
00887 return sum;
00888 }
00889
00890
00891
00892 template<class aT, class bT, class magT>
00893 inline void vil_math_image_vector_mag(const vil_image_view<aT>& imA,
00894 const vil_image_view<bT>& imB,
00895 vil_image_view<magT>& im_mag)
00896 {
00897 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00898 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00899 im_mag.set_size(ni,nj,np);
00900
00901 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00902 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00903 vcl_ptrdiff_t istepM=im_mag.istep(),jstepM=im_mag.jstep(),pstepM = im_mag.planestep();
00904 const aT* planeA = imA.top_left_ptr();
00905 const bT* planeB = imB.top_left_ptr();
00906 magT* planeM = im_mag.top_left_ptr();
00907 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeM += pstepM)
00908 {
00909 const aT* rowA = planeA;
00910 const bT* rowB = planeB;
00911 magT* rowM = planeM;
00912 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowM += jstepM)
00913 {
00914 const aT* pixelA = rowA;
00915 const bT* pixelB = rowB;
00916 magT* pixelM = rowM;
00917 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelM+=istepM)
00918 {
00919
00920 magT mag_sqr = static_cast<magT>((*pixelA)*(*pixelA) + (*pixelB)*(*pixelB));
00921 magT mag = vil_math_sqrt_functor()(mag_sqr);
00922 *pixelM = mag;
00923 }
00924 }
00925 }
00926 }
00927
00928
00929
00930
00931
00932 template<class aT, class bT, class scaleT>
00933 inline void vil_math_add_image_fraction(vil_image_view<aT>& imA, scaleT fa,
00934 const vil_image_view<bT>& imB, scaleT fb)
00935 {
00936 unsigned ni = imA.ni(),nj = imA.nj(),np = imA.nplanes();
00937 assert(imB.ni()==ni && imB.nj()==nj && imB.nplanes()==np);
00938
00939 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),pstepA = imA.planestep();
00940 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),pstepB = imB.planestep();
00941 aT* planeA = imA.top_left_ptr();
00942 const bT* planeB = imB.top_left_ptr();
00943 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB)
00944 {
00945 aT* rowA = planeA;
00946 const bT* rowB = planeB;
00947 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00948 {
00949 aT* pixelA = rowA;
00950 const bT* pixelB = rowB;
00951 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB)
00952 *pixelA = aT(fa*(*pixelA)+fb*(*pixelB));
00953 }
00954 }
00955 }
00956
00957
00958
00959
00960
00961
00962
00963 template<class aT, class sumT>
00964 inline void vil_math_integral_image(const vil_image_view<aT>& imA,
00965 vil_image_view<sumT>& im_sum)
00966 {
00967 assert(imA.nplanes()==1);
00968 unsigned ni = imA.ni(),nj = imA.nj();
00969 unsigned ni1=ni+1;
00970 unsigned nj1=nj+1;
00971 im_sum.set_size(ni1,nj1,1);
00972
00973
00974 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep();
00975 sumT* rowS = im_sum.top_left_ptr();
00976 sumT* pixelS = rowS;
00977 for (unsigned i=0;i<ni1;++i,pixelS+=istepS)
00978 *pixelS=0;
00979
00980
00981 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep();
00982 const aT* rowA = imA.top_left_ptr();
00983
00984 sumT sum;
00985 vcl_ptrdiff_t prev_j = -jstepS;
00986 rowS += jstepS;
00987
00988 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowS += jstepS)
00989 {
00990 const aT* pixelA = rowA;
00991 pixelS = rowS;
00992 sum = 0;
00993
00994 *pixelS = 0;
00995 pixelS+=istepS;
00996 for (unsigned i=1;i<ni1;++i,pixelA+=istepA,pixelS+=istepS)
00997 { sum+= (sumT)(*pixelA); *pixelS=sum + pixelS[prev_j];}
00998 }
00999 }
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012 template<class aT, class sumT>
01013 inline void vil_math_integral_sqr_image(const vil_image_view<aT>& imA,
01014 vil_image_view<sumT>& im_sum,
01015 vil_image_view<sumT>& im_sum_sq)
01016 {
01017 assert(imA.nplanes()==1);
01018 unsigned ni = imA.ni(),nj = imA.nj();
01019 unsigned ni1=ni+1;
01020 unsigned nj1=nj+1;
01021 im_sum.set_size(ni1,nj1,1);
01022 im_sum_sq.set_size(ni1,nj1,1);
01023
01024
01025 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep();
01026 vcl_ptrdiff_t istepS2=im_sum_sq.istep(),jstepS2=im_sum_sq.jstep();
01027 sumT* rowS = im_sum.top_left_ptr();
01028 sumT* rowS2 = im_sum_sq.top_left_ptr();
01029
01030 sumT* pixelS = rowS;
01031 for (unsigned i=0;i<ni1;++i,pixelS+=istepS)
01032 *pixelS=0;
01033
01034
01035 sumT* pixelS2 = rowS2;
01036 for (unsigned i=0;i<ni1;++i,pixelS2+=istepS2)
01037 *pixelS2=0;
01038
01039
01040 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep();
01041 const aT* rowA = imA.top_left_ptr();
01042
01043 sumT sum,sum2;
01044 vcl_ptrdiff_t prev_j = -jstepS;
01045 vcl_ptrdiff_t prev_j2 = -jstepS2;
01046 rowS += jstepS;
01047 rowS2 += jstepS2;
01048
01049 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowS += jstepS,rowS2 += jstepS2)
01050 {
01051 const aT* pixelA = rowA;
01052 pixelS = rowS;
01053 pixelS2 = rowS2;
01054 sum = 0;
01055 sum2 = 0;
01056
01057 *pixelS = 0;
01058 *pixelS2 = 0;
01059 pixelS+=istepS;
01060 pixelS2+=istepS2;
01061 for (unsigned i=1;i<ni1;++i,pixelA+=istepA,pixelS+=istepS,pixelS2+=istepS2)
01062 {
01063 sum+= (sumT)(*pixelA);
01064 *pixelS=sum + pixelS[prev_j];
01065 sum2+=sumT(*pixelA)*sumT(*pixelA);
01066 *pixelS2 = sum2 + pixelS2[prev_j2];
01067 }
01068 }
01069 }
01070
01071 #endif // vil_math_h_