www.pudn.com > colortracker.rar > histogram3d.h


#ifndef __HISTOGRAM_3d__ 
#define __HISTOGRAM_3d__ 
 
#include "preprocessor.h" 
#include "common.h" 
 
#include  
 
using std::ofstream; 
using std::ifstream; 
 
////////////////////////////////////// 
 
typedef struct tagHISTBIN {  
  int b1;  
  int b2;  
  int b3;  
 
	tagHISTBIN() { 
		b1 = 0; 
		b2 = 0;  
		b3 = 0; 
	} 
 
	inline tagHISTBIN(int _b1, int _b2, int _b3) { 
		set_bin(_b1, _b2, _b3); 
	} 
 
	inline void set_bin (int _b1, int _b2, int _b3) { 
		b1 = _b1; 
		b2 = _b2;  
		b3 = _b3; 
	} 
} HISTBIN;  
 
////////////////////////////////////// 
 
template class histogram3d { 
private: 
	double m_hist[BINSIZE][BINSIZE][BINSIZE];	 
	int m_totalMemSize; 
	int m_numBins; 
	int m_numColors; 
 
	inline double & get_prob(HISTBIN & bin) { 
		return((*this)[bin]); 
	} 
 
	inline void rgb2bin(const RGBTRIPLE & rgb, HISTBIN & bin) { 
		const double alpha = 0.0;	// -0.5 left edge of distribution 
		const double binwidth = static_cast(m_numColors)/static_cast(BINSIZE); 
		int r = floor( static_cast(rgb.rgbtRed-alpha)/binwidth ); 
		int g = floor( static_cast(rgb.rgbtGreen-alpha)/binwidth ); 
		int b = floor( static_cast(rgb.rgbtBlue-alpha)/binwidth ); 
		bin.set_bin(r, g, b); 
	} 
 
	inline void bin2rgb(const HISTBIN & bin, RGBTRIPLE & rgb) { 
		const double alpha = 0.0;	// -0.5 left edge of distribution 
		const double binwidth = static_cast(m_numColors)/static_cast(BINSIZE); 
		rgb.rgbtRed = (bin.b1 - alpha)*binwidth + alpha; 
		rgb.rgbtGreen = (bin.b2 - alpha)*binwidth + alpha; 
		rgb.rgbtBlue = (bin.b2 - alpha)*binwidth + alpha; 
	} 
 
  inline void addtobin(HISTBIN & bin, double value = 1.0) { 
		(*this)[bin] += value; 
	} 
 
public: 
	histogram3d() { 
		m_numBins = BINSIZE*BINSIZE*BINSIZE; 
		m_totalMemSize = m_numBins * sizeof(double); 
		m_numColors = 256; 
		clear(); 
	} 
	 
	inline double *begin () { 
		return (&(m_hist[0][0][0])); 
	} 
 
	inline const double *end () { 
		return(&(m_hist[BINSIZE-1][BINSIZE-1][BINSIZE-1])+1); 
	} 
 
	inline double & operator[] (HISTBIN & bin) { 
		return(m_hist[bin.b1][bin.b2][bin.b3]); 
	} 
 
  inline void addtobin(const RGBTRIPLE & rgb, const double value = 1.0) { 
		HISTBIN bin; 
		rgb2bin(rgb, bin); 
		addtobin(bin, value); 
	} 
 
	inline double & get_prob(const RGBTRIPLE & rgb) { 
		HISTBIN bin; 
		rgb2bin(rgb, bin); 
		return(get_prob(bin)); 
	} 
 
	void clear () { 
		memset(m_hist, 0, m_totalMemSize); 
	} 
 
	histogram3d & copy(histogram3d & hist) { 
		memcpy(hist.m_hist, m_hist, m_totalMemSize); 
		return(hist); 
	} 
 
	void normalize() { 
		double s = sum(); 
		for (double *it = begin(); it != end(); it++) { 
			if (*it) 
				*it /= s; 
		} 
	} 
 
	double sum() { 
		double s = 0.0; 
		for (double *it = begin(); it != end(); it++) 
			s += *it; 
		return (s); 
	} 
 
	void add_uniform (double weight = 1.0) { 
		const double uniform = weight*(1.0/static_cast(m_numBins)); 
		for (double *it = begin(); it != end(); it++) 
			*it = uniform + *it*(1-weight); 
	} 
 
	void weighted_add (histogram3d & hist, const double & weight) { 
		for (double *toptr = begin(), *fromptr = hist.begin(); toptr != end(); toptr++, fromptr++) 
			*toptr = *toptr*weight + *fromptr*(1-weight); 
	} 
 
	void print_values (ofstream &os) { 
		for (double *it = begin(); it != end(); it++) 
			os << *it << endl; 
	} 
 
	void load_from_file (ifstream &is) { 
		clear(); 
		for (double *it = begin(); it != end(); it++) 
			is >> *it; 
	} 
 
	void save_to_file (ofstream &os) { 
		print_values (os); 
	} 
}; 
 
////////////////////////////////////// 
 
#endif __HISTOGRAM_3d__