Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExampleJointHistogram.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 /**
26  * @example ExampleJointHistrogram.cpp
27  @relates Image, HistogramImage, JointHistogram
28  @brief Usage for the JointHistogram class and creation of
29  Normalized Mutual Information
30  @ingroup g_examples
31  @author ischiller
32 */
33 
34 
35 #include <Base/Image/Image.hh>
36 #include <Base/Image/ImageIO.hh>
37 #include <Base/Image/ImageConvert.hh>
38 #include <Base/ImageUtils/ImageDraw.hh>
39 #include <Base/Math/Random.hh>
40 #include <Image/JointHistogram.hh>
41 #include <Image/HistogramImage.hh>
42 #include <iostream>
43 #include <Filter/GradientGauss.hh>
44 #include <Filter/GradientSimple.hh>
45 
46 using namespace BIAS;
47 using namespace std;
48 
49 int main(int argc, char *argv[])
50 {
51  int res = 0;
52  Image<unsigned char> image1, image2;
53  Image<float> gauss1, gauss2, gauss1X, gauss1Y,gauss2X,gauss2Y;
54 
57 
58  if (argc <5) {
59  cerr<< argv[0] <<" <reference image> <output> <usegradient> filenames"<<endl;
60  exit(1);
61  }
62 
63  //if ((res=ImageIO::Load(argv[1], image1)) != 0){
64  if ((res=ImageIO::Load(argv[1], image1)) != 0){
65  cerr << "error loading file " << argv[1] << " " << res << endl;
66  exit (-1);
67  }
68 
69  if (image1.GetChannelCount() != 1){
70  cerr << "wrong channel count in image"<< endl;
72 
73  }
74  int numberOfImages = argc-1;
75  std::vector<string> images;
76  float nmi=0.0;
77  float maxNMI=-100.0;
78  float minJointEntropy=100000.0;
79  string minJointEntropyImageName;
80  string maxNMIImageName;
81  //go over all images and calculate nmi
82  for(int i=4;i<=numberOfImages;i++){
83 
84  //if ((res=ImageIO::Load(argv[i], image2)) != 0){
85  if ((res=ImageIO::Load(argv[i], image2)) != 0){
86  cerr << "error loading file " << argv[1] << " " << res << endl;
87  exit (-1);
88  }
89  else
90  cout<<"\nUsing image: "<<argv[i]<<" for comparison"<<endl;
91 
92  if (image2.GetChannelCount() != 1){
93  cerr << "wrong channel count in image"<< endl;
95  }
96 
97  if(atoi(argv[3]) > 0){
98  gradientGenerator.Filter(image1, gauss1X, gauss1Y, gauss1);
99  gradientGenerator.Filter(image2, gauss2X, gauss2Y, gauss2);
100  if(atoi(argv[3]) == 2){
101  cout<<"Using angle directions"<<endl;
102  float** idaX1 = gauss1X.GetImageDataArray();
103  float** idaY1 = gauss1Y.GetImageDataArray();
104  float** dst1 = gauss1.GetImageDataArray();
105  float** idaX2 = gauss2X.GetImageDataArray();
106  float** idaY2 = gauss2Y.GetImageDataArray();
107  float** dst2 = gauss2.GetImageDataArray();
108  double angle =0.0;
109  double gradientThreshold = 30;
110  for(unsigned int x=0;x<image1.GetWidth();x++){
111  for(unsigned int y=0;y<image1.GetHeight();y++){
112  double YGradValue = idaY1[y][x];
113  double XGradValue = idaX1[y][x];
114  //calulate the angle of the gradient
115  angle = atan2(YGradValue,XGradValue);
116 
117  // // bring angle to [0..2pi]
118  while (angle<0.0f) angle += 2.0f * (float)M_PI;
119  if (angle>float(2.0f*M_PI)) angle = 2.0f * (float)M_PI;
120  angle = (angle*180)/M_PI;
121 
122  if(dst1[y][x] >= gradientThreshold)
123  dst1[y][x] = (float)angle;
124  else
125  dst1[y][x] = (float)0;
126 
127  //second image
128  YGradValue = idaY2[y][x];
129  XGradValue = idaX2[y][x];
130  angle = atan2(YGradValue,XGradValue);
131 
132  // bring angle to [0..2pi]
133  while (angle<0.0f) angle += 2.0f * (float)M_PI;
134  if (angle>float(2.0f*M_PI)) angle = 2.0f * (float)M_PI;
135 
136  angle = (angle*180)/M_PI;
137  if(dst2[y][x] >= gradientThreshold)
138  dst2[y][x] = (float)angle;
139  else
140  dst2[y][x] = (float)0;
141  }//end for
142  }// end for
143  }
144  }
145  else
146  {
147  BIAS::ImageConvert::ConvertST(image1,gauss1, gauss1.GetStorageType());
148  BIAS::ImageConvert::ConvertST(image2,gauss2, gauss2.GetStorageType());
149  }
150 
151  jhist.Compute(gauss1,gauss2);
152  std::string filename;
153  filename = argv[2];
154  filename +="-";
155  filename +=argv[i];
156 
157  BIAS::Image<float> tmpImage;
158  jhist.Draw(tmpImage);
159 
160  //BIAS::ImageIO::Save(filename.c_str(),tmpImage);
161  BIAS::ImageIO::Save(filename.c_str(),tmpImage);
162 
163  float entropy = jhist.CalcShannonEntropy();
164  cout<<"Shannon Joint Entropy :"<<entropy<<endl;
165  if(entropy < minJointEntropy)
166  {
167  minJointEntropy = entropy;
168  minJointEntropyImageName = argv[i];
169  BIAS::Image<float> tmpImage;
170  jhist.Draw(tmpImage);
171  //BIAS::ImageIO::Save(argv[2],tmpImage);
172  BIAS::ImageIO::Save(argv[2],tmpImage);
173  }
174 
175  HistogramImage hist;
176  hist.InitHist(256,2);
177 
178  hist.AddHist(gauss1,0);
179  hist.AddHist(gauss2,1);
180 
181  float entropy0 = hist.CalcShannonEntropy(0);
182  float entropy1 = hist.CalcShannonEntropy(1);
183  cout<<"Shannon Entropies :"<<entropy0<<","<<entropy1<<endl;
184 
185  hist.Draw();
186  // BIAS::ImageIO::Save("hist.mip",hist);
187 
188  nmi = (entropy0 + entropy1)/entropy;
189  if(nmi > maxNMI)
190  {
191  maxNMI = nmi;
192  maxNMIImageName = argv[i];
193  }
194 
195  cout<<"Normalized Mutual Information: "<<nmi<<endl;
196 
197  }// end for
198 
199  cout<<"\n\n***************************************************************\n";
200  cout<<"******************* Final results: *************************** \n";
201  cout<<"ImageName with maximum NMI: "<<maxNMIImageName<<endl;
202  cout<<"MaxNMI : "<<maxNMI<<endl;
203  cout<<"ImageName with min JointEntropy: "<<minJointEntropyImageName<<endl;
204  cout<<"Min Joint Entropy : "<<minJointEntropy<<endl;
205  cout<<"***************************************************************\n";
206  return 0;
207 }
208 
float CalcShannonEntropy(unsigned int hist=0)
calculates the Shannon Entropy and treats entries in HistogramImage as probabilities ...
int InitHist(unsigned int bincount=256, unsigned int histcount=1)
reserves the internal data structures for histcount histograms with bincount bins in each in one imag...
int Draw()
actually draws histogram(s) from the internal data structures
unsigned int GetWidth() const
Definition: ImageBase.hh:312
int AddHist(const Image< StorageType > &Image, unsigned int hist=0)
calculates the histogram of image and adds them to the internal data structures
simple gradient calculation gx(x,y) = I(x+1,y) - I(x-1,y) gy(x,y) = I(x,y+1) - I(x,y-1)
void Draw(BIAS::Image< float > &image)
static int ConvertST(const BIAS::ImageBase &source, BIAS::ImageBase &dest, ImageBase::EStorageType targetST)
Function to convert the storage type of images e.g.
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
int Compute(BIAS::Image< StorageType > &image1, BIAS::Image< StorageType > &image2)
unsigned int GetHeight() const
Definition: ImageBase.hh:319
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
Definition: ImageIO.cpp:725
Class for easy histogram image generation.
static int Load(const std::string &FileName, ImageBase &img)
first tries a call to Read MIP image and if that fails, tries to Import Image with all other availabl...
Definition: ImageIO.cpp:141
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &grad)
returns a 2 channel image containing gx and gy
static int IP_ToGrey(Image< StorageType > &img)
In place conversion to gray image.
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153