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