Structural deformable models
Image.h
Go to the documentation of this file.
1 /* -*- C++ -*- */
2 // Image.h: Schnittstelle für die Klasse Image.
3 //
5 #ifndef _IMAGE_H_
6 #define _IMAGE_H_
7 
8 #include <iostream>
9 #include <fstream>
10 #include <vector>
11 #include <string>
12 #include "common.h"
13 #include "mathutil.h"
14 
15 template <class T>
16 class Image : public std::vector<T>
17 {
18 public:
19  typedef typename std::vector<T>::iterator iterator;
20  typedef typename std::vector<T>::const_iterator const_iterator;
21 
22  Image();
23  Image(int sx, int sy)
24  : std::vector<T>(sx*sy), sizeX(sx), sizeY(sy) {};
25  Image(int sx, int sy, const T &value)
26  : std::vector<T>(sx*sy, value), sizeX(sx), sizeY(sy) {};
27  Image(const Image<T> & rhs);
28  virtual ~Image() {};
29  void freeImage();
30 
31  void setSize(int nx, int ny);
32  void setSize(int nx, int ny, const T &value);
33 
34  template<class S>
35  bool sameSize(const Image<S>& rhs)
36  { return rhs.getSizeX()==sizeX && rhs.getSizeY()==sizeY; }
37 
38 
39  const T *getData() const {return &(*std::vector<T>::begin());}
40  T *getData() {return &(*std::vector<T>::begin());}
41 
42  int getSizeX() const { return sizeX;}
43  int getSizeY() const { return sizeY;}
44  int getSize() const { return std::vector<T>::size();}
45 
46  Image<T>& operator=(const Image<T>& rhs);
47  Image<T>& operator=(const T& rhs);
48  Image<T>& copy(const Image<T>& rhs);
49  Image<T>& copy(const T* rhs);
50 
51  int getIndex(int x, int y) const { return sizeX*y+x; }
52  int getBoundedIndex(int x, int y) const {
53  if((dword)x < (dword)sizeX && (dword)y < (dword)sizeY)
54  return sizeX*y+x;
55  else
56  return -1;
57  }
58 
59  const T getPixel(int x, int y) const {
60  return std::vector<T>::at(getIndex(x,y));
61  }
62  void setPixel(int x, int y, const T &value) {
63  std::vector<T>::at(getIndex(x,y)) = value;
64  }
66  const T findMax() const;
68  const T findMin() const;
72  const T norm() const;
73  double sum() const;
74  Image<T>& operator*=(const T& v);
75  Image<T>& operator/=(const T& v);
76  Image<T>& operator+=(const T& v);
77  Image<T>& operator-=(const T& v);
78  Image<T>& operator*=(const Image<T>& rhs);
79  Image<T>& operator/=(const Image<T>& rhs);
80  Image<T>& operator+=(const Image<T>& rhs);
81  Image<T>& operator-=(const Image<T>& rhs);
82 
83  void addLine(int x0, int y0, int x1, int y1, const T& value);
84 
85  Image<T>& unsetNAN(double val=0);
86  Image<T>& threshold(const T& th, double binarize=0);
87  Image<T>& findMaxima(int env=3);
88 
89 //template template member functions (still) have to be in the class definition
90  template <class S>
92  {
93  setSize(rhs.getSizeX(),rhs.getSizeY());
94  const S* sd = rhs.getData();
95  T* dd = getData();
96  for(int i=getSize();i>0;i--,dd++,sd++)
97  *dd = T(*sd);
98  return *this;
99  }
100 
101  const Image<T> mirror(bool horiz=true, bool vert=true) const
102  {
103  Image<T> dimg(getSizeX(),getSizeY());
104  int i,j;
105  for(j=0;j<getSizeY();j++)
106  for(i=0;i<getSizeX();i++)
107  {
108  int si = horiz ? getSizeX()-i-1 : i;
109  int sj = vert ? getSizeY()-j-1 : j;
110  dimg.setPixel(i,j,getPixel(si,sj));
111  }
112  return dimg;
113  }
114 
115  template <class S>
116  const Image<T> convolve(const Image<S>& kernel) const
117  {
118  Image<T> dst(sizeX,sizeY);
119  int ksx = kernel.getSizeX()/2;
120  int ksy = kernel.getSizeY()/2;
121  int endX = sizeX-ksx;
122  int endY = sizeY-ksy;
123  //int offset = ksy*sizeX+ksx;
124  int winskip = sizeX-kernel.getSizeX();
125  T* dstdat = dst.getData() + ksx + (ksy*sizeX);
126  const T* srcdat = getData();
127  for(int i=ksy;i<endY;i++)
128  {
129  for(int j=ksx;j<endX;j++,dstdat++,srcdat++)
130  {
131  S sum = 0;
132  const S *kdat = kernel.getData();
133  const T *sdat = srcdat;
134  for(int l=0;l<kernel.getSizeY();l++)
135  {
136  for(int k=0;k<kernel.getSizeX();k++, kdat++, sdat++)
137  {
138  sum += *kdat**sdat;
139  }
140  sdat += winskip;
141  }
142  *dstdat = T(sum);
143  }
144  dstdat+=ksx*2;
145  srcdat+=ksx*2;
146  }
147  return dst;
148  }
149 
150  Image<T>& interleave(const std::vector< Image<T> >& img,
151  dword ncomp=0)
152  {
153  if(!ncomp) ncomp = img.size();
154  const int comp = img.size()>ncomp ? ncomp : img.size();
155  const int size = img[0].size();
156  setSize(img[0].getSizeX()*ncomp, img[0].getSizeY());
158  for(int a=0; a<comp; a++) bi[a] = img[a].begin();
159  T *cv = getData();
160  const int cvinc = ncomp-comp;
161  for(int i=0; i<size; i++) {
162  for(int a=0; a<comp; a++) {
163  *(cv++) = *bi[a];
164  bi[a]++;
165  }
166  cv += cvinc;
167  }
168  return *this;
169  }
170 
171  Image<T> scaleBy(float s) { return scaleBy(s,s); }
172  Image<T> scaleBy(float sx, float sy)
173  {
174  //can only scale down by integral numbers
175  int stepx = (int)round(1/sx); if(stepx<=0) stepx=1;
176  int stepy = (int)round(1/sy); if(stepy<=0) stepy=1;
177  Image<T> nimg(getSizeX()/stepx, getSizeY()/stepy);
178  Image<T>::const_iterator src = std::vector<T>::begin();
179  Image<T>::iterator dst = nimg.begin();
180  for(int j=0; j<nimg.sizeY; j++) {
181  Image<T>::const_iterator linebegin = src;
182  for(int i=0; i<nimg.sizeX; i++, dst++, src+=stepx) {
183  *dst = *src;
184  }
185  src = linebegin+(stepy*sizeX);
186  }
187  return nimg;
188  }
189 
191  bool initialized() const { return !std::vector<T>::empty(); }
192 
193  friend std::ostream& operator<<(std::ostream& os, const Image<T>& rhs) {
194  os << rhs.sizeX << " " << rhs.sizeY << std::endl;
195  int xc = rhs.sizeX;
196  for(const_iterator pnt = rhs.begin(); pnt != rhs.end(); pnt++) {
197  os<<*pnt;
198  if(--xc == 0) {
199  std::cout << std::endl;
200  xc = rhs.sizeX;
201  } else std::cout << " ";
202  }
203  return os;
204  }
205 
206  bool writePPM(const std::string& fname) const {
207  std::fstream ofile(fname.c_str(), std::ios::binary|std::ios::out);
208  return writePPMstream(ofile);
209  }
210 
211  bool writePPMstream(std::ostream& os) const{
212  if(!os) return false;
213  os << sizeX << " " << sizeY << std::endl;
214  os.write((const char*)&std::vector<T>::front(), sizeX*sizeY);
215  return true;
216  }
217 
218  bool readPPM(const std::string& fname) {
219  std::fstream ifile(fname.c_str(), std::ios::binary|std::ios::in);
220  return readPPMstream(ifile);
221  }
222 
223  bool readPPMstream(std::istream& is) {
224  if(!is) return false;
225  is >> sizeX;
226  is >> sizeY;
227  std::vector<T>::resize(sizeX*sizeY);
228  is.read((char*)&std::vector<T>::front(), sizeX*sizeY);
229  return true;
230  }
231 
232  friend std::istream& operator>>(std::istream& is, Image<T>& rhs) {
233  is >> rhs.sizeX;
234  is >> rhs.sizeY;
235  rhs.resize(rhs.sizeX*rhs.sizeY);
236  for(iterator pnt = rhs.begin(); is && pnt != rhs.end(); pnt++)
237  is>>*pnt;
238  return is;
239  }
240 
241  void insert(const Image<T> &ii, const int x = 0, const int y = 0);
242  Image<T>& zeroPad(int brd, const T& col=0, bool smoothbrd=false);
243 
244 protected:
245  int sizeX, sizeY;
246 };
247 
248 template<class T>
250 {
251  sizeX = sizeY = 0;
252 }
253 
254 template<class T>
255 Image<T>::Image(const Image & rhs)
256 {
257  operator=(rhs);
258 }
259 
260 template<class T>
262 {
263  setSize(0);
264  sizeX = sizeY = 0;
265 }
266 
267 template<class T>
268 void Image<T>::setSize(int nx, int ny)
269 {
270  if(!std::vector<T>::empty() && nx==sizeX && ny==sizeY) return;
271  sizeX = nx;
272  sizeY = ny;
273  std::vector<T>::clear();
274  if(nx*ny) std::vector<T>::resize(nx*ny);
275 }
276 
277 template<class T>
278 void Image<T>::setSize(int nx, int ny, const T &value)
279 {
280  sizeX = nx;
281  sizeY = ny;
282  std::vector<T>::clear();
283  if(nx*ny) resize(nx*ny, value);
284 }
285 
286 template<class T>
288 {
289  if(&rhs == this) return *this;
290  std::vector<T>::operator=(rhs);
291  sizeX = rhs.getSizeX();
292  sizeY = rhs.getSizeY();
293  return *this;
294 }
295 
296 template<class T>
297 Image<T>& Image<T>::copy(const T* rhs)
298 {
299  for(iterator pnt = std::vector<T>::begin(); pnt != std::vector<T>::end(); pnt++, rhs++)
300  *pnt = *rhs;
301  return *this;
302 }
303 
304 template<class T>
306 {
307  return copy(rhs);
308 }
309 
310 template<class T>
312 {
313  if(!std::vector<T>::empty() && sizeX>0 && sizeY>0)
314  {
315  for(iterator pnt = std::vector<T>::begin(); pnt != std::vector<T>::end(); pnt++)
316  *pnt = rhs;
317  }
318  return *this;
319 }
320 
321 template<class T>
322 const T Image<T>::findMax() const
323 {
324  if(std::vector<T>::empty()) return 0;
325  const T* pnt = getData();
326  T max = *pnt;
327  for(int i=getSize(); i>0; i--, pnt++)
328  if(*pnt>max) max = *pnt;
329  return max;
330 }
331 
332 template<class T>
333 const T Image<T>::findMin() const
334 {
335  if(std::vector<T>::empty()) return 0;
336  const T* pnt = getData();
337  T min = *pnt;
338  for(int i=getSize(); i>0; i--, pnt++)
339  if(*pnt<min) min = *pnt;
340  return min;
341 }
342 
343 template<class T>
344 const T Image<T>::norm() const
345 {
346  double sum=0;
347  const T* pnt = getData();
348  for(int i=getSize(); i>0; i--, pnt++)
349  sum += *pnt**pnt;
350  sum = T(sqrt(sum));
351  return T(sum);
352 }
353 
354 template<class T>
355 double Image<T>::sum() const
356 {
357  double sum=0;
358  const T* pnt = getData();
359  for(int i=getSize(); i>0; i--, pnt++)
360  sum += (double)*pnt;
361  return sum;
362 }
363 
364 template<class T>
366 {
367  T* pnt = getData();
368  for(int i=getSize(); i>0; i--, pnt++)
369  *pnt *= v;
370  return *this;
371 }
372 
373 template<class T>
375 {
376  T* pnt = getData();
377  for(int i=getSize(); i>0; i--, pnt++)
378  *pnt /= v;
379  return *this;
380 }
381 
382 template<class T>
384 {
385  T* pnt = getData();
386  for(int i=getSize(); i>0; i--, pnt++)
387  *pnt += v;
388  return *this;
389 }
390 
391 template<class T>
393 {
394  T* pnt = getData();
395  for(int i=getSize(); i>0; i--, pnt++)
396  *pnt -= v;
397  return *this;
398 }
399 
400 template<class T>
402 {
403  T* pnt = getData();
404  const T* rval = rhs.getData();
405  for(int i=getSize(); i>0; i--, pnt++, rval++)
406  *pnt *= *rval;
407  return *this;
408 }
409 
410 template<class T>
412 {
413  T* pnt = getData();
414  const T* rval = rhs.getData();
415  for(int i=getSize(); i>0; i--, pnt++)
416  *pnt /= *rval;
417  return *this;
418 }
419 
420 template<class T>
422 {
423  T* pnt = getData();
424  const T* rval = rhs.getData();
425  for(int i=getSize(); i>0; i--, pnt++)
426  *pnt += *rval;
427  return *this;
428 }
429 
430 template<class T>
432 {
433  T* pnt = getData();
434  const T* rval = rhs.getData();
435  for(int i=getSize(); i>0; i--, pnt++)
436  *pnt -= *rval;
437  return *this;
438 }
439 
440 template<class T>
441 void Image<T>::addLine(int x0, int y0, int x1, int y1, const T& value)
442 {
443  if(std::vector<T>::empty()) return;
444  //left point first?
445  if(x0>x1) {
446  x0 += x1; x1 = x0-x1; x0 -= x1; //who needs a dummy?
447  y0 += y1; y1 = y0-y1; y0 -= y1;
448  }
449  T* dpos = getData() + x0 + y0*sizeX;
450  int pincY = sizeX;
451  int xinc = 1;
452  int yinc = 1;
453  int dy = y1 - y0;
454  int dx = x1 - x0;
455 
456  int nx = dy; //normal (negative reciprocal direction)
457  int ny = -dx;
458 
459  int dir = dx>absint(dy) ? 1 : -1;
460  if(dy<0)
461  {
462  yinc=-1;
463  pincY = -pincY;
464  }
465 
466  if(dir==1)
467  {
468  int diagInc = 2*(nx+ny*yinc);
469  int axisInc = 2*nx;
470 
471  int x = x0;
472  int y = y0;
473 
474  int d = 2*nx + ny*yinc;
475  while (x <= x1)
476  {
477  *dpos += value;
478  if (d*yinc >= 0) { // move diagonally
479  y += yinc;
480  dpos += pincY;
481  d += diagInc;
482  }
483  else d += axisInc;
484  x += xinc;
485  dpos += xinc;
486  }
487  } else {
488  int diagInc = 2*(nx+ny*yinc);
489  int axisInc = 2*ny*yinc;
490 
491  int x = x0;
492  int y = y0;
493  int d = 2*ny*yinc + nx;
494  int cnt = absint(dy);
495  while (cnt--)
496  {
497  *dpos += value;
498  if (d*yinc <= 0) { // move diagonally
499  x += xinc;
500  dpos += xinc;
501  d += diagInc;
502  }
503  else d += axisInc;
504  y += yinc;
505  dpos += pincY;
506  }
507  *dpos += value;
508  }
509 }
510 
511 template <class T>
512 Image<T>& Image<T>::threshold(const T& th, double binarize)
513 {
514  bool bin = (binarize>0);
515  T* pnt = getData();
516  for(int i=getSize(); i>0; i--, pnt++)
517  if(*pnt<th) *pnt = 0;
518  else if (bin) *pnt = T(binarize);
519  return *this;
520 }
521 
522 template <class T>
524 {
525  T* pnt = getData();
526  for(int i=getSize(); i>0; i--, pnt++)
527  if(isnan(*pnt)) *pnt = val;
528  return *this;
529 }
530 
531 template <class T>
533 {
534  env = (env/2)*2 + 1;
535  int ksx = env/2;
536  int ksy = env/2;
537  int endX = sizeX-ksx;
538  int endY = sizeY-ksy;
539  int offset = ksy*sizeX+ksx;
540  int winskip = sizeX-env;
541  T* srcdat = getData();
542  T* maxpnt = getData()+offset;
543  for(int i=ksy;i<endY;i++)
544  {
545  for(int j=ksx;j<endX;j++,srcdat++, maxpnt++)
546  {
547  bool ismax = true;
548  const T *sdat = srcdat;
549  maxpnt = srcdat+offset;
550  for(int l=0;l<env && ismax; l++)
551  {
552  for(int k=0;k<env && ismax; k++, sdat++)
553  {
554  if(*maxpnt<=*sdat &&
555  maxpnt != sdat) ismax=false;
556  }
557  sdat += winskip; //jump to next line
558  }
559  if(!ismax) *maxpnt = 0;
560  }
561  maxpnt+=ksx*2;
562  srcdat+=ksx*2;
563  }
564  return *this;
565 }
566 
567 template <class T>
568 void Image<T>::insert(const Image<T> &ii, const int x, const int y)
569 {
570  const int iwidth = std::min(getSizeX() - x, ii.getSizeX());
571  const int iheight = std::min(getSizeY() - y, ii.getSizeY());
572  if(iwidth>0 && iheight>0)
573  {
574  for(int j=0; j<iheight; j++) {
575  const_iterator src = ii.begin()+ii.getIndex(0,j);
576  iterator dst = std::vector<T>::begin()+getIndex(x,j+y);
577  for(int i=0; i<iwidth; i++, src++, dst++)
578  {
579  *dst = *src;
580  }
581  }
582  }
583 }
584 
585 template<class T>
586 Image<T>& Image<T>::zeroPad(int brd, const T& col, bool smoothbrd)
587 {
588  if(brd>0)
589  {
590  Image<T> ni(getSizeX()+2*brd, getSizeY()+2*brd, col);
591  ni.insert(*this, brd, brd);
592  if(smoothbrd) {
593  //smooth the inner image and blit again
594  Image<float> flt(2*brd,2*brd, 1.0f/(4*brd*brd));
595  ni.convolve(flt);
596  ni.insert(*this, brd, brd);
597  }
598  *this = ni;
599  }
600  return *this;
601 }
602 
603 #endif
bool writePPM(const std::string &fname) const
Definition: Image.h:206
int getBoundedIndex(int x, int y) const
Definition: Image.h:52
int getSize() const
Definition: Image.h:44
Image(int sx, int sy)
Definition: Image.h:23
void freeImage()
Definition: Image.h:261
bool readPPM(const std::string &fname)
Definition: Image.h:218
bool readPPMstream(std::istream &is)
Definition: Image.h:223
const Image< T > mirror(bool horiz=true, bool vert=true) const
Definition: Image.h:101
std::vector< T >::iterator iterator
Definition: Image.h:19
std::vector< T >::const_iterator const_iterator
Definition: Image.h:20
Image< T > & operator-=(const T &v)
Definition: Image.h:392
Image< T > & interleave(const std::vector< Image< T > > &img, dword ncomp=0)
Definition: Image.h:150
Image< T > & operator=(const Image< T > &rhs)
Definition: Image.h:305
STL namespace.
int getSizeX() const
Definition: Image.h:42
int sizeX
Definition: Image.h:245
const T findMax() const
calculate maximum
Definition: Image.h:322
Image< T > & operator*=(const T &v)
Definition: Image.h:365
const T findMin() const
calculate minimum
Definition: Image.h:333
const T getPixel(int x, int y) const
Definition: Image.h:59
Image< T > & zeroPad(int brd, const T &col=0, bool smoothbrd=false)
Definition: Image.h:586
bool initialized() const
Definition: Image.h:191
Image< T > & convertFrom(const Image< S > &rhs)
Definition: Image.h:91
Image< T > & operator/=(const T &v)
Definition: Image.h:374
Image< T > & operator+=(const T &v)
Definition: Image.h:383
Image(int sx, int sy, const T &value)
Definition: Image.h:25
virtual ~Image()
Definition: Image.h:28
friend std::istream & operator>>(std::istream &is, Image< T > &rhs)
Definition: Image.h:232
double sum() const
Definition: Image.h:355
bool writePPMstream(std::ostream &os) const
Definition: Image.h:211
Image< T > scaleBy(float s)
Definition: Image.h:171
const T norm() const
Definition: Image.h:344
int absint(int v)
Definition: mathutil.h:21
unsigned long dword
Definition: simpletypes.h:6
T * getData()
Definition: Image.h:40
Image< T > & threshold(const T &th, double binarize=0)
Definition: Image.h:512
Definition: Image.h:16
void setSize(int nx, int ny)
Definition: Image.h:268
void insert(const Image< T > &ii, const int x=0, const int y=0)
Definition: Image.h:568
int sizeY
Definition: Image.h:245
const T * getData() const
Definition: Image.h:39
Image()
Definition: Image.h:249
Image< T > & findMaxima(int env=3)
Definition: Image.h:532
int getIndex(int x, int y) const
Definition: Image.h:51
bool sameSize(const Image< S > &rhs)
Definition: Image.h:35
Image< T > scaleBy(float sx, float sy)
Definition: Image.h:172
void setPixel(int x, int y, const T &value)
Definition: Image.h:62
void addLine(int x0, int y0, int x1, int y1, const T &value)
Definition: Image.h:441
Image< T > & copy(const Image< T > &rhs)
Definition: Image.h:287
const Image< T > convolve(const Image< S > &kernel) const
Definition: Image.h:116
Image< T > & unsetNAN(double val=0)
Definition: Image.h:523
DMatrix< T > & sqrt(DMatrix< T > &mat)
Definition: DMatrixUtil.h:81
int getSizeY() const
Definition: Image.h:43