contrib/mul/vil3d/algo/vil3d_structuring_element.cxx
Go to the documentation of this file.
00001 // This is mul/vil3d/algo/vil3d_structuring_element.cxx
00002 #include "vil3d_structuring_element.h"
00003 //:
00004 // \file
00005 // \brief Structuring element for morphology represented as a list of non-zero pixels
00006 // \author Tim Cootes
00007 
00008 #include <vcl_cassert.h>
00009 #include <vcl_iostream.h>
00010 
00011   //: Define elements { (p_i[a],p_j[a],p_k[a]) }
00012 vil3d_structuring_element::vil3d_structuring_element(const vcl_vector<int>& p_i,
00013                                                      const vcl_vector<int>& p_j,
00014                                                      const vcl_vector<int>& p_k)
00015 {
00016   set(p_i,p_j,p_k);
00017 }
00018 
00019   //: Define elements { (p_i[a],p_j[a],p_k[a]) }
00020 void vil3d_structuring_element::set(const vcl_vector<int>& p_i,
00021                                     const vcl_vector<int>& p_j,
00022                                     const vcl_vector<int>& p_k)
00023 {
00024   assert(p_i.size()==p_j.size());
00025   assert(p_i.size()==p_k.size());
00026   assert(p_i.size()>0);
00027   p_i_ = p_i;
00028   p_j_ = p_j;
00029   p_k_ = p_k;
00030 
00031   max_i_=min_i_ = p_i[0];
00032   max_j_=min_j_ = p_j[0];
00033   max_k_=min_k_ = p_k[0];
00034   for (unsigned int a=1;a<p_i.size();++a)
00035   {
00036     if (p_i[a]<min_i_) min_i_=p_i[a];
00037     else if (p_i[a]>max_i_) max_i_=p_i[a];
00038 
00039     if (p_j[a]<min_j_) min_j_=p_j[a];
00040     else if (p_j[a]>max_j_) max_j_=p_j[a];
00041 
00042     if (p_k[a]<min_k_) min_k_=p_k[a];
00043     else if (p_k[a]>max_k_) max_k_=p_k[a];
00044   }
00045 }
00046 
00047 
00048 
00049 
00050 //: Set to 6 axis-aligned neighbours plus self
00051 void vil3d_structuring_element::set_to_7()
00052 {
00053   vcl_vector<int> px,py,pz;
00054   for (int i=-1;i<=1;i+=2)
00055   {
00056     px.push_back(i);  py.push_back(0);  pz.push_back(0);
00057     px.push_back(0);  py.push_back(i);  pz.push_back(0);
00058     px.push_back(0);  py.push_back(0);  pz.push_back(i);
00059   }
00060   px.push_back(0);  py.push_back(0);  pz.push_back(0);
00061   set(px,py,pz);
00062 }
00063 
00064   //: Set to 26 touching neighbours plus self
00065 void vil3d_structuring_element::set_to_27()
00066 {
00067   vcl_vector<int> px,py,pz;
00068   for (int k=-1;k<=1;++k)
00069     for (int j=-1;j<=1;++j)
00070       for (int i=-1;i<=1;++i)
00071       {
00072         px.push_back(i);  py.push_back(j);  pz.push_back(k);
00073       }
00074   set(px,py,pz);
00075 }
00076 
00077 
00078 //: Set to sphere of radius r
00079 //  Select pixels in disk s.t. x*x+y*y+z*z<=r^r
00080 void vil3d_structuring_element::set_to_sphere(double r)
00081 {
00082   vcl_vector<int> px,py,pz;
00083   double r2 = r*r;
00084   int r0 = int(r+1);
00085   for (int k=-r0;k<=r0;++k)
00086     for (int j=-r0;j<=r0;++j)
00087       for (int i=-r0;i<=r0;++i)
00088         if (i*i+j*j+k*k<r2)
00089         { px.push_back(i); py.push_back(j); pz.push_back(k); }
00090   set(px,py,pz);
00091 }
00092 
00093 //: Set to circle of radius r
00094 //  Select pixels in circle s.t. y*y+z*z<=r^r
00095 void vil3d_structuring_element::set_to_circle_i(double r)
00096 {
00097   vcl_vector<int> px,py,pz;
00098   double r2 = r*r;
00099   int r0 = int(r+1);
00100   const int i = 0;
00101   for (int k=-r0;k<=r0;++k)
00102     for (int j=-r0;j<=r0;++j)
00103       if (i*i+j*j+k*k<r2)
00104       { px.push_back(i); py.push_back(j); pz.push_back(k); }
00105   set(px,py,pz);
00106 }
00107 
00108 //: Set to circle of radius r
00109 //  Select pixels in circle s.t. x*x+z*z<=r^r
00110 void vil3d_structuring_element::set_to_circle_j(double r)
00111 {
00112   vcl_vector<int> px,py,pz;
00113   double r2 = r*r;
00114   int r0 = int(r+1);
00115   const int j = 0;
00116   for (int k=-r0;k<=r0;++k)
00117     for (int i=-r0;i<=r0;++i)
00118       if (i*i+j*j+k*k<r2)
00119         { px.push_back(i); py.push_back(j); pz.push_back(k); }
00120   set(px,py,pz);
00121 }
00122 
00123 //: Set to circle of radius r
00124 //  Select pixels in circle s.t. y*y+z*z<=r^r
00125 void vil3d_structuring_element::set_to_circle_k(double r)
00126 {
00127   vcl_vector<int> px,py,pz;
00128   double r2 = r*r;
00129   int r0 = int(r+1);
00130   const int k = 0;
00131   for (int j=-r0;j<=r0;++j)
00132     for (int i=-r0;i<=r0;++i)
00133       if (i*i+j*j+k*k<r2)
00134       { px.push_back(i); py.push_back(j); pz.push_back(k); }
00135   set(px,py,pz);
00136 }
00137 
00138 //: Set to sphere of radius r, but with non isotropic voxel sizes
00139 //  Voxel size supplied in sx,sy and sz. r then becomes an absolute radius
00140 //  Select pixels in disk s.t. x*x+y*y+z*z<=r^r
00141 void vil3d_structuring_element::set_to_sphere_noniso(double r, double sx, double sy, double sz)
00142 {
00143   vcl_vector<int> px,py,pz;
00144   double r2 = r*r;
00145   double sx2 = sx*sx;
00146   double sy2 = sy*sy;
00147   double sz2 = sz*sz;
00148   int r0 = int(r+1);
00149   for (int k=-r0;k<=r0;++k)
00150     for (int j=-r0;j<=r0;++j)
00151       for (int i=-r0;i<=r0;++i)
00152         if (i*i*sx2+j*j*sy2+k*k*sz2<r2)
00153         { px.push_back(i); py.push_back(j); pz.push_back(k); }
00154   set(px,py,pz);
00155 }
00156 
00157 //: Set to line along i (ilo,0)..(ihi,0)
00158 void vil3d_structuring_element::set_to_line_i(int ilo, int ihi)
00159 {
00160   p_i_.resize(1+ihi-ilo);
00161   p_j_.resize(1+ihi-ilo);
00162   p_k_.resize(1+ihi-ilo);
00163   for (int i = ilo;i<=ihi;++i)
00164   {
00165     p_i_[i-ilo]=i; p_j_[i-ilo]=0; p_k_[i-ilo]=0;
00166   }
00167 
00168   min_i_ = ilo; max_i_ = ihi;
00169   min_j_ = 0;   max_j_ = 0;
00170   min_k_ = 0;   max_k_ = 0;
00171 }
00172 
00173 //: Set to line along j (jlo,0)..(jhi,0)
00174 void vil3d_structuring_element::set_to_line_j(int jlo, int jhi)
00175 {
00176   p_i_.resize(1+jhi-jlo);
00177   p_j_.resize(1+jhi-jlo);
00178   p_k_.resize(1+jhi-jlo);
00179   for (int j = jlo;j<=jhi;++j)
00180   {
00181     p_i_[j-jlo]=0; p_j_[j-jlo]=j; p_k_[j-jlo]=0;
00182   }
00183 
00184   min_i_ = 0;   max_i_ = 0;
00185   min_j_ = jlo; max_j_ = jhi;
00186   min_k_ = 0;   max_k_ = 0;
00187 }
00188 
00189 //: Set to line along k (klo,0)..(khi,0)
00190 void vil3d_structuring_element::set_to_line_k(int klo, int khi)
00191 {
00192   p_i_.resize(1+khi-klo);
00193   p_j_.resize(1+khi-klo);
00194   p_k_.resize(1+khi-klo);
00195   for (int k = klo;k<=khi;++k)
00196   {
00197     p_i_[k-klo]=0; p_j_[k-klo]=0; p_k_[k-klo]=k;
00198   }
00199 
00200   min_i_ = 0;   max_i_ = 0;
00201   min_j_ = 0;   max_j_ = 0;
00202   min_k_ = klo; max_k_ = khi;
00203 }
00204 
00205 //: Write details to stream
00206 vcl_ostream& operator<<(vcl_ostream& os, const vil3d_structuring_element& element)
00207 {
00208   os<<"Bounds ["
00209     <<element.min_i()<<','<<element.max_i()<<"]["
00210     <<element.min_j()<<','<<element.max_j()<<"]["
00211     <<element.min_k()<<','<<element.max_k()<<"] Points: ";
00212   for (unsigned int a=0;a<element.p_i().size();++a)
00213   {
00214     os<<'('<<element.p_i()[a]<<','
00215       <<element.p_j()[a]<<','<<element.p_k()[a]<<") ";
00216   }
00217   return os;
00218 }
00219 
00220 //: Generate a list of offsets for use on image with istep,jstep,kstep
00221 void vil3d_compute_offsets(vcl_vector<vcl_ptrdiff_t>& offset,
00222                           const vil3d_structuring_element& element,
00223                           vcl_ptrdiff_t istep,
00224                           vcl_ptrdiff_t jstep,
00225                           vcl_ptrdiff_t kstep)
00226 {
00227   unsigned n = element.p_i().size();
00228   offset.resize(n);
00229   for (unsigned int a=0;a<n;++a)
00230     offset[a] = element.p_i()[a]*istep + element.p_j()[a]*jstep
00231               + element.p_k()[a]*kstep;
00232 }
00233