/home/oan/prosjekt/gotools/segmentation/gpl_distro/lsseg_1.0_gpl/include/Image.h

Go to the documentation of this file.
00001 //===========================================================================
00002 // The Level-Set Segmentation Library (LSSEG)
00003 //
00004 //
00005 // Copyright (C) 2000-2005 SINTEF ICT, Applied Mathematics, Norway.
00006 //
00007 // This program is free software; you can redistribute it and/or          
00008 // modify it under the terms of the GNU General Public License            
00009 // as published by the Free Software Foundation version 2 of the License. 
00010 //
00011 // This program is distributed in the hope that it will be useful,        
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of         
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
00014 // GNU General Public License for more details.                           
00015 //
00016 // You should have received a copy of the GNU General Public License      
00017 // along with this program; if not, write to the Free Software            
00018 // Foundation, Inc.,                                                      
00019 // 59 Temple Place - Suite 330,                                           
00020 // Boston, MA  02111-1307, USA.                                           
00021 //
00022 // Contact information: e-mail: tor.dokken@sintef.no                      
00023 // SINTEF ICT, Department of Applied Mathematics,                         
00024 // P.O. Box 124 Blindern,                                                 
00025 // 0314 Oslo, Norway.                                                     
00026 // 
00027 //
00028 // Other licenses are also available for this software, notably licenses
00029 // for:
00030 // - Building commercial software.                                        
00031 // - Building software whose source code you wish to keep private.        
00032 //
00033 //===========================================================================
00034 //===========================================================================
00035 //                                                                           
00036 // File: Image.h                                                             
00037 //                                                                           
00038 // Created: Tue Oct 25 13:57:00 2005                                         
00039 //                                                                           
00040 // Author: Odd A. Andersen <Odd.Andersen@sintef.no>
00041 //                                                                           
00042 // Revision: $Id: Image.h,v 1.23 2006/11/22 15:23:00 oan Exp $
00043 //                                                                           
00044 // Description:
00049 //                                                                           
00050 //===========================================================================
00051 
00052 #ifndef _IMAGE_H
00053 #define _IMAGE_H
00054 
00055 #include <algorithm>
00056 #include <assert.h>
00057 #include <vector>
00058 #include <istream>
00059 #include <ostream>
00060 #include <numeric>
00061 #include <boost/lambda/lambda.hpp>
00062 
00063 using namespace boost;
00064 using namespace boost::lambda;
00065 
00066 namespace lsseg {
00067 
00068 //===========================================================================
00070 
00075 template<typename T>
00076 class Image
00077 //===========================================================================
00078 {
00079 public:
00081     typedef T value_type;
00082 
00084     Image() 
00085     {std::fill(dim_, dim_ + 4, 0);}
00086 
00094     Image(int x, int y, int z = 1, int chan = 1, T fill_val = 0) 
00095         : data_(x * y * z * chan, fill_val)
00096     { 
00097         dim_[0] = x;
00098         dim_[1] = y;
00099         dim_[2] = z;
00100         dim_[3] = chan;
00101     }
00102     
00104     virtual ~Image() {}
00105 
00110     template<typename U>
00111     Image(const Image<U>& rhs) {
00112         dim_[0] = rhs.dimx();
00113         dim_[1] = rhs.dimy();
00114         dim_[2] = rhs.dimz();
00115         dim_[3] = rhs.numChannels();
00116         data_.resize(size());
00117         assert(size() == rhs.size());
00118         copy(rhs.begin(), rhs.end(), &data_[0]);
00119     }
00120 
00122     Image(const Image<T>& rhs) : data_(rhs.data_) 
00123     { std::copy(rhs.dim_, rhs.dim_ + 4, dim_);}
00124 
00132     template<typename U>
00133     Image(const Image<U>& rhs, bool copy) {
00134         dim_[0] = rhs.dimx();
00135         dim_[1] = rhs.dimy();
00136         dim_[2] = rhs.dimz();
00137         dim_[3] = rhs.numChannels();
00138         data_.resize(size());
00139         if (copy) {
00140             T* target = begin();
00141             for (const U* it = rhs.begin(); it != rhs.end(); ++it, ++target) {
00142                 *target = T(*it);
00143             }
00144         }
00145     }
00146     
00148     virtual Image<T>& operator=(const Image<T>& rhs) {
00149         Image<T> tmp(rhs);
00150         this->swap(tmp);
00151         return *this;
00152     }
00153 
00155     Image<T>& operator=(const T& val) {
00156         std::fill(data_.begin(), data_.end(), val);
00157         return *this;
00158     }
00159 
00161     unsigned long int size() const { return dim_[0] * dim_[1] * dim_[2] * dim_[3];}
00162 
00164     unsigned long int channelSize() const { return size() / numChannels();}
00165 
00168     unsigned long int graySize2D() const { return dimx() * dimy();}
00169 
00171     int dimx() const { return dim_[0];}
00172 
00174     int dimy() const { return dim_[1];}
00175     
00177     int dimz() const { return dim_[2];}
00178 
00180     int numChannels() const { return dim_[3];}
00181 
00184     template<typename U>
00185     void resize(const Image<U>& rhs) {
00186         resize(rhs.dimx(), rhs.dimy(), rhs.dimz(), rhs.numChannels());
00187     }
00188     
00195     virtual void resize(int x, int y, int z = 1, int channels = 1) 
00196     {
00197         dim_[0] = x;
00198         dim_[1] = y;
00199         dim_[2] = z;
00200         dim_[3] = channels;
00201         data_.resize(size());
00202     }
00203     
00205     virtual void swap(Image<T>& rhs) {
00206         std::swap_ranges(dim_, dim_ + 4, rhs.dim_);
00207         data_.swap(rhs.data_);
00208     }
00209 
00214     Image<T>& operator +=(const Image<T>& rhs) {
00215         assert(size_compatible(rhs));
00216         const T* from = rhs.begin();
00217         T* to;
00218         for (to = begin(); to != end(); ++to, ++from) {
00219             *to += *from;
00220         }
00221         return *this;
00222     }
00223 
00228     Image<T>& operator -=(const Image<T>& rhs) {
00229         assert(size_compatible(rhs));
00230         const T* from = rhs.begin();
00231         T* to;
00232         for (to = begin(); to != end(); ++to, ++from) {
00233             *to -= *from;
00234         }
00235         return *this;
00236     }
00237 
00242     Image<T>& operator +=(T a) {
00243         T* it;
00244         for (it = begin(); it != end(); ++it) {
00245             *it += a;
00246         }
00247         return *this;
00248     }
00249 
00254     Image<T>& operator -=(T a) {
00255         return operator+=(-a);
00256     }
00257 
00262     Image<T>& operator *=(T a) {
00263         T* it;
00264         for (it = begin(); it != end(); ++it) {
00265             *it *= a;
00266         }
00267         return *this;
00268     }
00269 
00274     Image<T>& operator /=(T a) {
00275         const T denom_inv = T(1) / a;
00276         return (*this) *= denom_inv;
00277     }
00278 
00280     T max() const { return *std::max_element(data_.begin(), data_.end()); }
00281 
00283     T min() const { return *std::min_element(data_.begin(), data_.end()); }
00284 
00290     template<typename U>
00291     bool spatial_compatible(const Image<U>& rhs) const {
00292         if (dimx() != rhs.dimx()) return false;
00293         if (dimy() != rhs.dimy()) return false;
00294         if (dimz() != rhs.dimz()) return false;
00295         return true;
00296     }
00297 
00298 
00303     template<typename U>
00304     bool size_compatible(const Image<U>& rhs) const {
00305         if (!spatial_compatible(rhs)) return false;
00306         if (numChannels() != rhs.numChannels()) return false;
00307         return true;
00308     }
00309 
00312     void fill(T val) { std::fill(data_.begin(), data_.end(), val); }
00313 
00315     void setAbsolute() {
00316         for (T* p = begin(); p != end(); ++p) {
00317             if (*p < 0) *p = -(*p);
00318         }
00319     }
00320 
00322     T getAverage() const
00323     { return std::accumulate(data_.begin(), data_.end(), T(0)) / T(size()); }
00324 
00326     T* begin() { return &data_[0];}
00327 
00329     T* end() { return &data_[0] + size();}
00330 
00332     const T* begin() const { return &data_[0];}
00333 
00335     const T* end() const { return &data_[0] + size();}
00336 
00341     T* channelBegin(int channel) { return &data_[0] + channel * channelSize();}
00342 
00346     T* channelEnd(int channel) { return channelBegin(channel) + channelSize();}
00347 
00351     const T* channelBegin(int channel) const { return &data_[0] + channel * channelSize();}
00352 
00356     const T* channelEnd(int channel) const  { return channelBegin(channel) + channelSize();}
00357 
00371     void superpose(const Image<T>& img) {
00372         assert(dimx() == img.dimx() && dimy() == img.dimy()); // at least this must be correct
00373         assert(img.size() <= size());
00374         T* to = begin();
00375         while (to != end()) {
00376             std::transform(img.begin(), img.end(), to, to, _1 + _2);
00377             to += img.size();
00378         }
00379     }
00380 
00388     void intersect(const Image<T>& img) {
00389         assert(size_compatible(img));
00390         std::transform(img.begin(), img.end(), begin(), begin(), _1 && _2);
00391     }
00392 
00395     void dumpInfo(std::ostream& os) const {
00396         os << "-------------\n";
00397         os << "X: " << data_[0] << '\n';
00398         os << "Y: " << data_[1] << '\n';
00399         os << "Z: " << data_[2] << '\n';
00400         os << "Channels: " << data_[3] << std::endl;
00401     }
00402 
00407     size_t indexOf(int x, int y) const {
00408         assert(x >= 0 && y >= 0);
00409         assert(x <= dimx() && y <= dimy());
00410         return x + dim_[0] * y;
00411     }
00412 
00416     size_t indexOf(int x, int y, int z) const {
00417         assert(x >= 0 && y >= 0 && z >= 0);
00418         assert(x <= dimx() && y <= dimy() && z <= dimz());
00419         return x + dim_[0] * (y + dim_[1] * z);
00420     }
00421 
00424     size_t indexOf(int x, int y, int z, int c) const {
00425         assert(x >= 0 && y >= 0 && z >= 0 && c >= 0);
00426         assert(x <= dimx() && y <= dimy() && z <= dimz() && c <= numChannels());
00427         return x + dim_[0] * (y + dim_[1] * (z + dim_[2] * c));
00428     }
00429 
00434     T& operator()(int x, int y) { return data_[indexOf(x, y)];}
00435 
00439     T& operator()(int x, int y, int z) { return data_[indexOf(x, y, z)];}
00440 
00443     T& operator()(int x, int y, int z, int c) { return data_[indexOf(x, y, z, c)];}
00444 
00449     const T& operator()(int x, int y) const { return data_[indexOf(x, y)];}
00450 
00454     const T& operator()(int x, int y, int z) const { return data_[indexOf(x, y, z)];}
00455 
00458     const T& operator()(int x, int y, int z, int c) const { return data_[indexOf(x, y, z, c)];}
00459 
00463     T& operator[](unsigned int ix) {
00464         return data_[ix];
00465     }
00466 
00470     const T& operator[](unsigned int ix) const {
00471         return data_[ix];
00472     }
00473 
00483     virtual void permute(const int* const perm)
00484     {
00485         Image<T> tmp_img(dim_[perm[0]], dim_[perm[1]], dim_[perm[2]], dim_[perm[3]]);
00486         int ix[4];
00487 
00488         const T* dp = begin();
00489         for (ix[3] = 0; ix[3] != numChannels(); ++ix[3]) {
00490             for (ix[2] = 0; ix[2] != dimz(); ++ix[2]) {
00491                 for (ix[1] = 0; ix[1] != dimy(); ++ix[1]) {
00492                     for (ix[0] = 0; ix[0] != dimx(); ++ix[0]) {
00493                         const int Xperm = ix[perm[0]];
00494                         const int Yperm = ix[perm[1]];
00495                         const int Zperm = ix[perm[2]];
00496                         const int Cperm = ix[perm[3]];
00497                         tmp_img.data_[tmp_img.indexOf(Xperm, Yperm, Zperm, Cperm)] = *dp++;
00498                     }
00499                 }
00500             }
00501         }
00502         swap(tmp_img);
00503         
00504 //      Go::GoBorrowedMVGrid<4, T> tmp_grid = getGrid();
00505 //      tmp_grid.permuteElements(perm);
00506 //      for (int i = 0; i < 4; ++i) {
00507 //          dim_[i] = tmp_grid.rowlength(i);
00508 //      }
00509     }
00510 
00515     void write(std::ostream& os, bool binary=true)  const
00516     {
00517         if (binary) {
00518             // writing to file in binary format
00519 
00520             // platform-dependent stuff
00521             assert(sizeof(double) == 8);
00522             assert(sizeof(float) == 4);
00523             assert(sizeof(int) == 4);
00524 
00525             const char* dp = reinterpret_cast<const char*>(dim_);
00526             int dim_storage_size = 4 * sizeof(int);
00527             os.write(dp, dim_storage_size);
00528 
00529             int total_data_size = size() * sizeof(T);
00530             dp = reinterpret_cast<const char*>(&data_[0]);
00531             os.write(dp, total_data_size);
00532 
00533         } else {
00534             // writing to file in ASCII format
00535             for (int d = 0; d != 4; ++d) {
00536                 os << dim_[d] << '\n';
00537             }
00538             for (size_t i = 0; i != data_.size(); ++i) {
00539                 os << data_[i] << ' ';
00540             }
00541             os << std::endl;
00542         }
00543     }
00544 
00545 
00551     virtual void read(std::istream& is, bool binary=true) 
00552     {
00553         Image<T> tmp_img;
00554 
00555         if (binary) {
00556             // read in binary format
00557 
00558             // platform-dependent stuff
00559             assert(sizeof(double) == 8);
00560             assert(sizeof(float) == 4);
00561             assert(sizeof(int) == 4);
00562 
00563             int dim[4];
00564             int dim_storage_size = 4 * sizeof(int);
00565             char* dp = reinterpret_cast<char *>(dim);
00566             is.read(dp, dim_storage_size);
00567             tmp_img.resize(dim[0], dim[1], dim[2], dim[3]);
00568 
00569             int total_data_size = tmp_img.size() * sizeof(T);
00570             dp = reinterpret_cast<char*>(tmp_img.begin());
00571             is.read(dp, total_data_size);
00572             
00573         } else {
00574             // read in ascii format
00575             int dim[4];
00576             for (int i = 0; i != 4; ++i) {
00577                 is >> dim[i];
00578             }
00579             tmp_img.resize(dim[0], dim[1], dim[2], dim[3]);
00580             T* dpointer = tmp_img.begin();
00581             for (size_t i = 0; i != tmp_img.size(); ++i) {
00582                 is >> *dpointer;
00583                 ++dpointer;
00584             }
00585         }
00586         swap(tmp_img);
00587     }
00588 
00601     void applyMask(const Image<char>& mask) {
00602         assert(spatial_compatible(mask));
00603         for (int ch = 0; ch  < numChannels(); ++ch) {
00604             const char* mp = mask.begin();
00605             T* ch_end = channelEnd(ch);
00606             for (T* pt = channelBegin(ch); pt != ch_end; ++pt, ++mp) {
00607                 *pt = (*mp) ? *pt : 0;
00608             }
00609         }
00610     }
00611 
00616     void makeChannelImage(Image<T>& target, int ch) 
00617     {
00618         target.resize(dimx(), dimy(), dimz(), 1);
00619         std::copy(begin() + ch * channelSize(), 
00620                   begin() + (ch + 1) * channelSize(),
00621                   target.begin());
00622     }
00623 
00624 protected:
00626     int dim_[4];
00627 
00629     std::vector<T> data_;
00630 };
00631 
00632 }; // end namespace lsseg
00633 
00634 #endif // _IMAGE_H
00635 

Generated on Tue Nov 28 18:35:47 2006 for lsseg by  doxygen 1.4.7