00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
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());
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
00505
00506
00507
00508
00509 }
00510
00515 void write(std::ostream& os, bool binary=true) const
00516 {
00517 if (binary) {
00518
00519
00520
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
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
00557
00558
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
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 };
00633
00634 #endif // _IMAGE_H
00635