Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
biasaverage.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  @file
27  @ingroup g_tools
28  @brief load images given by the command line and compute mean value for each pixel, see biasaverage.cpp
29  @author koeser, fkellner
30 */
31 
32 #include <Base/Image/ImageBase.hh>
33 #include <Base/Image/ImageIO.hh>
34 #include <Base/Image/ImageConvert.hh>
35 #include <Image/HomographyMapping.hh>
36 #include <Utils/Param.hh>
37 #include <Utils/IOUtils.hh>
38 #include <stdio.h>
39 
40 
41 using namespace BIAS;
42 using namespace std;
43 
44 
45 void usage()
46 {
47  cout << "Usage: biasaverage [options] files"<<endl;
48  cout <<" Options: "<< endl
49  <<" -r : rescale output by 2"<<endl
50  << endl;
51  cout <<"at each pixel position average values of all images"<<endl<<endl;
52 }
53 
54 int DetermineFiletype(const string &fn, ImageIO::TFileFormat &thetype)
55 {
56  string::size_type EndOfPrefix;
57  string suffix;
58 
59  EndOfPrefix = fn.rfind('.');
60 
61  if (EndOfPrefix == string::npos) return -1;
62  suffix = fn.substr(EndOfPrefix+1,fn.length());
63  if (suffix == "pnm") thetype = ImageIO::FF_ppm;
64  else if (suffix == "ppm") thetype = ImageIO::FF_ppm;
65  else if (suffix == "pgm") thetype = ImageIO::FF_pgm;
66  else if (suffix == "mip") thetype = ImageIO::FF_mip;
67  else return -1;
68 
69  return 0;
70 }
71 
72 int main (int argc, char *argv[])
73 {
74 
75  Param params(true);
76  string* imageList = params.AddParamString("images", "list of images", "", 'i');
77  string* output = params.AddParamString("output", "output filename (defaults to average.mip", "average.mip", 'o');
78  string* varoutput = params.AddParamString("varoutput", "variance output filename (defaults to variance.mip", "variance.mip", 'O');
79  string* outputUC = params.AddParamString("outputUC", "output filename of uchar image (defaults to average.pgm", "average.pgm", 'u');
80  double* rescaleFactor = params.AddParamDouble("rescale", "rescale factor", 1.0, 0.001, 1000.0, 'r');
81  bool* convertToRGB = params.AddParamBool("convertToRGB", "Convert to RGB before calculating", false,'c');
82  bool* computeVariance = params.AddParamBool("computeVariance", "Also compute a variance image",false,'v');
83  bool* analyzeSamples = params.AddParamBool("analyzeSamples", "Analyze 5 sample points",false,'a');
84 
85  if(!IOUtils::ParseCommandLineEvalHelp(params, argc, (char**)argv))
86  return 0;
87 
88  if (imageList->length() == 0) {
89  params.Usage();
90  return 0; // for Dart testing
91  }
92 
93  vector<string> imageNames;
94  if(Param::ParseListFile(*imageList, imageNames)!=0) {
95  BIASERR("error parsing image names!" << *imageList);
96  return -1;
97  }
98 
99  bool rescale = false;
100  if (*rescaleFactor != 1.0) {
101  std::cout << "rescale"<<endl;
102  rescale = true;
103  }
104 
105  BIAS::ImageBase CurImage;
106 
107  BIAS::Image<float> averageImage;
108  BIAS::Image<float> varianceImage;
109  bool initialized = false;
110  bool ucharout = true;
111 
112  int countImages = 0;
113  for (unsigned int i=0;i<imageNames.size();i++) {
114  if (ImageIO::Load(imageNames[i], CurImage) != 0) {
115  BIASERR("Error reading "<< imageNames[i]);
116  continue;
117  }
118  if(*convertToRGB){
119  if(CurImage.GetColorModel() != ImageBase::CM_RGB){
120  if (CurImage.GetStorageType() == ImageBase::ST_float) {
121  BIAS::Image<float> in(CurImage),out;
122  ImageConvert::ToRGB(in,out);
123  CurImage=out;
124  }
125  else if (CurImage.GetStorageType() == ImageBase::ST_unsignedchar) {
126  BIAS::Image<unsigned char> in(CurImage),out;
127  ImageConvert::ToRGB(in,out);
128  CurImage=out;
129  }
130  }
131  }
132  if (!initialized) {
133  averageImage.Init(CurImage.GetWidth(), CurImage.GetHeight(),
134  CurImage.GetChannelCount());
135  averageImage.SetZero();
136  varianceImage.Init(CurImage.GetWidth(), CurImage.GetHeight(),
137  CurImage.GetChannelCount());
138  varianceImage.SetZero();
139 
140  initialized = true;
141  }
142 
143  const unsigned int channels = CurImage.GetChannelCount();
144  BIASASSERT(channels==1 || CurImage.IsInterleaved());
145  BIASASSERT(averageImage.SamePixelAndChannelCount(CurImage));
146 
147  //cout << i << "/" << imageNames.size() << endl;
148 
149  void **ida = CurImage.GetImageDataArray();
150  for (unsigned int y=0; y<CurImage.GetHeight(); y++) {
151 
152  for (unsigned int x=0; x<CurImage.GetWidth(); x++) {
153  for (unsigned int c=0; c<channels; c++) {
154  //check storage type
155  if (CurImage.GetStorageType() == ImageBase::ST_float) {
156  averageImage.GetImageDataArray()[y][x*channels+c] +=
157  ((float**)ida)[y][x*channels+c];
158  if (ucharout) {
159  ucharout = false;
160  //cout << "-- Float input image found. disabling uchar image output" << endl;
161  }
162  } else if (CurImage.GetStorageType() == ImageBase::ST_unsignedchar) {
163  averageImage.GetImageDataArray()[y][x*channels+c] +=
164  float( ((unsigned char**)ida)[y][x*channels+c]) ;
165  } else {
166  BIASERR("Unknown storage type" << imageNames[i]);
167  }
168  }
169  }
170  }
171  countImages++;
172  }
173  averageImage.ScaleShift(1.0/double(countImages),0);
174 
175  if(*computeVariance)
176  {
177  //now calculate variance image
178  float **idaVar = varianceImage.GetImageDataArray();
179  float **idaAv = averageImage.GetImageDataArray();
180  for (unsigned int i=0;i<imageNames.size();i++) {
181 
182  if (ImageIO::Load(imageNames[i], CurImage) != 0) {
183  BIASERR("Error reading "<< imageNames[i]);
184  continue;
185  }
186  if(*convertToRGB){
187  if(CurImage.GetColorModel() != ImageBase::CM_RGB){
188  if (CurImage.GetStorageType() == ImageBase::ST_float) {
189  BIAS::Image<float> in(CurImage),out;
190  ImageConvert::ToRGB(in,out);
191  CurImage=out;
192  }
193  else if (CurImage.GetStorageType() == ImageBase::ST_unsignedchar) {
194  BIAS::Image<unsigned char> in(CurImage),out;
195  ImageConvert::ToRGB(in,out);
196  CurImage=out;
197  }
198  }
199  }
200 
201  void **ida = CurImage.GetImageDataArray();
202  const unsigned int channels = CurImage.GetChannelCount();
203  for (unsigned int y=0; y<averageImage.GetHeight(); y++) {
204  for (unsigned int x=0; x<averageImage.GetWidth(); x++) {
205  for (unsigned int c=0; c<channels; c++) {
206  idaVar[y][x*channels+c] += pow( (idaAv[y][x*channels+c]-((float**)ida)[y][x*channels+c]),2);
207  }
208  }
209  }
210  }
211  varianceImage.ScaleShift(1.0/double(countImages),0);
212  }// end if(computeVariance)
213 
214  if(*analyzeSamples){
215  unsigned width = averageImage.GetWidth();
216  unsigned height = averageImage.GetHeight();
217  float **idaVar = varianceImage.GetImageDataArray();
218  float **idaAv = averageImage.GetImageDataArray();
219 
220  vector<Vector2<unsigned> > points;
221  Vector2<unsigned> p(10,10); points.push_back(p);
222  p.Set(width-10,height-10); points.push_back(p);
223  p.Set(width/2,height/2); points.push_back(p);
224  p.Set(width-10,10); points.push_back(p);
225  p.Set(10,height-10); points.push_back(p);
226  for(unsigned i=0;i<points.size();i++){
227  cout<<"Mean at "<<points[i]<<": "<<idaAv[points[i][1]][points[i][0]]<<endl;
228  cout<<"Variance at "<<points[i]<<": "<<idaVar[points[i][1]][points[i][0]]<<endl;
229  }
230 
231  unsigned channels = averageImage.GetChannelCount();
232  float *mean = new float[channels];
233  float *var = new float[channels];
234  averageImage.GetMeanPixelValue(mean);
235 
236  varianceImage.GetMeanPixelValue(var);
237  cout<<"Image mean and variance variance : ";
238  for(unsigned i=0;i<channels;i++) cout<<mean[i]<<" "<<var[i]<<endl;
239  delete[] mean;
240  delete[] var;
241  }
242 
243  Image<float> rescaled,varRescaled;
246  if (rescale) {
247  H[0][0] = H[1][1] = 1.0 / (*rescaleFactor);
248  rescaled.Init((unsigned int)ceil( (*rescaleFactor)*double(averageImage.GetWidth()) ),
249  (unsigned int)ceil( (*rescaleFactor)*double(averageImage.GetHeight()) ), averageImage.GetChannelCount());
250  if(*computeVariance){
251  varRescaled.Init((unsigned int)ceil( (*rescaleFactor)*double(averageImage.GetWidth()) ),
252  (unsigned int)ceil( (*rescaleFactor)*double(averageImage.GetHeight()) ), averageImage.GetChannelCount());
253  }
254  converter.SetHomography(H);
255  converter.Map(averageImage, rescaled, MapBicubic);
256  if(*computeVariance){
257  converter.Map(varianceImage, varRescaled, MapBicubic);
258  }
259  } else {
260  rescaled = averageImage;
261  if(*computeVariance)
262  varRescaled = varianceImage;
263  }
264  if(*convertToRGB == false) {
265  rescaled.SetColorModel(CurImage.GetColorModel());
266  }
267  ImageIO::Save(*output, rescaled);
268  if(*computeVariance)
269  ImageIO::Save(*varoutput, varRescaled);
270 
271  if (ucharout) {
272  Image<unsigned char> ucImg;
274  if(*convertToRGB == false) {
275  ucImg.SetColorModel(CurImage.GetColorModel());
276  }
277  ImageIO::Save(*outputUC, ucImg);
278  }
279  return 0;
280 
281 }
282 
283 
284 
285 
286 
287 
288 
289 
290 
291 
292 
293 
a 3x3 Matrix describing projective transformations between planes
Definition: HMatrix.hh:39
Maps image src to image sink with homography H (software implementation)
bool IsInterleaved() const
Definition: ImageBase.hh:491
void SetColorModel(EColorModel Model)
Definition: ImageBase.hh:561
bool * AddParamBool(const std::string &name, const std::string &help, bool deflt=false, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:305
double * AddParamDouble(const std::string &name, const std::string &help, double deflt=0.0, double min=-DBL_MAX, double max=DBL_MAX, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:351
float image storage type
Definition: ImageBase.hh:118
int ScaleShift(double Scale, double Shift)
scales and shifts image (all channels simultanously)
Definition: Image.cpp:1064
unsigned int GetWidth() const
Definition: ImageBase.hh:312
void GetMeanPixelValue(StorageType mean[])
calculates mean of pixel
Definition: Image.cpp:623
void Usage(std::ostream &os=std::cout)
print Help-Information to stdout
Definition: Param.cpp:176
void ** GetImageDataArray() const
Get an array of pointers to image data.
Definition: ImageBase.hh:305
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
color values, 3 channels, order: red,green,blue
Definition: ImageBase.hh:131
TFileFormat
format specifier when writing an image to a file Do NOT change order or associated enum value because...
Definition: ImageIO.hh:76
unsigned int GetHeight() const
Definition: ImageBase.hh:319
int Map(const Image< InputStorageType > &src, Image< OutputStorageType > &sink, InterpolationMethod=MapTrilinear, bool newSink=false, double SuperSampling=1.0)
backward mapping with various interpolations
static int ParseListFile(const std::string &ListFileName, std::vector< std::string > &LinesInFile)
Extracts lines from passed file.
Definition: Param.cpp:1853
static bool ParseCommandLineEvalHelp(Param &params, int argc, char *argv[])
parses the command line, adds parameter &quot;help&quot;
Definition: IOUtils.cpp:176
bool SamePixelAndChannelCount(const ImageBase &Image) const
checks if data area has same &quot;size&quot; as Image of other type
Definition: ImageBase.hh:73
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
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
This class Param provides generic support for parameters.
Definition: Param.hh:231
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
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
void SetHomography(const HMatrix &H)
set your homography H (source = H * sink) before calling Map()
std::string * AddParamString(const std::string &name, const std::string &help, std::string deflt="", char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:327
static int ToRGB(const Image< StorageType > &source, Image< StorageType > &dest)
Create a RGB converted copy of source image in this.
void SetZero()
zeroes the image
Definition: ImageBase.hh:83
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153