26 #include "ColorHistogram.hh"
27 #include <Base/ImageUtils/BresenhamCircle.hh>
28 #include <Base/Image/ImageBase.hh>
29 #include <Base/Image/ImageConvert.hh>
31 #include <Base/Common/BIASpragma.hh>
50 template<
class StorageType>
62 SetBinSize(binSize_,binSizeSat_);
66 template<
class StorageType>
74 template<
class StorageType>
88 template<
class StorageType>
100 template<
class StorageType>
104 unsigned int nBins = (
unsigned int)(256/binSize_);
106 for(
unsigned int k=0;k<nBins;k++){
107 hist_[k].resize(nBins);
109 histl_.resize(nBins);
111 if (binSize_!=4 && binSize_!=8 && binSize_!=16 && binSize_!=32 && binSize_!=64 && binSize_!=128){
112 BIASERR(
"slow, not supported");
119 tmp=tmp>>1; shift_++;
125 luminance_.resize(8);
131 template<
class StorageType>
135 binSize_ = binSizeHue;
136 binSizeSat_ = binSizeSat;
137 unsigned int nBinsHue = (
unsigned int)(256/binSize_);
138 unsigned int nBinsSat = (
unsigned int)(256/binSizeSat_);
140 hist_.resize(nBinsHue);
141 for(
unsigned int k=0;k<nBinsHue;k++){
142 hist_[k].resize(nBinsSat);
144 histl_.resize(nBinsHue);
146 if (binSize_!=4 && binSize_!=8 && binSize_!=16 && binSize_!=32 && binSize_!=64 && binSize_!=128){
147 BIASERR(
"slow, not supported");
154 tmp=tmp>>1; shift_++;
160 tmp=tmp>>1; shiftSat_++;
166 luminance_.resize(8);
174 template<
class StorageType>
181 template<
class StorageType>
187 template<
class StorageType>
193 template<
class StorageType>
200 template<
class StorageType>
219 template<
class StorageType>
238 template<
class StorageType>
241 int ux,
int uy,
int lx,
int ly)
254 template<
class StorageType>
257 int x,
int y,
int r){
264 GenerateCircleHist(image);
270 template<
class StorageType>
277 if ( (abs(ux_- lx_)==0) | (abs(uy_-ly_)==0) )
284 BIASERR(
"GenerateHist() needs an image with HSL Colormodel!");
294 StorageType hue=0, sat=0, light=0;
296 data = image_->GetImageData();
299 int width = image_->GetWidth();
300 int step = 3*width-3*lx_+3*ux_;
301 StorageType *p = data+3*ux_+3*width*uy_;
302 StorageType *e = data+3*lx_+3*width*(ly_-1);
303 StorageType *le = data+3*lx_+3*width*uy_;
309 double invbin=1.0/(double)binSize_;
310 double invbinSat=1.0/(double)binSizeSat_;
318 lum = lum*float(1.0/(
double)32);
319 luminance_[(int)floor((
float)lum)]+=1;
324 sat = sat*float(invbinSat);
325 hue = hue*float(invbin);
326 hist_[(int)floor((
float)hue)][(
int)floor((
float)sat)]+=1;
333 light = light*float(invbin);
334 histl_[(int)floor((
float)light)]+=1;
357 if ( (abs(ux_- lx_)==0) | (abs(uy_-ly_)==0) )
364 BIASERR(
"GenerateHist() needs an image with HSL Colormodel!");
370 data = image_->GetImageData();
373 int width = image_->GetWidth();
374 int step = 3*width-3*lx_+3*ux_;
375 unsigned char *p = data+3*ux_+3*width*uy_;
376 unsigned char *e = data+3*lx_+3*width*(ly_-1);
377 unsigned char *le = data+3*lx_+3*width*uy_;
383 unsigned char hue=0, sat=0, light=0;
392 lum = lum>>shiftLum_;;
398 sat = sat>>shiftSat_;
407 light = light>>shift_;
423 template<
class StorageType>
432 int mp[2] = {mx_,my_};
440 BIASERR(
"GenerateHist() needs an image with HSL Colormodel!");
445 StorageType hue=0, sat=0, light=0;
447 StorageType **data = image_->GetImageDataArray();
448 unsigned int cc = image_->GetChannelCount();
449 height = image_->GetHeight();
450 width = image_->GetWidth();
454 if( (mx_-r_<0) && (my_-r_<0) && (mx_+r_>width) && (my_+r_>height)){
455 BIASERR (
"The range of the circle needs to be completly in the image.");
464 double invbin=1.0/(double)binSize_;
465 double invbinSat=1.0/(double)binSizeSat_;
468 lum = data[next[1]][next[0]*cc+2];
469 lum = lum*float(1.0/(
double)32);
470 luminance_[(int)floor((
float)lum)]+=1;
472 hue = data[next[1]][next[0]*cc+0];
473 sat = data[next[1]][next[0]*cc+1];
474 hue = hue*float(invbin);
475 sat = sat*float(invbinSat);
476 hist_[(int)floor((
float)hue)][(
int)floor((
float)sat)]+=1;
480 light = data[next[1]][next[0]*cc+2];
481 light = light*float(invbin);
482 histl_[(int)floor((
float)light)]+=1;
500 int mp[2] = {mx_,my_};
508 BIASERR(
"GenerateHist() needs an image with HSL Colormodel!");
513 unsigned char hue=0, sat=0, light=0;
515 unsigned char **data = image_->GetImageDataArray();
516 unsigned int cc = image_->GetChannelCount();
517 height = image_->GetHeight();
518 width = image_->GetWidth();
522 if( (mx_-r_<0) && (my_-r_<0) && (mx_+r_>width) && (my_+r_>height)){
523 BIASERR (
"The range of the circle needs to be completly in the image.");
530 double invbin=1.0/(double)binSize_;
531 double invbinSat=1.0/(double)binSizeSat_;
534 lum = data[next[1]][next[0]*cc+2];
536 lum = (
unsigned char)(
float(lum)*(1.0f/32.0f));
537 luminance_[(int)floor((
float)lum)]+=1;
539 hue = data[next[1]][next[0]*cc+0];
540 sat = data[next[1]][next[0]*cc+1];
541 hue = (
unsigned char)(
double(hue)*invbin);
542 sat = (
unsigned char)(
double(sat)*invbinSat);
543 hist_[(int)floor((
float)hue)][(
int)floor((
float)sat)]+=1;
547 light = data[next[1]][next[0]*cc+2];
548 light = (
unsigned char)(
double(light)*invbin);
549 histl_[(int)floor((
float)light)]+=1;
560 template<
class StorageType>
564 int nBins = 256/binSize_;
565 int nBinsSat = 256/binSizeSat_;
567 for(
int i=0;i<nBins;i++){
568 dist += sqrt(histl_[i]*chist.
histl_[i]);
569 for(
int j=0;j<nBinsSat;j++){
570 dist += sqrt(hist_[i][j]*chist.
hist_[i][j]);
577 dist = exp(-lambda_*(1-dist));
587 template<
class StorageType>
592 int nBins = 256/binSize_;
593 int nBinsSat = 256/binSizeSat_;
595 for(
int i=0;i<nBins;i++){
599 dist += sqrt(histl_[i]*chist.
histl_[i]);
601 for(
int j=0;j<nBinsSat;j++){
602 if (hist_[i][j]!=0) {
604 if (chist.
hist_[i][j]!=0)
605 dist += sqrt(hist_[i][j]*chist.
hist_[i][j]);
614 dist = exp(-lambda_*(1-dist));
622 weight /= (256.0/(double)binSize_) * (256.0/(double)binSize_);
626 template<
class StorageType>
633 BIASERR(
"can't update , beause histogramms have different binSize");
639 ux_= int((
double)ux_*(1.0-factor)+factor*(
double)hist.
ux_ + 0.5);
640 uy_= int((
double)uy_*(1.0-factor)+factor*(
double)hist.
uy_ + 0.5);
641 lx_= int((
double)lx_*(1.0-factor)+factor*(
double)hist.
lx_ + 0.5);
642 ly_= int((
double)ly_*(1.0-factor)+factor*(
double)hist.
ly_ + 0.5);
644 int nBins = 256/binSize_;
645 int nBinsSat = 256/binSizeSat_;
648 for(
int i=0;i<nBins;i++){
649 histl_[i]= histl_[i]*(1.0-factor) + factor * hist.
histl_[i];
650 for(
int j=0;j<nBinsSat;j++){
651 hist_[i][j] = hist_[i][j]*(1.0-factor) + factor * hist.
hist_[i][j];
665 float shutterstep = 0.001f;
666 float gainstep = 0.1f;
667 double lowerLum =luminance_[0]+luminance_[1];
668 double higherLum = luminance_[6]+luminance_[7];
675 if((lowerLum - lowerLumRef) > percent)
679 shutter += shutterstep;
694 else if((higherLum - higherLumRef) > percent)
696 if(gain - gainstep >
minGain + gainstep)
703 shutter -= shutterstep;
722 template<
class StorageType>
727 double lowerLum =luminance_[0]+luminance_[1];
728 double higherLum = luminance_[6]+luminance_[7];
730 if(lowerLum > percent)
736 else if(higherLum > percent)
750 template<
class StorageType>
755 std::vector<double> vHistL = GetHistL();
757 if(GetBinSize() == 32)
760 double lowerLum =vHistL[0]+vHistL[1]+vHistL[2]+vHistL[3];
761 double higherLum = vHistL[5]+vHistL[6]+vHistL[7];
763 if(lowerLum > percent)
765 cout<<
"Luminance is low: increase!"<<endl;
769 else if(higherLum > percent)
771 cout<<
"Luminance is high: decrease!"<<endl;
777 cout<<
"Luminace is good, no need to modify"<<endl;
783 BIASERR(
"Only implemented for binSizeHue==8");
797 template<
class StorageType>
800 int nBins = 256/binSize_;
801 int nBinsSat = 256/binSizeSat_;
803 for(
int i=0;i<nBins;i++){
804 for(
int j=0;j<nBinsSat;j++){
805 os <<hist_[i][j]<<
",";
811 for(
int i=0;i<nBins;i++){
817 for(
int i=0;i<8;i++){
818 os <<luminance_[i]<<
",";
829 template<
class StorageType>
832 int nBins = 256/binSize_;
833 int nBinsSat = 256/binSizeSat_;
836 os<<binSize_<<
"\t"<<binSizeSat_<<
"\t"<<mx_<<
837 "\t"<<my_<<
"\t"<<r_<<
"\t"<<(-1)<<endl;
839 os<<binSize_<<
"\t"<<binSizeSat_<<
"\t"<<ux_<<
840 "\t"<<uy_<<
"\t"<<lx_<<
"\t"<<ly_<<endl;
843 for(
int i=0;i<nBins;i++){
844 for(
int j=0;j<nBinsSat;j++){
845 os <<hist_[i][j]<<
"\t";
851 for(
int i=0;i<nBins;i++){
852 os <<histl_[i]<<
"\t";
856 for(
int i=0;i<8;i++){
857 os <<luminance_[i]<<
"\t";
861 os <<binCount_<<endl;
864 template<
class StorageType>
868 return 6 + (256/binSize_)*(256/binSizeSat_) + 2*(256/binSize_) +1;
875 template<
class StorageType>
878 cout<<
"Reading the histogram"<<endl;
879 ifstream histofile(filename);
881 cerr <<
"unable to open " << filename<< endl;
885 int binSize,binSizeSat,ux,uy,lx,ly;
887 histofile >> binSize;
888 histofile >> binSizeSat;
889 histofile >> ux >> uy >> lx >> ly;
890 SetBinSize(binSize,binSizeSat);
896 int nBins = 256/binSize_;
897 int nBinsSat = 256/binSizeSat_;
898 for(
int i=0;i<nBins;i++){
899 for(
int j=0;j<nBinsSat;j++){
900 histofile >> hist_[i][j];
905 for(
int i=0;i<nBins;i++){
906 histofile >> histl_[i];
910 for(
int i=0;i<8;i++){
911 histofile >> luminance_[i];
920 template<
class StorageType>
924 const int end=256>>shift_;
925 const int endSat=256>>shiftSat_;
926 const int endLum=256>>shiftLum_;
929 for(
int i=0;i<end;i++){
930 histl_[i]/=binCount_;
931 for(
int j=0;j<endSat;j++){
932 hist_[i][j] /=binCount_;
936 for(
int k=0;k<endLum;k++)
938 luminance_[k]/=binCount_;
945 template<
class StorageType>
950 histl_.assign(histl_.size(),0);
951 for (
unsigned int i=0;i<hist_.size();i++) {
952 hist_[i].assign(hist_.size(),0);
958 template<
class StorageType>
961 const int end=256>>shift_;
962 const int endSat=256>>shiftSat_;
964 for(
int i=0;i<end;i++){
965 for(
int j=0;j<endSat;j++){
966 if (hist_[i][j]!=0) count++;
969 count/=float(end*endSat);
974 template<
class StorageType>
976 int dataLength=
sizeof(double) * (hist_.size()*hist_[0].size() + histl_.size()*2)
979 char *ptr =
new char[dataLength];
980 int *tmp_int_ptr=(
int *)ptr;
981 *tmp_int_ptr++ = binSize_;
982 *tmp_int_ptr++ = binSizeSat_;
983 *tmp_int_ptr++ = ux_;
984 *tmp_int_ptr++ = uy_;
985 *tmp_int_ptr++ = lx_;
986 *tmp_int_ptr++ = ly_;
987 *tmp_int_ptr++ = binCount_;
989 length += 7*
sizeof(int);
990 int numSat = 256/binSizeSat_;
991 int numHue = 256/binSize_;
994 double *tmp_ptr=(
double*)tmp_int_ptr;
995 for (
int h=0; h<numHue; h++) {
996 for (
int s=0; s<numSat; s++){
997 *tmp_ptr++ = hist_[h][s];
998 length+=
sizeof(double);
1001 for(
int l=0;l<numHue;l++){
1002 *tmp_ptr++ = histl_[l]; length+=
sizeof(double);}
1005 for(
int t=0;t<numHue;t++){
1006 *tmp_ptr++ = luminance_[t]; length+=
sizeof(double);}
1011 template<
class StorageType>
1015 int *tmp_int_ptr =(
int *)data;
1016 binSize_ = *tmp_int_ptr++;
1017 binSizeSat_ = *tmp_int_ptr++;
1018 ux_ = *tmp_int_ptr++;
1019 uy_ = *tmp_int_ptr++;
1020 lx_ = *tmp_int_ptr++;
1021 ly_ = *tmp_int_ptr++;
1022 binCount_ = *tmp_int_ptr++;
1024 double *tmp_ptr=(
double*)tmp_int_ptr;
1026 SetBinSize(binSize_,binSizeSat_);
1027 SetROI(ux_,uy_,lx_,ly_);
1028 int nBins = 256/binSize_;
1029 int nBinsSat = 256/binSizeSat_;
1030 for(
int i=0;i<nBins;i++){
1031 for(
int j=0;j<nBinsSat;j++){
1032 hist_[i][j] = *tmp_ptr++;
1037 for(
int i=0;i<nBins;i++){
1038 histl_[i] = *tmp_ptr++;
1041 for(
int i=0;i<nBins;i++){
1042 luminance_[i] = *tmp_ptr++;
1048 #define INST(type) template class ColorHistogram<type>;
std::vector< std::vector< double > > GetHist() const
return the histogram with H&S values
int Update(const BIAS::ColorHistogram< StorageType > &hist, double factor=0.5)
Updates the histogramm with values from hist, where the factor gives the weighting of the new value...
int GenerateCircleHist(BIAS::Image< StorageType > &image, int x, int y, int r)
calcluates the cirlce formed histogram from data and adds them to the internal data structures ...
This Class handels Histogram matters on Images.
char * GetBinaryData(int &length)
int CheckImageQualityRef(ColorHistogram< StorageType > &cHist, float percent, float &shutter, float &gain)
same as above but checks similarity of luminance to a given reference histogram
HSL, similar to HSV but space is a double tipped cone.
std::vector< double > luminance_
int CheckImageQuality(float percent, float &shutter, float &gain)
checks the image quality depending on the given Histogram and increases ,decreases shutter and gain ...
Scans a circle using Bresenham's integer arithmetic algorithm.
std::vector< double > histl_
int SetROI(int ux, int uy, int lx, int ly)
set the coords for the ROI
void ReadBinaryData(char *data)
void GetROI(std::vector< int > &roi) const
std::vector< double > GetHistL() const
return the L-values of the HSLcolorspace that are <MINSAT in the ROI
double CalcSimilarity(const BIAS::ColorHistogram< StorageType > chist) const
Calculates the Bhattacharyya similarity Coeiffient^2 which is the distance or difference of 2 colorhi...
float GetSaturatedBins() const
returns the percentage [0..1] of HS-bins in the histogram that have values unequal to zero ...
void Dump(std::ostream &os=std::cout)
dumps information on histogram
int DeleteHist_()
deletes hist_, histl_...
int GenerateHist(BIAS::Image< StorageType > &image, int ux, int uy, int lx, int ly)
calcluates the histogram from data and adds them to the internal data structures
int Clear()
Deletes current Histogram information.
int CheckImageQualityComplete(float percent, float &shutter, float &gain)
same as above but luminance vector is created form all pixels in histogram
int GetNumberOfEntries()
this calculates of binsize, binsizesat (1 each) coords (4) the matrix (nrofbinssat * nrofbins) lvecto...
int SetBinSize(int binsize)
set the binsize (must be divideable by 2pown)
bool GetNext(int next[2])
Returns the coordinate of the next point on the circle.
The image template class for specific storage types.
ColorHistogram()
std Con-/Destructor
enum EColorModel GetColorModel() const
std::vector< std::vector< double > > hist_
int Read(const char *filename)
reads a histogram from instream and fills the internal data structures
void DumpCSV(std::ostream &os=std::cout)
dumps information on histogram to ostream format: binsize tab ux tab uy tab lx tab ly hs histogram...
void Normalise_()
Normalizes the histogram to be able to use it in the Bhattacharyya...