Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
IntegralHistogram.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 #include "IntegralHistogram.hh"
27 #include <Base/Image/ImageBase.hh>
28 #include <Base/Image/ImageConvert.hh>
29 #include <Base/Debug/TimeMeasure.hh>
30 
31 #include <Base/Common/BIASpragma.hh>
32 
33 using namespace BIAS;
34 using namespace std;
35 
36 BIAS::TimeMeasure usertime, rowtime;
37 
38 /**
39  This class creates an IntegralHistogram in the HSL color space.
40  @author ingo schiller
41  @date feb 2004
42  */
44 {
45  bExpDist_=true;
46  nMinSat_=10;
47  nLambda_=20;
48  nBinsize_=32;
49  nBinsizeSat_=64;
50  nOldBinsize_=0;
51 
52 }
53 
55 {
56  Clear();
57 }
58 
60  nLambda_= lambda;
61 }
62 
64  nMinSat_=minsat;
65 }
66 
68  nBinsize_ = binsize;
69 }
70 void IntegralHistogram::SetExpDist(bool expdist){
71  bExpDist_=expdist;
72 }
73 
75 {
76  bExpDist_=true;
77  nMinSat_=10;
78  nLambda_=20;
79  nBinsize_=32;
80  nBinsizeSat_=64;
81  nOldBinsize_=0;
82 }
83 
85 GetHistogram(int ux,int uy,int lx, int ly)
86 {
87  //D = D-C-B+A
88  Vector<int> histo = mHists_[ly-1][lx-1];
89  if(ux>0 && uy>0)
90  {
91  histo -= mHists_[ly-1][ux-1]; //lowery - (upperx-1)
92  histo -= mHists_[uy-1][lx-1]; // (uppery-1) - lowerx
93  histo += mHists_[uy-1][ux-1]; // (uppery-1) - (uppery-1)
94  }
95  else if(uy==0 && ux >0)
96  {
97  histo -= mHists_[ly-1][ux-1];
98  }
99  else if(ux==0 && uy >0)
100  {
101  histo -= mHists_[uy-1][lx-1];
102  }
103  return histo;
104 }
105 
106 
108  int nBinsize)
109 {
110 
111 
112  //at first test if image is in HSL
113  if (img.GetColorModel()!=ImageBase::CM_HSL){
114  BIASERR("GenerateIntegralHist() needs an image with HSL Colormodel!");
115  return -1;
116  }
117  //only resize if changed;
118  if(nBinsize != nOldBinsize_)
119  {
120  nBinsize_ = nBinsize;
121  nOldBinsize_ = nBinsize;
122  }
123  nBinsizeSat_ = nBinsize;
124  nOldBinsizeSat_ = nBinsize;
125 
126  const int nWidth = img.GetWidth();
127  const int nHeight = img.GetHeight();
128  unsigned char *pData = img.GetImageData(); //the image data
129  const int nStep = 256/nBinsize_; //the steps in pData
130  const int nStep2=nStep*nStep;
131  const int nNumIndex=nStep2+nStep;
132  unsigned char hue=0, sat=0, light=0;
133  int tmp = nBinsize_; //here calculate the shift
134  nShift_=-1;
135  while (tmp!=0) {
136  tmp=tmp>>1; nShift_++;
137  }
138 
139 
140  //resize the hists array to prevent overflows and init to 0
141  if(mHists_.size() != nWidth*nHeight){
142  Vector<int> tmp(nNumIndex+1);
143  mHists_.newsize(nHeight, nWidth);
144  mHists_=tmp;
145  }
146 
147 
148  //now go through picture and generate the pixelvalues
149  Vector<int> *uData, *lData, *RowEnd, *end;
150  uData = lData = &(mHists_[0][0]);
151  RowEnd = uData + nWidth;
152  end = uData + nWidth*nHeight;
153 
154  //set mHists_ [0][0]
155  lData->Fill(0);
156  hue = (*pData++)>>nShift_;
157  sat = (*pData++);
158  light = (*pData++)>>nShift_;
159  if (sat>nMinSat_){
160  sat = sat>>nShift_;
161  (*lData)[hue*nStep+sat]++;
162  } else {
163  (*lData)[nStep2+light]++;
164  }
165  (*lData)[nNumIndex]=1; // set bincount at [0][0] = 1 (first element
166  lData++;
167  // row 0 (setting elements mHists_[0][x]
168  while (lData < RowEnd){
169  CopyNoCheck(lData[-1], *lData); // copy mHists_[0][0] to mHists_[0][1]
170  hue = (*pData++)>>nShift_;
171  sat = (*pData++);
172  light = (*pData++)>>nShift_;
173  if (sat>nMinSat_){
174  sat = sat>>nShift_;
175  (*lData)[hue*nStep+sat]++;
176  } else {
177  (*lData)[nStep2+light]++;
178  }
179  (*lData)[nNumIndex]++; //increase bincount for mHists_[0][x]
180  lData++;
181 
182  }
183  RowEnd += nWidth;
184  // usertime.Reset();
185  // usertime.Start();
186  while (lData < end){
187  // first column
188  *lData = *uData;
189  hue = (*pData++)>>nShift_;
190  sat = (*pData++);
191  light = (*pData++)>>nShift_;
192  if (sat>nMinSat_){
193  sat = sat>>nShift_;
194  (*lData)[hue*nStep+sat]++;
195  } else {
196  (*lData)[nStep2+light]++;
197  }
198  (*lData)[nNumIndex]++; //increase bincount
199  lData++;
200  uData++;
201  while (lData < RowEnd){
202  *lData = *uData;
203  *lData -= uData[-1];
204  *lData += lData[-1];
205  hue = (*pData++)>>nShift_;
206  sat = (*pData++);
207  light = (*pData++)>>nShift_;
208  if (sat>nMinSat_){
209  sat = sat>>nShift_;
210  (*lData)[hue*nStep+sat]++;
211  } else {
212  (*lData)[nStep2+light]++;
213  }
214  (*lData)[nNumIndex]++;
215  lData++;
216  uData++;
217  }
218  RowEnd+=nWidth;
219  }
220  // usertime.Stop();
221  // cout<<"Building the Int Histo takes \n:";
222  // usertime.PrintRealTime();
223  // cout <<"usecs"<<endl;
224  // usertime.Reset();
225  //Dump(cout, 239, 319);
226  //assert(false);
227  return 0;
228 
229 }
230 
231 
233  int nBinsizeHue, int nBinsizeSat)
234 {
235  // cout<<"CreateIntergralHistDiffBin binSizeHue :"<<nBinsizeHue<<endl;
236  //cout<<"CreateIntergralHistDiffBin binSizeSat :"<<nBinsizeSat<<endl;
237 
238  //at first test if image is in HSL
239  if (img.GetColorModel()!=ImageBase::CM_HSL){
240  BIASERR("GenerateIntegralHist() needs an image with HSL Colormodel!");
241  return -1;
242  }
243  //only resize if changed;
244  if(nBinsizeHue != nOldBinsize_)
245  {
246  nBinsize_ = nBinsizeHue;
247  nOldBinsize_ = nBinsizeHue;
248  }
249  if(nBinsizeSat != nOldBinsizeSat_)
250  {
251  nBinsizeSat_ = nBinsizeSat;
252  nOldBinsizeSat_ = nBinsizeSat;
253  }
254 
255  const int nWidth = img.GetWidth();
256  const int nHeight = img.GetHeight();
257  unsigned char *pData = img.GetImageData(); //the image data
258  const int nStep = 256/nBinsize_; //the steps in pData
259  const int nStepSat = 256/nBinsizeSat_;
260  const int nStep2Sat = nStepSat*nStep;
261  const int nNumIndex=nStep2Sat+nStep;
262  unsigned char hue=0, sat=0, light=0;
263  int tmp = nBinsize_; //here calculate the shift
264  nShift_=-1;
265  while (tmp!=0) {
266  tmp=tmp>>1; nShift_++;
267  }
268 
269  tmp = nBinsizeSat_;
270  nShiftSat_=-1;
271  while (tmp!=0) {
272  tmp=tmp>>1; nShiftSat_++;
273  }
274 
275 
276 
277  //resize the hists array to prevent overflows and init to 0
278  if(mHists_.size() != nWidth*nHeight){
279  Vector<int> tmp(nNumIndex+1);
280  mHists_.newsize(nHeight, nWidth);
281  mHists_=tmp;
282  }
283 
284 
285  //now go through picture and generate the pixelvalues
286  Vector<int> *uData, *lData, *RowEnd, *end;
287  uData = lData = &(mHists_[0][0]);
288  RowEnd = uData + nWidth;
289  end = uData + nWidth*nHeight;
290 
291  //set mHists_[0][0]
292  lData->Fill(0);
293  hue = (*pData++)>>nShift_;
294  sat = (*pData++);
295  light = (*pData++)>>nShift_;
296  if (sat>nMinSat_){
297  sat = sat>>nShiftSat_;
298  (*lData)[hue*nStepSat+sat]++;
299  } else {
300  (*lData)[nStep2Sat+light]++;
301  }
302  (*lData)[nNumIndex]=1; // set bincount at [0][0] = 1 (first element
303  lData++;
304  // row 0 (setting elements mHists_[0][x]
305  while (lData < RowEnd){
306  CopyNoCheck(lData[-1], *lData); // copy mHists_[0][0] to mHists_[0][1]
307  hue = (*pData++)>>nShift_;
308  sat = (*pData++);
309  light = (*pData++)>>nShift_;
310  if (sat>nMinSat_){
311  sat = sat>>nShiftSat_;
312  (*lData)[hue*nStepSat+sat]++;
313  } else {
314  (*lData)[nStep2Sat+light]++;
315  }
316  (*lData)[nNumIndex]++; //increase bincount for mHists_[0][x]
317  lData++;
318 
319  }
320  RowEnd += nWidth;
321 
322  usertime.Reset();
323  usertime.Start();
324  while (lData < end){
325  // first column
326  *lData = *uData;
327  hue = (*pData++)>>nShift_;
328  sat = (*pData++);
329  light = (*pData++)>>nShift_;
330  if (sat>nMinSat_){
331  sat = sat>>nShiftSat_;
332  (*lData)[hue*nStepSat+sat]++;
333  } else {
334  (*lData)[nStep2Sat+light]++;
335  }
336  (*lData)[nNumIndex]++; //increase bincount
337  lData++;
338  uData++;
339  while (lData < RowEnd){
340  *lData = *uData;
341  *lData -= uData[-1];
342  *lData += lData[-1];
343  hue = (*pData++)>>nShift_;
344  sat = (*pData++);
345  light = (*pData++)>>nShift_;
346  if (sat>nMinSat_){
347  sat = sat>>nShiftSat_;
348 
349  (*lData)[hue*nStepSat+sat]++;
350  } else {
351  (*lData)[nStep2Sat+light]++;
352  }
353  (*lData)[nNumIndex]++;
354  lData++;
355  uData++;
356  }
357  RowEnd+=nWidth;
358  }
359  usertime.Stop();
360  // cout<<"Building the Int Histo takes \n:";
361  //usertime.PrintRealTime();
362  // cout <<"usecs"<<endl;
363  usertime.Reset();
364  //Dump(cout, 239, 319);
365  //assert(false);
366  return 0;
367 
368 }
369 
370 
371 double IntegralHistogram::
373  int ux,int uy,int lx, int ly)
374 {
375  double dist=0; //indicator for similarity
376 
377  // BIAS::TimeMeasure time;
378  // time.Reset();
379  // time.Start();
380 
381  //D = D-C-B+A
382  Vector<int> histo = mHists_[ly-1][lx-1];
383  if(ux>0 && uy>0)
384  {
385  histo -= mHists_[ly-1][ux-1]; //lowery - (upperx-1)
386  histo -= mHists_[uy-1][lx-1]; // (uppery-1) - lowerx
387  histo += mHists_[uy-1][ux-1]; // (uppery-1) - (uppery-1)
388  }
389  else if(uy==0 && ux >0)
390  {
391  histo -= mHists_[ly-1][ux-1];
392  }
393  else if(ux==0 && uy >0){
394  histo -= mHists_[uy-1][lx-1];
395  }
396  int nBinwidth = 256/nBinsize_; //width of one bin
397  int nBinwidthSat= 256/nBinsizeSat_; // width of one bin for Sat
398  // int nBinwidthsq = nBinwidth*nBinwidth
399  int nBinwidthsq = nBinwidth*nBinwidthSat;
400  int nBinCount = histo[nBinwidthsq+nBinwidth]; //Number of bins
401  //prevent division by o
402  if(nBinCount == 0)
403  nBinCount = 1;
404 
405  m_cHSData = chist.GetHist();
406  m_cLData = chist.GetHistL();
407 
408  //save normalised values (divided by bincount) in normHisto
409  Vector<double> normHisto(histo.size());
410  for(int x=0;x<histo.size()-1;x++){
411  normHisto[x]= (double)((double) histo[x] / nBinCount);
412  }
413  //but leave last element as the bincount
414  normHisto[histo.size()-1] = histo[histo.size()-1];
415 
416  //sum up the sqrt of the product of q*(n)and q(n;x) over all bins
417  for(int i=0;i<nBinwidth;i++){
418  //lValue
419  dist += sqrt(((double)normHisto[nBinwidthsq+i])*m_cLData[i]);
420  //hsValues
421  // for(int j=0;j<nBinwidth;j++){
422  for(int j=0;j<nBinwidthSat;j++){
423  dist += sqrt((normHisto[i*nBinwidthSat+j])*m_cHSData[i][j]);
424  }
425  }
426  //new
427  if(!bExpDist_)
428  dist = sqrt(1-dist);
429  else
430  dist = exp(-nLambda_*(1-dist));
431 
432  /* old
433  if(bExpDist_)
434  dist = exp(-nLambda_*(1-dist));
435  */
436  // time.Stop();
437  // cout<<"CalculateSimilarity took:"<<endl;
438  // time.Print();
439  return dist;
440 }
441 
442 double
444  int ux1,int uy1,int lx1, int ly1,
446  int ux2,int uy2,int lx2, int ly2,
447  double weightSecond)
448 {
449  double sim1 = CalcSimilarity(chist1,ux1,uy1,lx1,ly1);
450  double sim2 = CalcSimilarity(chist2,ux2,uy2,lx2,ly2);
451  return (1.0-weightSecond)*sim1 + weightSecond*sim2;
452 }
453 
454 /**
455  dumps information on histogram to ostream
456  format:
457  binsize tab ux tab uy tab lx tab ly
458  hs histogram, as a matrix with binsize x binsize (tab separated)
459  l values as a line with lenght binsize (tab separated)
460 */
461 void IntegralHistogram::Dump(std::ostream& os, int y, int x)
462 {
463  os << " D = B + C - A\n";
464  os << "A: "<<mHists_[y-1][x-1]<<endl
465  << "B: "<<mHists_[y-1][x]<<endl
466  << "C: "<<mHists_[y][x-1]<<endl
467  << "D: "<<mHists_[y][x]<<endl;
468  os << " D = B + C - A\n";
469 }
470 
471 
std::vector< std::vector< double > > GetHist() const
return the histogram with H&amp;S values
void SetLambda(int lambda)
sets Lambda, which is used to calculate the dist in CalcSimilarity
HSL, similar to HSV but space is a double tipped cone.
Definition: ImageBase.hh:147
IntegralHistogram()
This class creates an IntegralHistogram in the HSL color space.
std::vector< double > GetHistL() const
return the L-values of the HSLcolorspace that are &lt;MINSAT in the ROI
unsigned int GetWidth() const
Definition: ImageBase.hh:312
void Clear()
Deletes ALL current Histogram information.
unsigned int GetHeight() const
Definition: ImageBase.hh:319
double CalcSimilarity(ColorHistogram< unsigned char > &chist, int ux, int uy, int lx, int ly)
Calculates the Bhattacharyya similarity Coeiffient^2 which is the distance or difference of 2 colorhi...
void SetMinSat(int minsat)
set minsat_, which defines the minimum saturation
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
void SetBinSize(int binsize)
set the binsize (must be divideable by 2pown)
void SetExpDist(bool expdist)
sets expDist_ true or false, used to calculate the dist in CalcSimilarity
void Dump(std::ostream &os, int y, int x)
dumps information on histogram
int GenerateIntegralHist(BIAS::Image< unsigned char > &image, int nBinsize)
calcluates the histogram from the picture and fills the data structs
class TimeMeasure contains functions for timing real time and cpu time.
Definition: TimeMeasure.hh:111
int GenerateIntegralHistDiffBin(BIAS::Image< unsigned char > &image, int nBinsizeHue, int nBinsizeSat)
calcluates the histogram from the picture and fills the data structs
Subscript size() const
Definition: vec.h:262
void Fill(const T &scalar)
fills complete Vector with scalar value
Definition: Vector.cpp:92
Vector< int > GetHistogram(int ux, int uy, int lx, int ly)
Get Histogram.