Lens distortion correction division model 1p
 All Classes Files Functions Variables
image.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2011, AMI RESEARCH GROUP <lalvarez@dis.ulpgc.es>
3  * All rights reserved.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under, at your option, the terms of the GNU General Public
7  * License as published by the Free Software Foundation, either
8  * version 3 of the License, or (at your option) any later version, or
9  * the terms of the simplified BSD license.
10  *
11  * You should have received a copy of these licenses along this
12  * program. If not, see <http://www.gnu.org/licenses/> and
13  * <http://www.opensource.org/licenses/bsd-license.html>.
14  */
15 
16 
22 #ifndef image_H
23 #define image_H
24 
25 #include <vector>
26 #include <iostream>
27 #include <istream>
28 #include <ostream>
29 #include <typeinfo>
30 #include <string>
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 
35 #include "io_png/io_png.h"
36 
37 namespace ami {
38 
39 // ITERATOR ALIAS
40 
41 typedef std::vector<unsigned char>::iterator usIt;
42 typedef std::vector<int>::iterator iIt;
43 typedef std::vector<short>::iterator sIt;
44 typedef std::vector<float>::iterator fIt;
45 typedef std::vector<double>::iterator dIt;
46 
47 typedef std::vector<unsigned char>::const_iterator uscIt;
48 typedef std::vector<int>::const_iterator icIt;
49 typedef std::vector<short>::const_iterator scIt;
50 typedef std::vector<float>::const_iterator fcIt;
51 typedef std::vector<double>::const_iterator dcIt;
52 
53 }
54 
55 
56 namespace ami {
57 
59 
64 template <class T>
65 class image{
66  std::vector <T> image_ ;
68  int width_ ;
69  int height_ ;
70  int nChannels_ ;
71  std::vector <int> roi_ ;
74 
75  std::vector <float> origin_ ;
76  std::vector <float> pixel_size_ ;
77 
78  public:
79 
80  // CONSTRUCTOR - DESTRUCTOR METHODS
81  image();
82  image(const int width,const int height);
83  image(const T *vector,const int width,const int height,const int channels);
84  image(const int width,const int height, const int nChannels, const T &a);
85  image(const int width,const int height, const T &a, const T &b, const T &c);
86  image(const int width,const int height, const int nChannels);
87  image(std::string name );
88 
89 
90  image(const image<bool> &img_in, bool isbool);
91  image(const image<T> &img_in); //----------------------------------------
92  ~image();
93 
94  // CLASS ELEMENT ACCESS METHODS
95  inline std::vector <T> *get_image(){return &image_;}
96  inline int width() const {return width_;}
97  inline int height() const {return height_;}
98  inline int nChannels() const {return nChannels_;}
99  inline int size() const {return image_.size();}
100  inline T& operator[](const int &i);
101  inline T& operator()(const int &x,const int &y,const int &channel);
102  inline const T& operator[](const int &i) const;
103 
104  // BASIC OPERATION METHODS
105  int write(std::string name);
106  int write_bool(std::string name);
107  int read(std::string name);
108  image & operator=(const image &image2);
109  void clear();
110  void init(const int width,const int height, const int nChannels);
111  void set_nchannels(int nchannel1);
112  void set_size(int width,int height);
113  void imageMirrored();
114  image<T> const resize(const int width, const int height) const;
115  image<T> const resize_no_omp(const int width, const int height) const ;
116  image<T> const linear_transform(const double H[3][3]) const ;
117  image<T> const sampling() const ;
118 
119  // BASIC METHODS TO MANIPULATE SUBWINDOWS (ROI : REGION OF INTEREST )
120  std::vector <int> get_roi() const{return roi_;}
121  void roi_clear(){roi_.clear();}
122  void set_roi(const int x0,const int x1,const int y0,const int y1);
123  void set_roi(const int x0,const int x1,const int y0,const int y1,
124  const int c0,const int c1);
125  void set_roi(const std::vector<int> roi);
126  template <class U> void get_roi_image(image<U> &image2) const;
127  image<T> const get_roi_image(const std::vector <int> &roi2) const;
128  template <class U> void set_roi_image(const image<U> &image2);
129 
130  // BASIC METHODS TO MANIPULATE IMAGE WITH ITERATORS
131  typedef typename std::vector <T>::iterator iterator;
132  inline iterator begin() {return(image_.begin());}
133  inline iterator end() {return(image_.end());}
134 
135  //CHANGE CHANNEL
138  template <class U>
139  void hsv_to_rgb(image<U> &image);
140 
141  // ACCESS VECTOR BOOL
142  T get_value(const int x);
143  void set_value(const int x,T value);
144 
145  // HISTOGRAM
146  template<class U> void get_histogram(std::vector<U> &histograma,int channel);
147 
148 
149 };
150 
152 
157 template<class T>
159 {
160  // WE DEFINE SAMPLED IMAGE
161  image<T> sampled_img;
162  int width_s=width_/2;
163  int height_s=height_/2;
164  sampled_img=image<T>(width_s,height_s,nChannels_);
165  // WE FILTER THE IMAGE AND DOWNSAMPLING IT
166  for(int n=0;n<nChannels_;n++){
167  int n0=n*width_*height_;
168  int n_s=n*width_s*height_s;
169  int i_end=height_s-1;
170  #ifdef _OPENMP
171  #pragma omp parallel for shared(i_end,n0,n_s,sampled_img,width_s)
172  #endif
173  for(int i=1;i<i_end;i++){
174  int m0=n0+2*i*width_;
175  int m_s=n_s+i*width_s;
176  int j_end=width_s-1;
177  for(int j=1;j<j_end;j++){
178  int m=m0+2*j;
179  sampled_img[m_s+j]=0.25*image_[m]+0.125*(image_[m+1]+image_[m-1]+
180  image_[m+width_]+
181  image_[m-width_])+
182  0.0625*(image_[m+width_+1]+
183  image_[m+width_-1]+
184  image_[m-width_+1]+
185  image_[m-width_-1]);
186  }
187  }
188  }
189 
190  // WE SAMPLE IMAGE BORDER VERTICAL LINES
191  for(int n=0;n<nChannels_;n++){
192  int n0=n*width_*height_;
193  int n_s=n*width_s*height_s;
194  for(int i=0;i<height_s;i++){
195  int i0=2*i;
196  int m0=n0+i0*width_;
197  int m_s=n_s+i*width_s;
198  for(int j=0;j<width_s;j+=width_s-1){
199  int j0=2*j;
200  int m=m0+j0;
201  int mN=m,mS=m,mW=m,mE=m,mNE=m,mNW=m,mSE=m,mSW=m;
202  if(i0>0){ mS-=width_; mSE-=width_; mSW=m-width_; }
203  if(i0<(height_-1)){ mN+=width_; mNE+=width_; mNW+=width_; }
204  if(j0>0) {mW-=1; mNW-=1; mSW-=1;}
205  if(j0<(width_-1)){ mE+=1; mNE+=1; mSE+=1;}
206 
207  sampled_img[m_s+j]=0.25*image_[m]+0.125*(image_[mN]+image_[mS]+
208  image_[mW]+image_[mE])+
209  0.0625*(image_[mNW]+image_[mNE]+
210  image_[mSW]+image_[mSE]);
211  }
212  }
213  }
214 
215  // WE SAMPLE IMAGE BORDER HORIZONTAL LINES
216  for(int n=0;n<nChannels_;n++){
217  int n0=n*width_*height_;
218  int n_s=n*width_s*height_s;
219  for(int i=0;i<height_s;i+=height_s-1){
220  int i0=2*i;
221  int m0=n0+i0*width_;
222  int m_s=n_s+i*width_s;
223  for(int j=1,j_end=width_s-1;j<j_end;j++){
224  int j0=2*j;
225  int m=m0+j0;
226  int mN=m,mS=m,mW=m,mE=m,mNE=m,mNW=m,mSE=m,mSW=m;
227  if(i0>0){ mS-=width_; mSE-=width_; mSW=m-width_; }
228  if(i0<(height_-1)){ mN+=width_; mNE+=width_; mNW+=width_; }
229  if(j0>0) {mW-=1; mNW-=1; mSW-=1;}
230  if(j0<(width_-1)){ mE+=1; mNE+=1; mSE+=1;}
231 
232  sampled_img[m_s+j]=0.25*image_[m]+0.125*(image_[mN]+image_[mS]+
233  image_[mW]+image_[mE])+
234  0.0625*(image_[mNW]+image_[mNE]+
235  image_[mSW]+image_[mSE]);
236  }
237  }
238  }
239  return(sampled_img);
240 }
241 
243 
249 template <class T> template <class U>
250 void image<T>::get_histogram(std::vector<U> &histograma,
252  int channel)
253 {
254  if (nChannels_<channel)
255  return;
256  if (channel <= 0)
257  return;
258  int size=width_*height_;
259  histograma.resize(256);
260  #ifdef _OPENMP
261  #pragma omp parallel for
262  #endif
263  for(int i=0;i<256;i++) histograma[i]=0;
264 
265  int i_end=size*channel;
266  //#pragma omp parallel for default(none) shared(size, channel,i_end)
267  for(int i=size*(channel-1);i<i_end;i++)
268  histograma[image_[i]]++;
269 }
270 
272 
278 template <class T>
279 void image<T>::init(const int width,const int height, const int nChannels)
280 {
281  width_=width;
282  height_=height;
283  nChannels_=nChannels;
284  int size=width_*height_*nChannels_;
285  image_.resize(size);
286 }
287 
288 
290 
295 template <class T>
296 void image<T>::set_value(const int x,T value)
297 {
298  if (x<=width_*height_*nChannels_)
299  image_[x]=value;
300 }
301 
303 
308 template <class T>
309 T image<T>::get_value(const int x)
310 {
311  T value=0;
312  if (x<=width_*height_*nChannels_)
313  return image_[x];
314  return value;
315 }
316 
317 
319 
326 template <class T>
327 image<T>::image(const T *vector,const int width,const int height,
328  const int channels)
329 {
330  width_=width ;
331  height_=height;
332  nChannels_=channels;
333  int size=width_*height_*nChannels_;
334  image_.resize(size);
335  size=width_*height_;
336  #ifdef _OPENMP
337  #pragma omp parallel \
338  shared(size, vector)
339  #endif
340  for(int n=0;n<nChannels();n++){
341  int n2_=n*size;
342  #ifdef _OPENMP
343  #pragma omp for nowait
344  #endif
345  for(int i=0;i<size;i++)
346  {
347  image_[i+n2_]=vector[i+n2_];
348  }
349  }
350 
351 // for (int i=0;i< size;i++)
352 // image_[i]=vector[i];
353 }
355 
361 template <class T>
362 image<T>::image(const image<T> &img_in)
363 {
364  width_=img_in.width() ;
365  height_=img_in.height();
366  nChannels_=img_in.nChannels();
367  int size=width_*height_*nChannels_;
368  image_.resize(size);
369  size=width_*height_;
370  #ifdef _OPENMP
371  #pragma omp parallel \
372  shared(size)
373  #endif
374  for(int n=0;n<img_in.nChannels();n++){
375  int n2_=n*size;
376  #ifdef _OPENMP
377  #pragma omp for nowait
378  #endif
379  for(int i=0;i<size;i++)
380  {
381  image_[i+n2_]=img_in[i+n2_];
382  }
383  }
384 
385  if(img_in.get_roi().size() == 6){
386  roi_.resize(6);
387  roi_.at(0)=img_in.get_roi().at(0);
388  roi_.at(1)=img_in.get_roi().at(1);
389  roi_.at(2)=img_in.get_roi().at(2);
390  roi_.at(3)=img_in.get_roi().at(3);
391  roi_.at(4)=img_in.get_roi().at(4);
392  roi_.at(5)=img_in.get_roi().at(5);
393  }
394 }
395 
397 
403 template <class T> template<class U>
405 {
406  if (nChannels_!=3) return;
407  int size=width_*height_;
408  for (int i=0; i<size;i++)
409  {
410  U hue= image_[i];
411  U value= image_[i+size];
412  U saturation= image_[i+2*size];
413  U red=0,blue=0,green=0;
414 
415  if(hue<=43){
416  red=image[i]=value;
417  image[i+size*2]=value-saturation*value/255;
418  blue=image[i+size]=hue*(red-blue)/43+blue;
419  }
420  if(hue>43 && hue<=85){
421  green=image[i+size]=value;
422  blue=image[i+size*2]=value-saturation*value/255;
423  image[i]=-((hue-85)*(green-blue)/43-blue);
424  }
425  if(hue>85 && hue<=128){
426  red=image[i+size]=value;
427  green=image[i]=value-saturation*value/255;
428  image[i+size*2]=(hue-85)*(green-red)/43+red;
429  }
430  if(hue>128 && hue<=171){
431  blue=image[i+2*size]=value;
432  red=image[i]=value-saturation*value/255;
433  image[i+size]=((hue-171)*(blue-red)/43+red);
434  }
435  if(hue>171 && hue<=214){
436  blue=image[i+2*size]=value;
437  green=image[i+size]=value-saturation*value/255;
438  image[i]=-(hue-171)*(blue-green)/43+green;
439  }
440  if(hue>214){
441  red=image[i]=value;
442  green=image[i+size]=value-saturation*value/255;
443  image[i+2*size]=((hue-214)*(red-green)/43+green);
444  }
445  }
446 }
447 
449 
456 template <class T>
459 {
460  if (nChannels_!=3) return;
461  if (H.width()!=width_ || S.width()!=width_ || V.width()!=width_)return;
462 
463  int size_=width_*height_;
464  for (int i=0; i<size_;i++)
465  {
466  unsigned char red, green, blue;
467  red= (unsigned char) image_[i];
468  green=(unsigned char) image_[i+size_];
469  blue=(unsigned char) image_[i+2*size_];
470  unsigned char rgb_min,rgb_max;
471  rgb_min=rgb_max=red;
472  if(rgb_min>green) rgb_min=green;
473  if(rgb_min>blue) rgb_min=blue;
474  if(rgb_max<green) rgb_max=green;
475  if(rgb_max<blue) rgb_max=blue;
476  if(rgb_max == 0){
477  H[i]=0;
478  S[i]=0;
479  V[i]=0; //HSV
480  continue;
481  }
482  V[i]=(unsigned char) rgb_max; //V
483  S[i]=(unsigned char) ((int) 255*(rgb_max - rgb_min)/rgb_max); //S
484  if(S[i]==0){
485  H[i]=0; //Hl
486  continue;
487  }
488  //H
489  if(rgb_max==red){
490  H[i]=(unsigned char) ((int) 0+43*((int) green - blue)/
491  (rgb_max - rgb_min));
492  }
493  else if (rgb_max == green) {
494  H[i]= (unsigned char) ((int) 85+ 43*((int) blue-red)/(rgb_max - rgb_min));
495  }
496  else{
497  H[i]= (unsigned char) ((int) 171 + 43*((int) red - green)/
498  (rgb_max - rgb_min));
499  }
500  }
501 }
502 
504 
510 template <class T>
511 void image<T>::set_roi(const int x0,const int x1,const int y0,const int y1)
512 {
513  if(x0>x1 || y0>y1 || x0>width_ || y0>height_) return;
514 
515  roi_.resize(6);
516  roi_.at(0)=x0;
517  roi_.at(1)=x1>width_?width_:x1;
518  roi_.at(2)=y0;
519  roi_.at(3)=y1>height_?height_:y1;
520  roi_.at(4)=0;
521  roi_.at(5)=nChannels_;
522 
523 }
524 
526 
532 template <class T>
533 void image<T>::set_roi(const int x0,const int x1,const int y0,
534  const int y1,const int c0, const int c1)
535 {
536  if(x0>x1 || y0>y1 || x0>width_ || y0>height_ || c0>nChannels_ || c0>c1 )
537  return;
538 
539  roi_.resize(6);
540  roi_.at(0)=x0;
541  roi_.at(1)=x1>width_?width_:x1;
542  roi_.at(2)=y0;
543  roi_.at(3)=y1>height_?height_:y1;
544  roi_.at(4)=c0;
545  roi_.at(5)=c1;
546 
547 }
548 
550 
555 template <class T>
556 void image<T>::set_roi(const std::vector<int> roi){ roi_=roi; }
557 
559 
566 template <class T> template <class U> void image<T>::
567  set_roi_image(const image<U> &image2)
568 {
569 
570  if(roi_.size()<6) return;
571  int x0=roi_.at(0);
572  int x1=roi_.at(1);
573  int y0=roi_.at(2);
574  int y1=roi_.at(3);
575  int c0=roi_.at(4);
576  int c1=roi_.at(5);
577 
578  if( x1<=width_ && y1<=height_ && x0<=x1 && y0<=y1 && c1<=nChannels_ &&
579  c0<=c1){
580  int width=x1-x0;
581  int height=y1-y0;
582  int size=width*height;
583 
584  if(image2.width()!=width || image2.height()!=height ||
585  image2.nChannels()!=nChannels_) return;
586 
587  int i,j,n,i2,i2_,n2,n2_,size_=width_*height_;
588 
589  #ifdef _OPENMP
590  #pragma omp parallel \
591  shared(x0,x1,y0,y1,c0,c1,width,size,size_) \
592  private(n,i,j,n2,n2_,i2,i2_)
593  #endif
594  for(n=c0;n<c1;n++){
595  n2=(n-c0)*size;
596  n2_=n*size_;
597  #ifdef _OPENMP
598  #pragma omp for nowait
599  #endif
600  for(i=y0;i<y1;++i){
601  i2_=n2_+i*width_;
602  i2=n2+(i-y0)*width-x0;
603  for(j=x0;j<x1;++j){
604  image_[i2_+j]=(T) image2[i2+j] ;
605  }
606  }
607  }
608  return;
609  }
610 }
611 
613 
619 template <class T>
620 image<T> const image<T>::get_roi_image(const std::vector <int> &roi2) const
621 {
622  int x0,x1,y0,y1,c0,c1;
623 
624  // IF THERE IS NOT ROI DEFINED WE RETURN AN EMPTY IMAGE
625  if(roi2.size()<6){
626  return(image<T>());
627  }
628  else{
629  x0=roi2.at(0);
630  x1=roi2.at(1);
631  y0=roi2.at(2);
632  y1=roi2.at(3);
633  c0=roi2.at(4);
634  c1=roi2.at(5);
635  }
636 
637  int width,height;
638  if( x1<= width_ && y1<= height_ && x0<x1 && y0<y1 && c1<= nChannels_ &&
639  c0<c1){
640  width=x1-x0;
641  height=y1-y0;
642  }
643  else{
644  return(image<T>());
645  }
646 
647  image<T> image2(width,height,c1-c0);
648 
649  int size_=width_*height_;
650  int size=width*height;
651  int i,n,j,i2,i2_,n2,n2_;
652 
653  #ifdef _OPENMP
654  #pragma omp parallel \
655  shared(image2,x0,x1,y0,y1,c0,c1,width,size,size_) \
656  private(n,i,j,n2,n2_,i2,i2_)
657  #endif
658  for(n=c0;n<c1;n++){
659  n2=(n-c0)*size;
660  n2_=n*size_;
661  #ifdef _OPENMP
662  #pragma omp for nowait
663  #endif
664  for(i=y0;i<y1;++i){
665  i2_=n2_+i*width_;
666  i2=n2+(i-y0)*width-x0;
667  for(j=x0;j<x1;++j){
668  image2[i2+j]= image_[i2_+j] ;
669  }
670  }
671  }
672  return(image2);
673 }
674 
676 
683 template <class T> template <class U> void image<T>::
684  get_roi_image(image<U> &image2) const
685 {
686  int x0,x1,y0,y1,c0,c1;
687 
688  // IF THERE IS NOT ROI DEFINED WE TAKE THE WHOLE IMAGE
689  if(roi_.size()<6){
690  x0=0;
691  x1=width_;
692  y0=0;
693  y1=height_;
694  c0=0;
695  c1=nChannels_;
696  }
697  else{
698  x0=roi_.at(0);
699  x1=roi_.at(1);
700  y0=roi_.at(2);
701  y1=roi_.at(3);
702  c0=roi_.at(4);
703  c1=roi_.at(5);
704  }
705 
706  if( x1<= width_ && y1<= height_ && x0<=x1 && y0<=y1 && c1<= nChannels_ &&
707  c0<=c1){
708  int width=x1-x0;
709  int height=y1-y0;
710 
711  // WE ALLOCATE MEMORY IF NEEDED
712  if(image2.width()!=width || image2.height()!=height ||
713  image2.nChannels()!=nChannels_){
714  image2=image<U>(width,height,c1-c0);
715  }
716 
717  int size_=width_*height_;
718  int size=width*height;
719  int i,n,j,i2,i2_,n2,n2_;
720 
721  #ifdef _OPENMP
722  #pragma omp parallel \
723  shared(x0,x1,y0,y1,c0,c1,width,size,size_) \
724  private(n,i,j,n2,n2_,i2,i2_)
725  #endif
726  for(n=c0;n<c1;n++){
727  n2=(n-c0)*size;
728  n2_=n*size_;
729  #ifdef _OPENMP
730  #pragma omp for nowait
731  #endif
732  for(i=y0;i<y1;++i){
733  i2_=n2_+i*width_;
734  i2=n2+(i-y0)*width-x0;
735  for(j=x0;j<x1;++j){
736  image2[i2+j]=(U) image_[i2_+j] ;
737  }
738  }
739  }
740  return;
741  }
742 }
743 
745 
750 template <class T>
751 image<T> & image<T>::operator=(const image &image2)
752 {
753  if( width_==image2.width() && height_==image2.height() &&
754  nChannels_==3 && image2.nChannels()==1){
755  if(image_.size()!=(unsigned int) (3*width_*height_) ) image_.resize(3*width_*height_);
756  int size_=width_*height_;
757  int size_2=2*size_;
758  for(int m=0;m<size_;m++){
759  image_[m] = image2[m];
760  image_[m+size_] = image2[m];
761  image_[m+size_2] = image2[m];
762  }
763  return *this;
764  }
765 
766 
767  if( width_!=image2.width() || height_!=image2.height() ||
768  nChannels_!=image2.nChannels()){
769  width_=image2.width();
770  height_=image2.height();
771  nChannels_=image2.nChannels();
772  image_.resize(image2.size());
773  }
774 
775  int k,k_end=image2.size();
776  #ifdef _OPENMP
777  #pragma omp parallel for shared(k_end) private(k)
778  #endif
779  for(k=0;k<k_end;++k)
780  image_[k]= image2[k];
781 
782  return *this;
783 }
784 
786 
792 template <class T>
793 image<T> const image<T>::linear_transform(const double H[3][3]) const
794 {
795  image<T> image2(width_,height_,nChannels_,255);
796 
797  int width_1=width_-1;
798  int height_1=height_-1;
799  for(int n=0;n<nChannels_;n++){
800  int n0=n*width_*height_;
801  #ifdef _OPENMP
802  #pragma omp parallel for shared(H,image2,n,n0,width_1,height_1)
803  #endif
804  for(int i=0;i<height_;i++){
805  for(int j=0;j<width_;j++){
806  //WE COMPUTE THE HOMOGRAPHY TRANSFORMATION
807  double z0=H[2][0]*j+H[2][1]*i+H[2][2];
808  double x0=H[0][0]*j+H[0][1]*i+H[0][2];
809  double y0=H[1][0]*j+H[1][1]*i+H[1][2];
810  x0/=z0;
811  y0/=z0;
812  if(x0<0 || x0>=width_ || y0<0 || y0>=height_) continue;
813  int y0i=y0;
814  double dy0=y0-y0i;
815  double dy0_1=1-dy0;
816  int m0=n0+y0i*width_;
817  int m2=n0+i*width_;
818  int x0i=x0;
819  double dx0=x0-x0i;
820  double dx0_1=1-dx0;
821  if( x0i<width_1){
822  if( y0i<height_1){
823  image2[m2+j]=(T) (
824  dy0_1*dx0_1*image_[m0+x0i]+
825  dy0*dx0_1*image_[m0+width_+x0i]+
826  dy0*dx0*image_[m0+width_+x0i+1]+
827  dy0_1*dx0*image_[m0+x0i+1]
828  );
829  }
830  else{
831  image2[m2+j]=(T) (
832  dy0_1*dx0_1*image_[m0+x0i]+
833  dy0*dx0_1*image_[m0+x0i]+
834  dy0*dx0*image_[m0+x0i+1]+
835  dy0_1*dx0*image_[m0+x0i+1]
836  );
837  }
838  }
839  else{
840  if( y0i<height_1){
841  image2[m2+j]=(T) (
842  dy0_1*dx0_1*image_[m0+x0i]+
843  dy0*dx0_1*image_[m0+width_+x0i]+
844  dy0*dx0*image_[m0+width_+x0i]+
845  dy0_1*dx0*image_[m0+x0i]
846  );
847  }
848  else{
849  image2[m2+j]=(T) (
850  dy0_1*dx0_1*image_[m0+x0i]+
851  dy0*dx0_1*image_[m0+x0i]+
852  dy0*dx0*image_[m0+x0i]+
853  dy0_1*dx0*image_[m0+x0i]
854  );
855  }
856  }
857  }
858  }
859  }
860  return image2;
861 }
862 
864 
870 template <class T>
872 const int width ,
873 const int height ) const
874 {
875  printf("width=%d width_=%d height=%d height_=%d \n",width,width_,height,
876  height_);
877 
878  if(width==width_ && height==height_) return (*this);
879 
880  if(width<=width_/2 && height<=height_/2){
881  return(((*this).sampling()).resize(width,height));
882  }
883 
884  if(height<100) return(resize_no_omp(width,height));
885 
886  if(width==0 || height==0) return(image<T> ());
887 
888  image<T> image2(width,height,nChannels_);
889 
890 
891  // WE PROCESS IN THE CASE WE DO NOT NEED INTERPOLATION
892  if( width_>width && width_%width==0 && height_>height && height_%height==0 ){
893  int scale_x=width_/width;
894  int scale_y=height_/height;
895  for(int n=0;n<nChannels_;n++){
896  int n0=n*width_*height_;
897  int n2=n*width*height;
898  #ifdef _OPENMP
899  #pragma omp parallel for shared(image2,n,n0,n2,scale_x,scale_y)
900  #endif
901  for(int i=0;i<height;i++){
902  int m0=n0+scale_y*i*width_;
903  int m2=n2+i*width;
904  for(int j=0;j<width;j++){
905  image2[m2+j]=image_[m0+scale_x*j];
906  }
907  }
908  }
909  return image2;
910  }
911 
912  // WE PROCESS THE CASE WHERE WE NEED A INTERPOLATION PROCEDURE
913  double scale_x=(double) width_/width;
914  double scale_y=(double) height_/height;
915 
916  int width_1=width_-1;
917  int height_1=height_-1;
918  for(int n=0;n<nChannels_;n++){
919  int n0=n*width_*height_;
920  int n2=n*width*height;
921  #ifdef _OPENMP
922  #pragma omp parallel for shared(image2,n,n0,n2,scale_x,scale_y,width_1,\
923  height_1)
924  #endif
925  for(int i=0;i<height;i++){
926  double y0=scale_y*i;
927  int y0i=y0;
928  double dy0=y0-y0i;
929  double dy0_1=1-dy0;
930  int m0=n0+y0i*width_;
931  int m2=n2+i*width;
932  for(int j=0;j<width;j++){
933  double x0=scale_x*j;
934  int x0i=x0;
935  double dx0=x0-x0i;
936  double dx0_1=1-dx0;
937  if( x0i<width_1){
938  if( y0i<height_1){
939  image2[m2+j]=(T) (
940  dy0_1*dx0_1*image_[m0+x0i]+
941  dy0*dx0_1*image_[m0+width_+x0i]+
942  dy0*dx0*image_[m0+width_+x0i+1]+
943  dy0_1*dx0*image_[m0+x0i+1]
944  );
945  }
946  else{
947  image2[m2+j]=(T) (
948  dy0_1*dx0_1*image_[m0+x0i]+
949  dy0*dx0_1*image_[m0+x0i]+
950  dy0*dx0*image_[m0+x0i+1]+
951  dy0_1*dx0*image_[m0+x0i+1]
952  );
953  }
954  }
955  else{
956  if( y0i<height_1){
957  image2[m2+j]=(T) (
958  dy0_1*dx0_1*image_[m0+x0i]+
959  dy0*dx0_1*image_[m0+width_+x0i]+
960  dy0*dx0*image_[m0+width_+x0i]+
961  dy0_1*dx0*image_[m0+x0i]
962  );
963  }
964  else{
965  image2[m2+j]=(T) (
966  dy0_1*dx0_1*image_[m0+x0i]+
967  dy0*dx0_1*image_[m0+x0i]+
968  dy0*dx0*image_[m0+x0i]+
969  dy0_1*dx0*image_[m0+x0i]
970  );
971  }
972  }
973  }
974  }
975  }
976 
977  return image2;
978 }
979 
981 
987 template <class T>
988 image<T> const image<T>::resize_no_omp(const int width, const int height) const
989 {
990 
991  if(width==0 || height==0) return(image<T> ());
992 
993  if(width==width_ && height==height_) return (*this);
994 
995  if(width<=width_/2 && height<=height_/2)
996  return(((*this).sampling()).resize_no_omp(width,height));
997 
998  image<T> image2(width,height,nChannels_);
999 
1000 
1001  // WE PROCESS IN THE CASE WE DO NOT NEED INTERPOLATION
1002  if( width_>width && width_%width==0 && height_>height && height_%height==0 ){
1003  int scale_x=width_/width;
1004  int scale_y=height_/height;
1005  for(int n=0;n<nChannels_;n++){
1006  int n0=n*width_*height_;
1007  int n2=n*width*height;
1008  for(int i=0;i<height;i++){
1009  int m0=n0+scale_y*i*width_;
1010  int m2=n2+i*width;
1011  for(int j=0;j<width;j++){
1012  image2[m2+j]=image_[m0+scale_x*j];
1013  }
1014  }
1015  }
1016  return image2;
1017  }
1018 
1019  // WE PROCESS THE CASE WHERE WE NEED A INTERPOLATION PROCEDURE
1020  double scale_x=(double) width_/width;
1021  double scale_y=(double) height_/height;
1022 
1023  int width_1=width_-1;
1024  int height_1=height_-1;
1025  for(int n=0;n<nChannels_;n++){
1026  int n0=n*width_*height_;
1027  int n2=n*width*height;
1028  for(int i=0;i<height;i++){
1029  double y0=scale_y*i;
1030  int y0i=y0;
1031  double dy0=y0-y0i;
1032  double dy0_1=1-dy0;
1033  if(y0i>=height_) y0i=height_-1;
1034  int m0=n0+y0i*width_;
1035  int m2=n2+i*width;
1036  for(int j=0;j<width;j++){
1037  double x0=scale_x*j;
1038  int x0i=x0;
1039  double dx0=x0-x0i;
1040  double dx0_1=1-dx0;
1041  if( x0i<width_1){
1042  if( y0i<height_1){
1043  image2[m2+j]=(T) (
1044  dy0_1*dx0_1*image_[m0+x0i]+
1045  dy0*dx0_1*image_[m0+width_+x0i]+
1046  dy0*dx0*image_[m0+width_+x0i+1]+
1047  dy0_1*dx0*image_[m0+x0i+1]
1048  );
1049  }
1050  else{
1051  image2[m2+j]=(T) (
1052  dy0_1*dx0_1*image_[m0+x0i]+
1053  dy0*dx0_1*image_[m0+x0i]+
1054  dy0*dx0*image_[m0+x0i+1]+
1055  dy0_1*dx0*image_[m0+x0i+1]
1056  );
1057  }
1058  }
1059  else{
1060  if( y0i<height_1){
1061  image2[m2+j]=(T) (
1062  dy0_1*dx0_1*image_[m0+x0i]+
1063  dy0*dx0_1*image_[m0+width_+x0i]+
1064  dy0*dx0*image_[m0+width_+x0i]+
1065  dy0_1*dx0*image_[m0+x0i]
1066  );
1067  }
1068  else{
1069  image2[m2+j]=(T) (
1070  dy0_1*dx0_1*image_[m0+x0i]+
1071  dy0*dx0_1*image_[m0+x0i]+
1072  dy0*dx0*image_[m0+x0i]+
1073  dy0_1*dx0*image_[m0+x0i]
1074  );
1075  }
1076  }
1077  }
1078  }
1079  }
1080  return image2;
1081 }
1082 
1084 
1089 template <class T>
1090 int image<T>::write_bool(std::string name )
1091 {
1092  ami::image<unsigned char> aux(width_,height_,nChannels_,0);
1093  int size=width_*height_;
1094  #ifdef _OPENMP
1095  #pragma omp parallel for shared(size,aux)
1096  #endif
1097  for (int i=0; i<size;i++)
1098  {
1099  if (get_value(i))
1100  aux[i]=255;
1101  }
1102  return aux.write(name);
1103 }
1104 
1106 
1112 template <class T>
1113 int image<T>::write(std::string name )
1114 {
1115  int pos=name.find_last_of('.');
1116  int size_ = width_*height_;
1117  unsigned char *red = new unsigned char[size_],
1118  *green = new unsigned char[size_],
1119  *blue = new unsigned char[size_];
1120 
1121  if(pos == (int)std::string::npos) return -1;
1122 
1123  for(int i=0; i<size_; i++)
1124  {
1125  red[i] = image_[i];
1126  green[i] = image_[i+size_];
1127  blue[i] = image_[i+size_*2];
1128  }
1129 
1130  std::string extension=name.substr(pos+1);
1131  if( (extension == std::string("png")) || (extension == std::string("PNG")))
1132  {
1133  int output_value = ami_write_png(strdup(name.c_str()),red,green,blue,width_,
1134  height_);
1135  delete []red;
1136  delete []green;
1137  delete []blue;
1138  return output_value;
1139  }
1140  delete []red;
1141  delete []green;
1142  delete []blue;
1143  printf("WRITE::Unrecognized image format\n");
1144  return -1;
1145 }
1146 
1148 
1154 template <class T>
1155 T& image<T>::operator()(const int &x,const int &y,const int &channel){
1156  #ifdef IMAGE_DEBUG
1157  if((x+y*width_+channel*width_*height_)>=(image_.size())){
1158  printf("image<T>: bounds error vector access\n");
1159  printf("image size()=%d index to accces the vector =%d\n",
1160  image_.size(),x+y*width_+
1161  channel*width_*height_);
1162  int j; scanf("%d",&j);
1163  exit(0);
1164  }
1165  #endif
1166  return image_[x+y*width_+channel*width_*height_];
1167 }
1168 
1170 
1175 template <class T>
1176 const T& image<T>::operator[](const int &i) const
1177 {
1178  #ifdef IMAGE_DEBUG
1179  if(i>=(int)(image_.size())){
1180  printf("image<T>: bounds error vector access\n");
1181  printf("image size()=%d index to accces the vector =%d\n",
1182  (int)image_.size(),i);
1183  int j; scanf("%d",&j);
1184  exit(0);
1185  }
1186  #endif
1187  return image_[i];
1188 }
1189 
1191 
1196 template <class T>
1197 T& image<T>::operator[](const int &i)
1198 {
1199  #ifdef IMAGE_DEBUG
1200  if(i>=(int)(image_.size())){
1201  printf("image<T>: bounds error vector access\n");
1202  printf("image size()=%d index to accces the vector =%d\n",
1203  (int)image_.size(),i);
1204  int j; scanf("%d",&j);
1205  exit(0);
1206  }
1207  #endif
1208  return (image_.at(i));
1209 }
1210 
1212 
1217 template <class T>
1218 image<T>::image(int width,int height)
1219 {
1220  width_=width ;
1221  height_=height;
1222  nChannels_=1;
1223  image_.resize(width*height);
1224 }
1225 
1227 
1234 template <class T>
1235 image<T>::image(const int width,const int height, const T &a, const T &b,
1236  const T &c)
1237 {
1238  width_=width ;
1239  height_=height;
1240  nChannels_=3;
1241  int size=width_*height_;
1242  image_.resize(size*3);
1243  int i;
1244  #ifdef _OPENMP
1245  #pragma omp parallel for shared(size) private(i)
1246  #endif
1247  for(i=0;i<size;i++)
1248  image_.at(i)=a;
1249  #ifdef _OPENMP
1250  #pragma omp parallel for shared(size) private(i)
1251  #endif
1252  for(i=size;i<2*size;i++)
1253  image_.at(i)=b;
1254  #ifdef _OPENMP
1255  #pragma omp parallel for shared(size) private(i)
1256  #endif
1257  for(i=2*size;i<3*size;i++)
1258  image_.at(i)=c;
1259 }
1260 
1262 
1268 template <class T>
1269 image<T>::image(const int width,const int height,const int nChannels,const T &a)
1270 {
1271  width_=width ;
1272  height_=height;
1273  nChannels_=nChannels;
1274  int size=width_*height_*nChannels_;
1275  image_.resize(size);
1276  int i;
1277  #ifdef _OPENMP
1278  #pragma omp parallel for shared(size) private(i)
1279  #endif
1280  for(i=0;i<size;i++) image_.at(i)=a;
1281 }
1282 
1284 
1290 template <class T>
1291 image<T>::image(const int width,const int height, const int nChannels)
1292 {
1293  width_=width;
1294  height_=height;
1295  nChannels_=nChannels;
1296  int size=width_*height_*nChannels_;
1297  image_.resize(size);
1298 }
1299 
1301 
1306 template <class T>
1307 image<T>::image() : width_(0), height_(0), nChannels_(0) {}
1308 
1310 
1315 template <class T>
1317 
1319 
1325 template <class T>
1326 image<T>::image(std::string name )
1327 {
1328  read(name);
1329 }
1330 
1332 
1337 template <class T>
1339 {
1340  width_=0;
1341  height_=0;
1342  nChannels_=0;
1343  roi_clear();
1344  image_.clear();
1345 }
1346 
1348 
1354 template <class T>
1355 void image<T>::set_nchannels(int nchannel1)
1356 {
1357  nChannels_=nchannel1;
1358  image_.resize(nChannels_*width_*height_);
1359 }
1360 
1362 
1368 template <class T>
1369 void image<T>::set_size(int width,int height)
1370 {
1371  width_=width;
1372  height_=height;
1373  image_.resize(nChannels_*width_*height_);
1374 }
1375 
1377 
1382 template <class T>
1384 {
1385  //#pragma omp parallel for
1386  // all of channels
1387  for(int k=0; k<nChannels_;k++){
1388  // reading for columns
1389  for(int i=0; i< height_;i++){
1390  // reading for rows
1391  for(int j=0; j<(width_/2);j++){
1392  T aux = image_[(k*height_*width_)+i*width_+j];
1393  // swapping mirrored values in the row
1394  image_[(k*height_*width_)+i*width_+j] = image_[(k*height_*width_)+
1395  i*width_+width_-j-1];
1396  image_[(k*height_*width_)+i*width_+width_-j-1] = aux;
1397  }
1398  }
1399  }
1400  return;
1401 }
1402 
1404 
1410 template <class T>
1411 int image<T>::read (std::string name)
1412 {
1413  unsigned char *red, *green, *blue;
1414  int width, height;
1415  // READ THE IMAGE WITH IO_PNG
1416  int output_value = ami_read_png(strdup(name.c_str()),&red,&green,&blue,
1417  &width,&height);
1418  if(output_value!=0)
1419  {
1420  return output_value;
1421  }
1422  // INITIALIZE ATTRIBUTES AND COUNTERS
1423  width_ = width;
1424  height_ = height;
1425  nChannels_= 3;
1426  int size_ = width_ * height_;
1427  image_.resize(size_*nChannels_);
1428  // FILL THE IMAGE VECTOR WITH THE INFORMATION FROM IO_PNG
1429  for(int i=0; i<size_; i++)
1430  {
1431  image_[i] = (T)red[i];
1432  image_[i+size_] = (T)green[i];
1433  image_[i+size_*2] = (T)blue[i];
1434  }
1435  // FREE MEMORY
1436  free(red);
1437  free(green);
1438  free(blue);
1439  return 0;
1440 }
1441 
1442 }
1443 
1444 #endif
image< T > const linear_transform(const double H[3][3]) const
function to apply a linear transform given by an homography H to the image. H goes to the output imag...
Definition: image.h:793
void imageMirrored()
mirrored the image
Definition: image.h:1383
int read(std::string name)
Read an image selecting the library depend on the image format, returns 0 when it can't load the imag...
Definition: image.h:1411
image< T > const resize(const int width, const int height) const
Definition: image.h:871
void clear()
Function to put the image to 0 and clear its vectors.
Definition: image.h:1338
image()
basic destructor
Definition: image.h:1307
void init(const int width, const int height, const int nChannels)
initializes the image taking memory
Definition: image.h:279
image< T > const sampling() const
method to downsample the image by a factor of 2. We filter the image before downsampling ...
Definition: image.h:158
int write(std::string name)
Function to write an image to disk.
Definition: image.h:1113
void get_histogram(std::vector< U > &histograma, int channel)
Definition: image.h:250
void rgb_to_hsv(image< unsigned char > &H, image< unsigned char > &S, image< unsigned char > &V)
function to get colour model HSV from RGB (unsigned char version)
Definition: image.h:457
void set_value(const int x, T value)
set value to x position of vector
Definition: image.h:296
T & operator[](const int &i)
operator [] to acces image value
Definition: image.h:1197
void set_roi(const int x0, const int x1, const int y0, const int y1)
function to set a subwindow border
Definition: image.h:511
~image()
basic constructor
Definition: image.h:1316
void set_size(int width, int height)
Change the image dimensions.
Definition: image.h:1369
int write_bool(std::string name)
function to write to disk a 8/16 bit tif image from boolean image
Definition: image.h:1090
T & operator()(const int &x, const int &y, const int &channel)
operator () to acces image value
Definition: image.h:1155
void set_nchannels(int nchannel1)
Change number of channels.
Definition: image.h:1355
image & operator=(const image &image2)
operator = (equality of images of different size is not allowed )
Definition: image.h:751
T get_value(const int x)
get value to x position of vector
Definition: image.h:309
Class to store multiChannel images and basic methods.
Definition: image.h:65