00001
00002 #ifndef vil3d_math_h_
00003 #define vil3d_math_h_
00004
00005
00006
00007
00008
00009 #include <vcl_cassert.h>
00010 #include <vcl_vector.h>
00011
00012 #include <vil3d/vil3d_image_view.h>
00013 #include <vil3d/vil3d_plane.h>
00014 #include <vcl_algorithm.h>
00015
00016
00017
00018
00019 template <class T>
00020 inline void vil3d_math_value_range(const vil3d_image_view<T>& im,
00021 T& min_value, T& max_value)
00022 {
00023 if (im.size()==0)
00024 {
00025 min_value = 0;
00026 max_value = 0;
00027 return;
00028 }
00029
00030 const T* plane = im.origin_ptr();
00031 min_value = *plane;
00032 max_value = min_value;
00033
00034 unsigned ni = im.ni();
00035 unsigned nj = im.nj();
00036 unsigned nk = im.nk();
00037 unsigned np = im.nplanes();
00038 vcl_ptrdiff_t istep = im.istep(), jstep=im.jstep(), kstep=im.kstep();
00039
00040 for (unsigned int p=0;p<np;++p, plane += im.planestep())
00041 {
00042 const T* slice = plane;
00043 for (unsigned int k=0;k<nk;++k, slice += kstep)
00044 {
00045 const T* row = slice;
00046 for (unsigned int j=0;j<nj;++j, row += jstep)
00047 {
00048 const T* pixel = row;
00049 for (unsigned int i=0;i<ni;++i, pixel+=istep)
00050 {
00051 if (*pixel<min_value) min_value = *pixel;
00052 else if (*pixel>max_value) max_value = *pixel;
00053 }
00054 }
00055 }
00056 }
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 template <class T>
00070 inline void vil3d_math_value_range_percentile(const vil3d_image_view<T>& im,
00071 const double fraction,
00072 T& value)
00073 {
00074 vcl_vector<double> fractions(1, fraction);
00075 vcl_vector<T> values;
00076 vil3d_math_value_range_percentiles(im, fractions, values);
00077 if (values.size() > 0)
00078 value = values[0];
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 template <class T>
00091 inline void vil3d_math_value_range_percentiles(const vil3d_image_view<T>& im,
00092 const vcl_vector<double> fraction,
00093 vcl_vector<T>& value)
00094 {
00095 value.clear();
00096
00097
00098 if (im.size()==0)
00099 {
00100 return;
00101 }
00102 unsigned nfrac = fraction.size();
00103 for (unsigned f=0; f<nfrac; ++f)
00104 {
00105 if (fraction[f]<0.0 || fraction[f]>1.0)
00106 return;
00107 }
00108
00109
00110 unsigned ni = im.ni();
00111 unsigned nj = im.nj();
00112 unsigned nk = im.nk();
00113 unsigned np = im.nplanes();
00114 vcl_ptrdiff_t istep = im.istep();
00115 vcl_ptrdiff_t jstep=im.jstep();
00116 vcl_ptrdiff_t kstep=im.kstep();
00117 vcl_ptrdiff_t pstep = im.planestep();
00118 vcl_vector<T> data(ni*nj*nk*np);
00119
00120 typename vcl_vector<T>::iterator it = data.begin();
00121 const T* plane = im.origin_ptr();
00122 for (unsigned int p=0;p<np;++p, plane += pstep)
00123 {
00124 const T* slice = plane;
00125 for (unsigned int k=0;k<nk;++k, slice += kstep)
00126 {
00127 const T* row = slice;
00128 for (unsigned int j=0;j<nj;++j, row += jstep)
00129 {
00130 const T* pixel = row;
00131 for (unsigned int i=0;i<ni;++i, pixel+=istep)
00132 {
00133 *it = *pixel;
00134 it++;
00135 }
00136 }
00137 }
00138 }
00139 unsigned npix = data.size();
00140
00141
00142 value.resize(nfrac);
00143 for (unsigned f=0; f<nfrac; ++f)
00144 {
00145 unsigned index = static_cast<unsigned>(fraction[f]*npix - 0.5);
00146 typename vcl_vector<T>::iterator index_it = data.begin() + index;
00147 vcl_nth_element(data.begin(), index_it, data.end());
00148 value[f] = *index_it;
00149 }
00150 }
00151
00152
00153
00154
00155 template<class aT, class sumT>
00156 inline void vil3d_math_mean_over_planes(const vil3d_image_view<aT>& src,
00157 vil3d_image_view<sumT>& dest)
00158 {
00159 dest.set_size(src.ni(), src.nj(), src.nk(), 1);
00160 for (unsigned k=0;k<src.nk();++k)
00161 for (unsigned j=0;j<src.nj();++j)
00162 for (unsigned i=0;i<src.ni();++i)
00163 {
00164 sumT sum=0;
00165 for (unsigned p=0;p<src.nplanes();++p)
00166 sum += (sumT) src(i,j,k,p);
00167 dest(i,j,k) = sum / src.nplanes();
00168 }
00169 }
00170
00171
00172
00173 template<class inT, class outT, class sumT>
00174 inline void vil3d_math_mean_over_planes(const vil3d_image_view<inT>& src,
00175 vil3d_image_view<outT>& dest,
00176 sumT )
00177 {
00178 dest.set_size(src.ni(), src.nj(), src.nk(), 1);
00179 for (unsigned k=0;k<src.nk();++k)
00180 for (unsigned j=0;j<src.nj();++j)
00181 for (unsigned i=0;i<src.ni();++i)
00182 {
00183 sumT sum=0;
00184 for (unsigned p=0;p<src.nplanes();++p)
00185 sum += static_cast<sumT>(src(i,j,k,p));
00186 dest(i,j,k) = static_cast<outT>(sum / src.nplanes());
00187 }
00188 }
00189
00190
00191
00192 template<class inT, class outT, class sumT>
00193 inline void vil3d_math_rms(const vil3d_image_view<inT>& src,
00194 vil3d_image_view<outT>& dest,
00195 sumT )
00196 {
00197 dest.set_size(src.ni(), src.nj(), src.nk(), 1);
00198 for (unsigned k=0;k<src.nk();++k)
00199 for (unsigned j=0;j<src.nj();++j)
00200 for (unsigned i=0;i<src.ni();++i)
00201 {
00202 sumT sum_sqr=0;
00203 for (unsigned p=0;p<src.nplanes();++p)
00204 sum_sqr += static_cast<sumT>(src(i,j,k,p))*static_cast<sumT>(src(i,j,k,p));
00205 dest(i,j,k) = static_cast<outT>(vcl_sqrt(sum_sqr / src.nplanes()));
00206 }
00207 }
00208
00209
00210
00211
00212 template <class imT, class sumT>
00213 inline void vil3d_math_sum(sumT& sum, const vil3d_image_view<imT>& im,
00214 unsigned p)
00215 {
00216 assert(p<im.nplanes());
00217 sum=0;
00218 if (im.size()==0)
00219 {
00220 return;
00221 }
00222
00223 const imT* plane = im.origin_ptr();
00224 unsigned ni = im.ni();
00225 unsigned nj = im.nj();
00226 unsigned nk = im.nk();
00227 vcl_ptrdiff_t istep = im.istep(), jstep=im.jstep(), kstep=im.kstep();
00228
00229 const imT* slice = plane + p*im.planestep();
00230 for (unsigned int k=0;k<nk;++k, slice += kstep)
00231 {
00232 const imT* row = slice;
00233 for (unsigned int j=0;j<nj;++j, row += jstep)
00234 {
00235 const imT* pixel = row;
00236 for (unsigned int i=0;i<ni;++i, pixel+=istep) sum += sumT(*pixel);
00237 }
00238 }
00239 }
00240
00241
00242
00243 template <class imT, class sumT>
00244 inline void vil3d_math_mean(sumT& mean, const vil3d_image_view<imT>& im,
00245 unsigned p)
00246 {
00247 if (im.size()==0) { mean=0; return; }
00248 vil3d_math_sum(mean,im,p);
00249 mean/=(im.ni()*im.nj()*im.nk());
00250 }
00251
00252
00253
00254
00255 template <class imT, class sumT>
00256 inline void vil3d_math_sum_squares(sumT& sum, sumT& sum_sq,
00257 const vil3d_image_view<imT>& im, unsigned p)
00258 {
00259 assert(p<im.nplanes());
00260 sum = 0; sum_sq=0;
00261 if (im.size()==0)
00262 {
00263 return;
00264 }
00265
00266 const imT* plane = im.origin_ptr();
00267 unsigned ni = im.ni();
00268 unsigned nj = im.nj();
00269 unsigned nk = im.nk();
00270 vcl_ptrdiff_t istep = im.istep(), jstep=im.jstep(), kstep=im.kstep();
00271
00272 const imT* slice = plane + p*im.planestep();
00273 for (unsigned int k=0;k<nk;++k, slice += kstep)
00274 {
00275 const imT* row = slice;
00276 for (unsigned int j=0;j<nj;++j, row += jstep)
00277 {
00278 const imT* p = row;
00279 for (unsigned int i=0;i<ni;++i, p+=istep)
00280 { sum += *p; sum_sq+=sumT(*p)*sumT(*p); }
00281 }
00282 }
00283 }
00284
00285
00286
00287
00288 template <class imT, class sumT>
00289 inline sumT vil3d_math_ssd(const vil3d_image_view<imT>& imA,
00290 const vil3d_image_view<imT>& imB, sumT )
00291 {
00292 assert(imA.ni() == imB.ni() && imB.nj() == imB.nj()
00293 && imB.nk() == imB.nk() && imA.nplanes() == imB.nplanes());
00294 sumT ssd=0;
00295 for (unsigned p=0;p<imA.nplanes();++p)
00296 for (unsigned k=0;k<imA.nk();++k)
00297 for (unsigned j=0;j<imA.nj();++j)
00298 for (unsigned i=0;i<imA.ni();++i)
00299 {
00300 const sumT v = ((sumT)imA(i,j,k,p) - (sumT)imB(i,j,k,p));
00301 ssd += v*v;
00302 }
00303 return ssd;
00304 }
00305
00306
00307
00308
00309 template<class imT, class offsetT>
00310 inline void vil3d_math_scale_and_offset_values(vil3d_image_view<imT>& image,
00311 double scale, offsetT offset)
00312 {
00313 unsigned ni = image.ni(), nj = image.nj(),
00314 nk = image.nk(), np = image.nplanes();
00315 vcl_ptrdiff_t istep=image.istep(), jstep=image.jstep(),
00316 kstep = image.kstep(), pstep = image.planestep();
00317 imT* plane = image.origin_ptr();
00318 for (unsigned p=0;p<np;++p,plane += pstep)
00319 {
00320 imT* slice = plane;
00321 for (unsigned k=0;k<nk;++k,slice += kstep)
00322 {
00323 imT* row = slice;
00324 for (unsigned j=0;j<nj;++j,row += jstep)
00325 {
00326 imT* pixel = row;
00327 for (unsigned i=0;i<ni;++i,pixel+=istep)
00328 *pixel = imT(scale*(*pixel)+offset);
00329 }
00330 }
00331 }
00332 }
00333
00334
00335
00336
00337 template <class imT, class sumT>
00338 inline void vil3d_math_mean_and_variance(sumT& mean, sumT& var,
00339 const vil3d_image_view<imT>& im,
00340 unsigned p)
00341 {
00342 if (im.size()==0) { mean=0; var=0; return; }
00343 sumT sum, sum_sq;
00344 vil3d_math_sum_squares(sum,sum_sq,im,p);
00345 mean = sum/(im.ni()*im.nj()*im.nk());
00346 var = sum_sq/(im.ni()*im.nj()*im.nk()) - mean*mean;
00347 }
00348
00349
00350
00351
00352 template <class imT, class sumT>
00353 inline sumT vil3d_math_dot_product(const vil3d_image_view<imT>& imA,
00354 const vil3d_image_view<imT>& imB, sumT)
00355 {
00356 assert(imA.ni() == imB.ni() && imB.nj() == imB.nj()
00357 && imB.nk() == imB.nk() && imA.nplanes() == imB.nplanes());
00358 sumT dp=0;
00359 for (unsigned p=0;p<imA.nplanes();++p)
00360 for (unsigned k=0;k<imA.nk();++k)
00361 for (unsigned j=0;j<imA.nj();++j)
00362 for (unsigned i=0;i<imA.ni();++i)
00363 dp += (sumT)imA(i,j,k,p) * (sumT)imB(i,j,k,p);
00364 return dp;
00365 }
00366
00367
00368
00369
00370 template<class aT, class bT, class sumT>
00371 inline void vil3d_math_image_difference(const vil3d_image_view<aT>& imA,
00372 const vil3d_image_view<bT>& imB,
00373 vil3d_image_view<sumT>& im_sum)
00374 {
00375 unsigned ni = imA.ni(),nj = imA.nj(),nk = imA.nk(),np = imA.nplanes();
00376 assert(imB.ni()==ni && imB.nj()==nj && imB.nk()==nk && imB.nplanes()==np);
00377 im_sum.set_size(ni,nj,nk,np);
00378
00379 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),kstepA=imA.kstep(),pstepA = imA.planestep();
00380 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),kstepB=imB.kstep(),pstepB = imB.planestep();
00381 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep(),kstepS=im_sum.kstep(),pstepS = im_sum.planestep();
00382 const aT* planeA = imA.origin_ptr();
00383 const bT* planeB = imB.origin_ptr();
00384 sumT* planeS = im_sum.origin_ptr();
00385 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00386 {
00387 const aT* sliceA = planeA;
00388 const bT* sliceB = planeB;
00389 sumT* sliceS = planeS;
00390 for (unsigned k=0;k<nk;++k,sliceA += kstepA,sliceB += kstepB,sliceS += kstepS)
00391 {
00392 const aT* rowA = sliceA;
00393 const bT* rowB = sliceB;
00394 sumT* rowS = sliceS;
00395 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00396 {
00397 const aT* pixelA = rowA;
00398 const bT* pixelB = rowB;
00399 sumT* pixelS = rowS;
00400 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00401 *pixelS = sumT(*pixelA)-sumT(*pixelB);
00402 }
00403 }
00404 }
00405 }
00406
00407
00408
00409 template<class aT, class bT, class sumT>
00410 inline void vil3d_math_image_sum(const vil3d_image_view<aT>& imA,
00411 const vil3d_image_view<bT>& imB,
00412 vil3d_image_view<sumT>& im_sum)
00413 {
00414 unsigned ni = imA.ni(),nj = imA.nj(),nk = imA.nk(),np = imA.nplanes();
00415 assert(imB.ni()==ni && imB.nj()==nj && imB.nk()==nk && imB.nplanes()==np);
00416 im_sum.set_size(ni,nj,nk,np);
00417
00418 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),kstepA=imA.kstep(),pstepA = imA.planestep();
00419 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),kstepB=imB.kstep(),pstepB = imB.planestep();
00420 vcl_ptrdiff_t istepS=im_sum.istep(),jstepS=im_sum.jstep(),kstepS=im_sum.kstep(),pstepS = im_sum.planestep();
00421 const aT* planeA = imA.origin_ptr();
00422 const bT* planeB = imB.origin_ptr();
00423 sumT* planeS = im_sum.origin_ptr();
00424 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00425 {
00426 const aT* sliceA = planeA;
00427 const bT* sliceB = planeB;
00428 sumT* sliceS = planeS;
00429 for (unsigned k=0;k<nk;++k,sliceA += kstepA,sliceB += kstepB,sliceS += kstepS)
00430 {
00431 const aT* rowA = sliceA;
00432 const bT* rowB = sliceB;
00433 sumT* rowS = sliceS;
00434 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00435 {
00436 const aT* pixelA = rowA;
00437 const bT* pixelB = rowB;
00438 sumT* pixelS = rowS;
00439 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00440 *pixelS = sumT(*pixelA)+sumT(*pixelB);
00441 }
00442 }
00443 }
00444 }
00445
00446
00447
00448 template<class aT, class bT, class prodT>
00449 inline void vil3d_math_image_product(const vil3d_image_view<aT>& imA,
00450 const vil3d_image_view<bT>& imB,
00451 vil3d_image_view<prodT>& im_prod)
00452 {
00453 unsigned ni = imA.ni(),nj = imA.nj(),nk = imA.nk(),np = imA.nplanes();
00454 assert(imB.ni()==ni && imB.nj()==nj && imB.nk()==nk && imB.nplanes()==np);
00455 im_prod.set_size(ni,nj,nk,np);
00456
00457 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),kstepA=imA.kstep(),pstepA = imA.planestep();
00458 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),kstepB=imB.kstep(),pstepB = imB.planestep();
00459 vcl_ptrdiff_t istepS=im_prod.istep(),jstepS=im_prod.jstep(),kstepS=im_prod.kstep(),pstepS = im_prod.planestep();
00460 const aT* planeA = imA.origin_ptr();
00461 const bT* planeB = imB.origin_ptr();
00462 prodT* planeS = im_prod.origin_ptr();
00463 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB,planeS += pstepS)
00464 {
00465 const aT* sliceA = planeA;
00466 const bT* sliceB = planeB;
00467 prodT* sliceS = planeS;
00468 for (unsigned k=0;k<nk;++k,sliceA += kstepA,sliceB += kstepB,sliceS += kstepS)
00469 {
00470 const aT* rowA = sliceA;
00471 const bT* rowB = sliceB;
00472 prodT* rowS = sliceS;
00473 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB,rowS += jstepS)
00474 {
00475 const aT* pixelA = rowA;
00476 const bT* pixelB = rowB;
00477 prodT* pixelS = rowS;
00478 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB,pixelS+=istepS)
00479 *pixelS = prodT(*pixelA)*prodT(*pixelB);
00480 }
00481 }
00482 }
00483 }
00484
00485
00486
00487
00488
00489
00490 template<class aT, class bT, class scaleT>
00491 inline void vil3d_math_add_image_fraction(vil3d_image_view<aT>& imA, scaleT fa,
00492 const vil3d_image_view<bT>& imB, scaleT fb)
00493 {
00494 unsigned ni = imA.ni(),nj = imA.nj(),nk = imA.nk(),np = imA.nplanes();
00495 assert(imB.ni()==ni && imB.nj()==nj && imB.nk()==nk && imB.nplanes()==np);
00496
00497 vcl_ptrdiff_t istepA=imA.istep(),jstepA=imA.jstep(),kstepA=imA.kstep(),pstepA = imA.planestep();
00498 vcl_ptrdiff_t istepB=imB.istep(),jstepB=imB.jstep(),kstepB=imB.kstep(),pstepB = imB.planestep();
00499 aT* planeA = imA.origin_ptr();
00500 const bT* planeB = imB.origin_ptr();
00501 for (unsigned p=0;p<np;++p,planeA += pstepA,planeB += pstepB)
00502 {
00503 aT* sliceA = planeA;
00504 const bT* sliceB = planeB;
00505 for (unsigned k=0;k<nk;++k,sliceA += kstepA,sliceB += kstepB)
00506 {
00507 aT* rowA = sliceA;
00508 const bT* rowB = sliceB;
00509 for (unsigned j=0;j<nj;++j,rowA += jstepA,rowB += jstepB)
00510 {
00511 aT* pixelA = rowA;
00512 const bT* pixelB = rowB;
00513 for (unsigned i=0;i<ni;++i,pixelA+=istepA,pixelB+=istepB)
00514 *pixelA = aT(fa*(*pixelA)+fb*(*pixelB));
00515 }
00516 }
00517 }
00518 }
00519
00520
00521
00522
00523
00524 template<class T>
00525 inline void vil3d_math_truncate_range(vil3d_image_view<T>& image,
00526 T min_v, T max_v)
00527 {
00528 unsigned ni=image.ni(), nj=image.nj(), nk=image.nk(), np=image.nplanes();
00529 vcl_ptrdiff_t istep=image.istep(), jstep=image.jstep(),
00530 kstep=image.kstep(), pstep=image.planestep();
00531 T* plane = image.origin_ptr();
00532 for (unsigned p=0; p<np; ++p, plane+=pstep)
00533 {
00534 T* slice = plane;
00535 for (unsigned k=0; k<nk; ++k, slice+=kstep)
00536 {
00537 T* row = slice;
00538 for (unsigned j=0; j<nj; ++j, row+=jstep)
00539 {
00540 T* pixel = row;
00541 for (unsigned i=0; i<ni; ++i, pixel+=istep)
00542 {
00543 if (*pixel<min_v) *pixel=min_v;
00544 else if (*pixel>max_v) *pixel=max_v;
00545 }
00546 }
00547 }
00548 }
00549 }
00550
00551 #endif