Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#include "traster.h"
Toshihiro Shimizu 890ddd
#include "tcolorutils.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
#include <list></list>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef float KEYER_FLOAT;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
#ifdef WIN32
Toshihiro Shimizu 890ddd
#define ISNAN _isnan
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
extern "C" int isnan(double);
Toshihiro Shimizu 890ddd
#define ISNAN isnan
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#define CLUSTER_ELEM_CONTAINER_IS_A_SET
Toshihiro Shimizu 890ddd
//#define WITH_ALPHA_IN_STATISTICS
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ClusterStatistic
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	KEYER_FLOAT sumComponents[3]; // vettore 3x1
Toshihiro Shimizu 890ddd
	unsigned int elemsCount;
Toshihiro Shimizu 890ddd
	KEYER_FLOAT matrixR[9]; // matrice 3x3 = somma(x * trasposta(x))
Toshihiro Shimizu 890ddd
							// dove x sono i pixel del cluster
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT covariance[9]; // matrice di covarianza
Toshihiro Shimizu 890ddd
	TPoint sumCoords;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WITH_ALPHA_IN_STATISTICS
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT sumAlpha;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ClusterElem
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ClusterElem(unsigned char _r,
Toshihiro Shimizu 890ddd
				unsigned char _g,
Toshihiro Shimizu 890ddd
				unsigned char _b,
Toshihiro Shimizu 890ddd
				KEYER_FLOAT _a,
Toshihiro Shimizu 890ddd
				unsigned int _x = 0,
Toshihiro Shimizu 890ddd
				unsigned int _y = 0)
Toshihiro Shimizu 890ddd
		: r(toDouble(_r)), g(toDouble(_g)), b(toDouble(_b)), a(_a), x(_x), y(_y), pix32(TPixel32(_r, _g, _b))
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~ClusterElem() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static KEYER_FLOAT toDouble(unsigned char chan)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return ((KEYER_FLOAT)chan) * (KEYER_FLOAT)(1.0 / 255.0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	unsigned int x;
Toshihiro Shimizu 890ddd
	unsigned int y;
Toshihiro Shimizu 890ddd
	KEYER_FLOAT r;
Toshihiro Shimizu 890ddd
	KEYER_FLOAT g;
Toshihiro Shimizu 890ddd
	KEYER_FLOAT b;
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a;
Toshihiro Shimizu 890ddd
	TPixel32 pix32;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef CLUSTER_ELEM_CONTAINER_IS_A_SET
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::set<clusterelem *=""> ClusterElemContainer;</clusterelem>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::vector<clusterelem *=""> ClusterElemContainer;</clusterelem>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Cluster
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Cluster();
Toshihiro Shimizu 890ddd
	Cluster(const Cluster &rhs);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~Cluster();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void computeCovariance();
Toshihiro Shimizu 890ddd
	void insert(ClusterElem *elem);
Toshihiro Shimizu 890ddd
	void computeStatistics();
Toshihiro Shimizu 890ddd
	void getMeanAxis(KEYER_FLOAT axis[3]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ClusterStatistic statistic;
Toshihiro Shimizu 890ddd
	ClusterElemContainer data;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT eigenVector[3];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT eigenValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	void operator=(const Cluster &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::vector<cluster *=""> ClusterContainer;</cluster>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void chooseLeafToClusterize(ClusterContainer::iterator &itRet,
Toshihiro Shimizu 890ddd
							KEYER_FLOAT &eigenValue,
Toshihiro Shimizu 890ddd
							KEYER_FLOAT eigenVector[3],
Toshihiro Shimizu 890ddd
							ClusterContainer &clusters);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void split(Cluster *subcluster1,
Toshihiro Shimizu 890ddd
		   Cluster *subcluster2,
Toshihiro Shimizu 890ddd
		   KEYER_FLOAT eigenVector[3],
Toshihiro Shimizu 890ddd
		   Cluster *cluster);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SolveCubic(KEYER_FLOAT a,   /* coefficient of x^3 */
Toshihiro Shimizu 890ddd
				KEYER_FLOAT b,   /* coefficient of x^2 */
Toshihiro Shimizu 890ddd
				KEYER_FLOAT c,   /* coefficient of x   */
Toshihiro Shimizu 890ddd
				KEYER_FLOAT d,   /* constant term      */
Toshihiro Shimizu 890ddd
				int *solutions,  /* # of distinct solutions */
Toshihiro Shimizu 890ddd
				KEYER_FLOAT *x); /* array of solutions      */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
unsigned short int calcCovarianceEigenValues(const KEYER_FLOAT covariance[9],
Toshihiro Shimizu 890ddd
											 KEYER_FLOAT eigenValues[3]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void split(Cluster *subcluster1,
Toshihiro Shimizu 890ddd
		   Cluster *subcluster2,
Toshihiro Shimizu 890ddd
		   KEYER_FLOAT eigenVector[3],
Toshihiro Shimizu 890ddd
		   Cluster *cluster)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	KEYER_FLOAT n = (KEYER_FLOAT)cluster->statistic.elemsCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT mean[3];
Toshihiro Shimizu 890ddd
	mean[0] = cluster->statistic.sumComponents[0] / n;
Toshihiro Shimizu 890ddd
	mean[1] = cluster->statistic.sumComponents[1] / n;
Toshihiro Shimizu 890ddd
	mean[2] = cluster->statistic.sumComponents[2] / n;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ClusterElemContainer::const_iterator it = cluster->data.begin();
Toshihiro Shimizu 890ddd
	for (; it != cluster->data.end(); ++it) {
Toshihiro Shimizu 890ddd
		ClusterElem *elem = *it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		KEYER_FLOAT r = (KEYER_FLOAT)elem->r;
Toshihiro Shimizu 890ddd
		KEYER_FLOAT g = (KEYER_FLOAT)elem->g;
Toshihiro Shimizu 890ddd
		KEYER_FLOAT b = (KEYER_FLOAT)elem->b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//cluster->data.erase(it);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (eigenVector[0] * r + eigenVector[1] * g + eigenVector[2] * b <=
Toshihiro Shimizu 890ddd
			eigenVector[0] * mean[0] + eigenVector[1] * mean[1] + eigenVector[2] * mean[2])
Toshihiro Shimizu 890ddd
			subcluster1->insert(elem);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			subcluster2->insert(elem);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void chooseLeafToClusterize(ClusterContainer::iterator &itRet,
Toshihiro Shimizu 890ddd
							KEYER_FLOAT &eigenValue,
Toshihiro Shimizu 890ddd
							KEYER_FLOAT eigenVector[3],
Toshihiro Shimizu 890ddd
							ClusterContainer &clusters)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	itRet = clusters.end();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ClusterContainer::iterator itFound = clusters.end();
Toshihiro Shimizu 890ddd
	bool found = false;
Toshihiro Shimizu 890ddd
	KEYER_FLOAT maxEigenValue = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	unsigned short int multeplicity = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ClusterContainer::iterator it = clusters.begin();
Toshihiro Shimizu 890ddd
	for (; it != clusters.end(); ++it) {
Toshihiro Shimizu 890ddd
		unsigned short int tmpMulteplicity = 0;
Toshihiro Shimizu 890ddd
		KEYER_FLOAT tmpEigenValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		Cluster *cluster = *it;
Toshihiro Shimizu 890ddd
		// calcola la matrice di covarianza
Toshihiro Shimizu 890ddd
		const KEYER_FLOAT *clusterCovariance = cluster->statistic.covariance;
Toshihiro Shimizu 890ddd
		assert(!ISNAN(clusterCovariance[0]));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// calcola gli autovalori della matrice di covarianza della statistica
Toshihiro Shimizu 890ddd
		// del cluster (siccome la matrice e' simmetrica gli autovalori
Toshihiro Shimizu 890ddd
		// sono tutti reali)
Toshihiro Shimizu 890ddd
		KEYER_FLOAT eigenValues[3];
Toshihiro Shimizu 890ddd
		tmpMulteplicity = calcCovarianceEigenValues(clusterCovariance, eigenValues);
Toshihiro Shimizu 890ddd
		assert(tmpMulteplicity > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tmpEigenValue = tmax(eigenValues[0], eigenValues[1], eigenValues[2]);
Toshihiro Shimizu 890ddd
		cluster->eigenValue = tmpEigenValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// eventuale aggiornamento del cluster da cercare
Toshihiro Shimizu 890ddd
		if (itFound == clusters.end()) {
Toshihiro Shimizu 890ddd
			itFound = it;
Toshihiro Shimizu 890ddd
			maxEigenValue = tmpEigenValue;
Toshihiro Shimizu 890ddd
			multeplicity = tmpMulteplicity;
Toshihiro Shimizu 890ddd
			found = true;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			if (tmpEigenValue > maxEigenValue) {
Toshihiro Shimizu 890ddd
				itFound = it;
Toshihiro Shimizu 890ddd
				maxEigenValue = tmpEigenValue;
Toshihiro Shimizu 890ddd
				multeplicity = tmpMulteplicity;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (found) {
Toshihiro Shimizu 890ddd
		assert(multeplicity > 0);
Toshihiro Shimizu 890ddd
		itRet = itFound;
Toshihiro Shimizu 890ddd
		eigenValue = maxEigenValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// calcola l'autovettore relativo a maxEigenValue
Toshihiro Shimizu 890ddd
		Cluster *clusterFound = *itFound;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(multeplicity > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		KEYER_FLOAT tmpMatrixM[9];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const KEYER_FLOAT *clusterCovariance = clusterFound->statistic.covariance;
Toshihiro Shimizu 890ddd
		int i = 0;
Toshihiro Shimizu 890ddd
		for (; i < 9; ++i)
Toshihiro Shimizu 890ddd
			tmpMatrixM[i] = clusterCovariance[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tmpMatrixM[0] -= maxEigenValue;
Toshihiro Shimizu 890ddd
		tmpMatrixM[4] -= maxEigenValue;
Toshihiro Shimizu 890ddd
		tmpMatrixM[8] -= maxEigenValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < 3; ++i)
Toshihiro Shimizu 890ddd
			eigenVector[i] = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (multeplicity == 1) {
Toshihiro Shimizu 890ddd
			KEYER_FLOAT u11 = tmpMatrixM[4] * tmpMatrixM[8] - tmpMatrixM[5] * tmpMatrixM[5];
Toshihiro Shimizu 890ddd
			KEYER_FLOAT u12 = tmpMatrixM[2] * tmpMatrixM[5] - tmpMatrixM[1] * tmpMatrixM[8];
Toshihiro Shimizu 890ddd
			KEYER_FLOAT u13 = tmpMatrixM[1] * tmpMatrixM[5] - tmpMatrixM[2] * tmpMatrixM[5];
Toshihiro Shimizu 890ddd
			KEYER_FLOAT u22 = tmpMatrixM[0] * tmpMatrixM[8] - tmpMatrixM[2] * tmpMatrixM[2];
Toshihiro Shimizu 890ddd
			KEYER_FLOAT u23 = tmpMatrixM[1] * tmpMatrixM[2] - tmpMatrixM[5] * tmpMatrixM[0];
Toshihiro Shimizu 890ddd
			KEYER_FLOAT u33 = tmpMatrixM[0] * tmpMatrixM[4] - tmpMatrixM[1] * tmpMatrixM[1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			KEYER_FLOAT uMax = tmax(tmax(u11, u12, u13), u22, u23, u33);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (uMax == u11) {
Toshihiro Shimizu 890ddd
				eigenVector[0] = u11;
Toshihiro Shimizu 890ddd
				eigenVector[1] = u12;
Toshihiro Shimizu 890ddd
				eigenVector[2] = u13;
Toshihiro Shimizu 890ddd
			} else if (uMax == u12) {
Toshihiro Shimizu 890ddd
				eigenVector[0] = u12;
Toshihiro Shimizu 890ddd
				eigenVector[1] = u22;
Toshihiro Shimizu 890ddd
				eigenVector[2] = u23;
Toshihiro Shimizu 890ddd
			} else if (uMax == u13) {
Toshihiro Shimizu 890ddd
				eigenVector[0] = u13;
Toshihiro Shimizu 890ddd
				eigenVector[1] = u23;
Toshihiro Shimizu 890ddd
				eigenVector[2] = u33;
Toshihiro Shimizu 890ddd
			} else if (uMax == u22) {
Toshihiro Shimizu 890ddd
				eigenVector[0] = u12;
Toshihiro Shimizu 890ddd
				eigenVector[1] = u22;
Toshihiro Shimizu 890ddd
				eigenVector[2] = u23;
Toshihiro Shimizu 890ddd
			} else if (uMax == u23) {
Toshihiro Shimizu 890ddd
				eigenVector[0] = u13;
Toshihiro Shimizu 890ddd
				eigenVector[1] = u23;
Toshihiro Shimizu 890ddd
				eigenVector[2] = u33;
Toshihiro Shimizu 890ddd
			} else if (uMax == u33) {
Toshihiro Shimizu 890ddd
				eigenVector[0] = u13;
Toshihiro Shimizu 890ddd
				eigenVector[1] = u23;
Toshihiro Shimizu 890ddd
				eigenVector[2] = u33;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				assert(false && "impossibile!!");
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		} else if (multeplicity == 2) {
Toshihiro Shimizu 890ddd
			short int row = -1;
Toshihiro Shimizu 890ddd
			short int col = -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			KEYER_FLOAT mMax = tmax(tmax(tmpMatrixM[0], tmpMatrixM[1], tmpMatrixM[2]),
Toshihiro Shimizu 890ddd
									tmpMatrixM[4], tmpMatrixM[5], tmpMatrixM[8]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (mMax == tmpMatrixM[0]) {
Toshihiro Shimizu 890ddd
				row = 1;
Toshihiro Shimizu 890ddd
				col = 1;
Toshihiro Shimizu 890ddd
			} else if (mMax == tmpMatrixM[1]) {
Toshihiro Shimizu 890ddd
				row = 1;
Toshihiro Shimizu 890ddd
				col = 2;
Toshihiro Shimizu 890ddd
			} else if (mMax == tmpMatrixM[2]) {
Toshihiro Shimizu 890ddd
				row = 1;
Toshihiro Shimizu 890ddd
				col = 3;
Toshihiro Shimizu 890ddd
			} else if (mMax == tmpMatrixM[4]) {
Toshihiro Shimizu 890ddd
				row = 2;
Toshihiro Shimizu 890ddd
				col = 2;
Toshihiro Shimizu 890ddd
			} else if (mMax == tmpMatrixM[5]) {
Toshihiro Shimizu 890ddd
				row = 2;
Toshihiro Shimizu 890ddd
				col = 3;
Toshihiro Shimizu 890ddd
			} else if (mMax == tmpMatrixM[8]) {
Toshihiro Shimizu 890ddd
				row = 3;
Toshihiro Shimizu 890ddd
				col = 3;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (row == 1) {
Toshihiro Shimizu 890ddd
				if (col == 1 || col == 2) {
Toshihiro Shimizu 890ddd
					eigenVector[0] = -tmpMatrixM[1];
Toshihiro Shimizu 890ddd
					eigenVector[1] = tmpMatrixM[0];
Toshihiro Shimizu 890ddd
					eigenVector[2] = 0.0;
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					eigenVector[0] = tmpMatrixM[2];
Toshihiro Shimizu 890ddd
					eigenVector[1] = 0.0;
Toshihiro Shimizu 890ddd
					eigenVector[2] = -tmpMatrixM[0];
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else if (row == 2) {
Toshihiro Shimizu 890ddd
				eigenVector[0] = 0.0;
Toshihiro Shimizu 890ddd
				eigenVector[1] = -tmpMatrixM[5];
Toshihiro Shimizu 890ddd
				eigenVector[2] = tmpMatrixM[4];
Toshihiro Shimizu 890ddd
			} else if (row == 3) {
Toshihiro Shimizu 890ddd
				eigenVector[0] = 0.0;
Toshihiro Shimizu 890ddd
				eigenVector[1] = -tmpMatrixM[8];
Toshihiro Shimizu 890ddd
				eigenVector[2] = tmpMatrixM[5];
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else if (multeplicity == 3) {
Toshihiro Shimizu 890ddd
			eigenVector[0] = 1.0;
Toshihiro Shimizu 890ddd
			eigenVector[1] = 0.0;
Toshihiro Shimizu 890ddd
			eigenVector[2] = 0.0;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			assert(false && "impossibile!!");
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// normalizzazione dell'autovettore calcolato
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
      KEYER_FLOAT eigenVectorMagnitude = sqrt(eigenVector[0]*eigenVector[0] +
Toshihiro Shimizu 890ddd
                                         eigenVector[1]*eigenVector[1] +
Toshihiro Shimizu 890ddd
                                         eigenVector[2]*eigenVector[2]);
Toshihiro Shimizu 890ddd
      assert(eigenVectorMagnitude > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
      eigenVector[0] /= eigenVectorMagnitude;
Toshihiro Shimizu 890ddd
      eigenVector[1] /= eigenVectorMagnitude;
Toshihiro Shimizu 890ddd
      eigenVector[2] /= eigenVectorMagnitude;
Toshihiro Shimizu 890ddd
      */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		clusterFound->eigenVector[0] = eigenVector[0];
Toshihiro Shimizu 890ddd
		clusterFound->eigenVector[1] = eigenVector[1];
Toshihiro Shimizu 890ddd
		clusterFound->eigenVector[2] = eigenVector[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(!ISNAN(eigenVector[0]));
Toshihiro Shimizu 890ddd
		assert(!ISNAN(eigenVector[1]));
Toshihiro Shimizu 890ddd
		assert(!ISNAN(eigenVector[2]));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
unsigned short int calcCovarianceEigenValues(const KEYER_FLOAT clusterCovariance[9],
Toshihiro Shimizu 890ddd
											 KEYER_FLOAT eigenValues[3])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	unsigned short int multeplicity = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a11 = clusterCovariance[0];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a12 = clusterCovariance[1];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a13 = clusterCovariance[2];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a22 = clusterCovariance[4];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a23 = clusterCovariance[5];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a33 = clusterCovariance[8];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT c0 =
Toshihiro Shimizu 890ddd
		(KEYER_FLOAT)(a11 * a22 * a33 + 2.0 * a12 * a13 * a23 - a11 * a23 * a23 - a22 * a13 * a13 - a33 * a12 * a12);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT c1 = (KEYER_FLOAT)(a11 * a22 - a12 * a12 + a11 * a33 - a13 * a13 + a22 * a33 - a23 * a23);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT c2 = (KEYER_FLOAT)(a11 + a22 + a33);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int solutionsCount = 0;
Toshihiro Shimizu 890ddd
	SolveCubic((KEYER_FLOAT)-1.0, c2, -c1, c0, &solutionsCount, eigenValues);
Toshihiro Shimizu 890ddd
	assert(solutionsCount > 0);
Toshihiro Shimizu 890ddd
	multeplicity = 4 - solutionsCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(!ISNAN(eigenValues[0]));
Toshihiro Shimizu 890ddd
	assert(!ISNAN(eigenValues[1]));
Toshihiro Shimizu 890ddd
	assert(!ISNAN(eigenValues[2]));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(multeplicity > 0);
Toshihiro Shimizu 890ddd
	return multeplicity;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SolveCubic(KEYER_FLOAT a,  /* coefficient of x^3 */
Toshihiro Shimizu 890ddd
				KEYER_FLOAT b,  /* coefficient of x^2 */
Toshihiro Shimizu 890ddd
				KEYER_FLOAT c,  /* coefficient of x   */
Toshihiro Shimizu 890ddd
				KEYER_FLOAT d,  /* constant term      */
Toshihiro Shimizu 890ddd
				int *solutions, /* # of distinct solutions */
Toshihiro Shimizu 890ddd
				KEYER_FLOAT *x) /* array of solutions      */
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static const KEYER_FLOAT epsilon = (KEYER_FLOAT)0.0001;
Toshihiro Shimizu 890ddd
	if (a != 0 && fabs(b - 0.0) <= epsilon && fabs(c - 0.0) <= epsilon && fabs(d - 0.0) <= epsilon)
Toshihiro Shimizu 890ddd
	//if(a != 0 && b == 0 && c == 0 && d == 0)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		*solutions = 1;
Toshihiro Shimizu 890ddd
		x[0] = x[1] = x[2] = 0.0;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a1 = (KEYER_FLOAT)(b / a);
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a2 = (KEYER_FLOAT)(c / a);
Toshihiro Shimizu 890ddd
	KEYER_FLOAT a3 = (KEYER_FLOAT)(d / a);
Toshihiro Shimizu 890ddd
	KEYER_FLOAT Q = (KEYER_FLOAT)((a1 * a1 - 3.0 * a2) / 9.0);
Toshihiro Shimizu 890ddd
	KEYER_FLOAT R = (KEYER_FLOAT)((2.0 * a1 * a1 * a1 - 9.0 * a1 * a2 + 27.0 * a3) / 54.0);
Toshihiro Shimizu 890ddd
	KEYER_FLOAT R2_Q3 = (KEYER_FLOAT)(R * R - Q * Q * Q);
Toshihiro Shimizu 890ddd
	KEYER_FLOAT theta;
Toshihiro Shimizu 890ddd
	KEYER_FLOAT PI = (KEYER_FLOAT)3.1415926535897932384626433832795;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (R2_Q3 <= 0) {
Toshihiro Shimizu 890ddd
		*solutions = 3;
Toshihiro Shimizu 890ddd
		theta = (KEYER_FLOAT)acos(R / sqrt(Q * Q * Q));
Toshihiro Shimizu 890ddd
		x[0] = (KEYER_FLOAT)(-2.0 * sqrt(Q) * cos(theta / 3.0) - a1 / 3.0);
Toshihiro Shimizu 890ddd
		x[1] = (KEYER_FLOAT)(-2.0 * sqrt(Q) * cos((theta + 2.0 * PI) / 3.0) - a1 / 3.0);
Toshihiro Shimizu 890ddd
		x[2] = (KEYER_FLOAT)(-2.0 * sqrt(Q) * cos((theta + 4.0 * PI) / 3.0) - a1 / 3.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(!ISNAN(x[0]));
Toshihiro Shimizu 890ddd
		assert(!ISNAN(x[1]));
Toshihiro Shimizu 890ddd
		assert(!ISNAN(x[2]));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
            long KEYER_FLOAT v;
Toshihiro Shimizu 890ddd
            v = x[0];
Toshihiro Shimizu 890ddd
            assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0));
Toshihiro Shimizu 890ddd
            v = x[1];
Toshihiro Shimizu 890ddd
            assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0));
Toshihiro Shimizu 890ddd
            v = x[2];
Toshihiro Shimizu 890ddd
            assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0));
Toshihiro Shimizu 890ddd
            */
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		*solutions = 1;
Toshihiro Shimizu 890ddd
		x[0] = (KEYER_FLOAT)pow((float)(sqrt(R2_Q3) + fabs(R)), (float)(1 / 3.0));
Toshihiro Shimizu 890ddd
		x[0] += (KEYER_FLOAT)(Q / x[0]);
Toshihiro Shimizu 890ddd
		x[0] *= (KEYER_FLOAT)((R < 0.0) ? 1 : -1);
Toshihiro Shimizu 890ddd
		x[0] -= (KEYER_FLOAT)(a1 / 3.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(!ISNAN(x[0]));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
            long KEYER_FLOAT v;
Toshihiro Shimizu 890ddd
            v = x[0];
Toshihiro Shimizu 890ddd
            assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0));
Toshihiro Shimizu 890ddd
            */
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void clusterize(ClusterContainer &clusters, int clustersCount)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	unsigned int clustersSize = clusters.size();
Toshihiro Shimizu 890ddd
	assert(clustersSize >= 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// faccio in modo che in clusters ci siano solo e sempre le foglie
Toshihiro Shimizu 890ddd
	// dell'albero calcolato secondo l'algoritmo TSE descritto da Orchard-Bouman
Toshihiro Shimizu 890ddd
	// (c.f.r. "Color Quantization of Images" - M.Orchard, C. Bouman)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// numero di iterazioni, numero di cluster = numero di iterazioni + 1
Toshihiro Shimizu 890ddd
	int m = clustersCount - 1;
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
	for (; i < m; ++i) {
Toshihiro Shimizu 890ddd
		// sceglie la foglia dell'albero dei cluster (ovvero il cluster nel
Toshihiro Shimizu 890ddd
		// ClusterContainer "clusters") che ha il maggiore autovalore, ovvero
Toshihiro Shimizu 890ddd
		// il cluster che ha maggiore varainza rispetto all'asse opportuno
Toshihiro Shimizu 890ddd
		// (che poi e' l'autovettore corrispondente all'autovalore piu' grande)
Toshihiro Shimizu 890ddd
		KEYER_FLOAT eigenValue = 0.0;
Toshihiro Shimizu 890ddd
		KEYER_FLOAT eigenVector[3] = {0.0, 0.0, 0.0};
Toshihiro Shimizu 890ddd
		ClusterContainer::iterator itChoosedCluster;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		chooseLeafToClusterize(itChoosedCluster,
Toshihiro Shimizu 890ddd
							   eigenValue,
Toshihiro Shimizu 890ddd
							   eigenVector,
Toshihiro Shimizu 890ddd
							   clusters);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(itChoosedCluster != clusters.end());
Toshihiro Shimizu 890ddd
		Cluster *choosedCluster = *itChoosedCluster;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if 0
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    // se il cluster che si e' scelto per la suddivisione contiene un solo
Toshihiro Shimizu 890ddd
    // elemento vuol dire che non c'e' piu' niente da suddividere e si esce
Toshihiro Shimizu 890ddd
    // dal ciclo.
Toshihiro Shimizu 890ddd
    // Questo succede quando si sono chiesti piu' clusters di quanti elementi
Toshihiro Shimizu 890ddd
    // ci sono nel cluster iniziale.
Toshihiro Shimizu 890ddd
    if(choosedCluster->statistic.elemsCount == 1)
Toshihiro Shimizu 890ddd
      break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// un cluster che ha un solo elemento non ha molto senso di esistere,
Toshihiro Shimizu 890ddd
		// credo crei problemi anche nel calcolo della matrice di covarianza,
Toshihiro Shimizu 890ddd
		// quindi mi fermo quando il cluster contiene meno di 4 elementi
Toshihiro Shimizu 890ddd
		if (choosedCluster->statistic.elemsCount == 3)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// suddivide il cluster scelto in altri due cluster
Toshihiro Shimizu 890ddd
		Cluster *subcluster1 = new Cluster();
Toshihiro Shimizu 890ddd
		Cluster *subcluster2 = new Cluster();
Toshihiro Shimizu 890ddd
		split(subcluster1, subcluster2, eigenVector, choosedCluster);
Toshihiro Shimizu 890ddd
		assert(subcluster1);
Toshihiro Shimizu 890ddd
		assert(subcluster2);
Toshihiro Shimizu 890ddd
		if ((subcluster1->data.size() == 0) ||
Toshihiro Shimizu 890ddd
			(subcluster2->data.size() == 0))
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// calcola la nuova statistica per subcluster1
Toshihiro Shimizu 890ddd
		subcluster1->computeStatistics();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// calcola la nuova statistica per subcluster2
Toshihiro Shimizu 890ddd
		int j = 0;
Toshihiro Shimizu 890ddd
		for (; j < 3; ++j) {
Toshihiro Shimizu 890ddd
			subcluster2->statistic.sumComponents[j] =
Toshihiro Shimizu 890ddd
				choosedCluster->statistic.sumComponents[j] -
Toshihiro Shimizu 890ddd
				subcluster1->statistic.sumComponents[j];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		subcluster2->statistic.sumCoords.x =
Toshihiro Shimizu 890ddd
			choosedCluster->statistic.sumCoords.x -
Toshihiro Shimizu 890ddd
			subcluster1->statistic.sumCoords.x;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		subcluster2->statistic.sumCoords.y =
Toshihiro Shimizu 890ddd
			choosedCluster->statistic.sumCoords.y -
Toshihiro Shimizu 890ddd
			subcluster1->statistic.sumCoords.y;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		subcluster2->statistic.elemsCount =
Toshihiro Shimizu 890ddd
			choosedCluster->statistic.elemsCount -
Toshihiro Shimizu 890ddd
			subcluster1->statistic.elemsCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WITH_ALPHA_IN_STATISTICS
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		subcluster2->statistic.sumAlpha =
Toshihiro Shimizu 890ddd
			choosedCluster->statistic.sumAlpha -
Toshihiro Shimizu 890ddd
			subcluster1->statistic.sumAlpha;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (j = 0; j < 9; ++j)
Toshihiro Shimizu 890ddd
			subcluster2->statistic.matrixR[j] =
Toshihiro Shimizu 890ddd
				choosedCluster->statistic.matrixR[j] -
Toshihiro Shimizu 890ddd
				subcluster1->statistic.matrixR[j];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		subcluster2->computeCovariance();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// aggiorna in modo opportuno il ClusterContainer "clusters", cancellando
Toshihiro Shimizu 890ddd
		// il cluster scelto e inserendo i due appena creati.
Toshihiro Shimizu 890ddd
		// Facendo cosi' il ClusterContainer "cluster" contiene solo e sempre
Toshihiro Shimizu 890ddd
		// le foglie dell'albero creato dall'algoritmo TSE.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		Cluster *cluster = *itChoosedCluster;
Toshihiro Shimizu 890ddd
		assert(cluster);
Toshihiro Shimizu 890ddd
		cluster->data.clear();
Toshihiro Shimizu 890ddd
		//clearPointerContainer(cluster->data);
Toshihiro Shimizu 890ddd
		assert(cluster->data.size() == 0);
Toshihiro Shimizu 890ddd
		delete cluster;
Toshihiro Shimizu 890ddd
		clusters.erase(itChoosedCluster);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		clusters.push_back(subcluster1);
Toshihiro Shimizu 890ddd
		clusters.push_back(subcluster2);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Cluster::Cluster()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Cluster::Cluster(const Cluster &rhs)
Toshihiro Shimizu 890ddd
	: statistic(rhs.statistic)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ClusterElemContainer::const_iterator it = rhs.data.begin();
Toshihiro Shimizu 890ddd
	for (; it != rhs.data.end(); ++it)
Toshihiro Shimizu 890ddd
		data.push_back(new ClusterElem(**it));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Cluster::~Cluster()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	clearPointerContainer(data);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Cluster::computeCovariance()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	KEYER_FLOAT sumComponentsMatrix[9];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT sumR = statistic.sumComponents[0];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT sumG = statistic.sumComponents[1];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT sumB = statistic.sumComponents[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sumComponentsMatrix[0] = sumR * sumR;
Toshihiro Shimizu 890ddd
	sumComponentsMatrix[1] = sumR * sumG;
Toshihiro Shimizu 890ddd
	sumComponentsMatrix[2] = sumR * sumB;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sumComponentsMatrix[3] = sumComponentsMatrix[1];
Toshihiro Shimizu 890ddd
	sumComponentsMatrix[4] = sumG * sumG;
Toshihiro Shimizu 890ddd
	sumComponentsMatrix[5] = sumG * sumB;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sumComponentsMatrix[6] = sumComponentsMatrix[2];
Toshihiro Shimizu 890ddd
	sumComponentsMatrix[7] = sumComponentsMatrix[5];
Toshihiro Shimizu 890ddd
	sumComponentsMatrix[8] = sumB * sumB;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT n = (KEYER_FLOAT)statistic.elemsCount;
Toshihiro Shimizu 890ddd
	assert(n > 0);
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
	for (; i < 9; ++i) {
Toshihiro Shimizu 890ddd
		statistic.covariance[i] =
Toshihiro Shimizu 890ddd
			statistic.matrixR[i] - sumComponentsMatrix[i] / n;
Toshihiro Shimizu 890ddd
		assert(!ISNAN(statistic.matrixR[i]));
Toshihiro Shimizu 890ddd
		//assert(statistic.covariance[i] >= 0.0);
Toshihiro Shimizu 890ddd
		// instabilita' numerica ???
Toshihiro Shimizu 890ddd
		if (statistic.covariance[i] < 0.0)
Toshihiro Shimizu 890ddd
			statistic.covariance[i] = 0.0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Cluster::insert(ClusterElem *elem)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef CLUSTER_ELEM_CONTAINER_IS_A_SET
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	data.insert(elem);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	data.push_back(elem);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Cluster::computeStatistics()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// inizializza a zero la statistica del cluster
Toshihiro Shimizu 890ddd
	statistic.elemsCount = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	statistic.sumCoords = TPoint(0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
	for (; i < 3; ++i)
Toshihiro Shimizu 890ddd
		statistic.sumComponents[i] = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < 9; ++i)
Toshihiro Shimizu 890ddd
		statistic.matrixR[i] = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// calcola la statistica del cluster
Toshihiro Shimizu 890ddd
	ClusterElemContainer::const_iterator it = data.begin();
Toshihiro Shimizu 890ddd
	for (; it != data.end(); ++it) {
Toshihiro Shimizu 890ddd
		const ClusterElem *elem = *it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WITH_ALPHA_IN_STATISTICS
Toshihiro Shimizu 890ddd
		KEYER_FLOAT alpha = elem->a;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		KEYER_FLOAT r = (KEYER_FLOAT)elem->r;
Toshihiro Shimizu 890ddd
		KEYER_FLOAT g = (KEYER_FLOAT)elem->g;
Toshihiro Shimizu 890ddd
		KEYER_FLOAT b = (KEYER_FLOAT)elem->b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		statistic.sumComponents[0] += r;
Toshihiro Shimizu 890ddd
		statistic.sumComponents[1] += g;
Toshihiro Shimizu 890ddd
		statistic.sumComponents[2] += b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WITH_ALPHA_IN_STATISTICS
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		statistic.sumAlpha += alpha;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// prima riga della matrice R
Toshihiro Shimizu 890ddd
		statistic.matrixR[0] += r * r;
Toshihiro Shimizu 890ddd
		statistic.matrixR[1] += r * g;
Toshihiro Shimizu 890ddd
		statistic.matrixR[2] += r * b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// seconda riga della matrice R
Toshihiro Shimizu 890ddd
		statistic.matrixR[3] += r * g;
Toshihiro Shimizu 890ddd
		statistic.matrixR[4] += g * g;
Toshihiro Shimizu 890ddd
		statistic.matrixR[5] += g * b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// terza riga della matrice R
Toshihiro Shimizu 890ddd
		statistic.matrixR[6] += r * b;
Toshihiro Shimizu 890ddd
		statistic.matrixR[7] += b * g;
Toshihiro Shimizu 890ddd
		statistic.matrixR[8] += b * b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		statistic.sumCoords.x += elem->x;
Toshihiro Shimizu 890ddd
		statistic.sumCoords.y += elem->y;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		++statistic.elemsCount;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(statistic.elemsCount > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	computeCovariance();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Cluster::getMeanAxis(KEYER_FLOAT axis[3])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	KEYER_FLOAT n = (KEYER_FLOAT)statistic.elemsCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if 1
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	axis[0] = (KEYER_FLOAT)(sqrt(statistic.covariance[0]) / n);
Toshihiro Shimizu 890ddd
	axis[1] = (KEYER_FLOAT)(sqrt(statistic.covariance[4]) / n);
Toshihiro Shimizu 890ddd
	axis[2] = (KEYER_FLOAT)(sqrt(statistic.covariance[8]) / n);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT I[3];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT J[3];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT K[3];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	I[0] = statistic.covariance[0];
Toshihiro Shimizu 890ddd
	I[1] = statistic.covariance[1];
Toshihiro Shimizu 890ddd
	I[2] = statistic.covariance[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	J[0] = statistic.covariance[3];
Toshihiro Shimizu 890ddd
	J[1] = statistic.covariance[4];
Toshihiro Shimizu 890ddd
	J[2] = statistic.covariance[5];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	K[0] = statistic.covariance[6];
Toshihiro Shimizu 890ddd
	K[1] = statistic.covariance[7];
Toshihiro Shimizu 890ddd
	K[2] = statistic.covariance[8];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	KEYER_FLOAT magnitudeI = I[0] * I[0] + I[1] * I[1] + I[2] * I[2];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT magnitudeJ = J[0] * J[0] + J[1] * J[1] + J[2] * I[2];
Toshihiro Shimizu 890ddd
	KEYER_FLOAT magnitudeK = K[0] * K[0] + K[1] * K[1] + K[2] * I[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (magnitudeI >= magnitudeJ && magnitudeI >= magnitudeK) {
Toshihiro Shimizu 890ddd
		axis[0] = sqrt(I[0] / n);
Toshihiro Shimizu 890ddd
		axis[1] = sqrt(I[1] / n);
Toshihiro Shimizu 890ddd
		axis[2] = sqrt(I[2] / n);
Toshihiro Shimizu 890ddd
	} else if (magnitudeJ >= magnitudeI && magnitudeJ >= magnitudeK) {
Toshihiro Shimizu 890ddd
		axis[0] = sqrt(J[0] / n);
Toshihiro Shimizu 890ddd
		axis[1] = sqrt(J[1] / n);
Toshihiro Shimizu 890ddd
		axis[2] = sqrt(J[2] / n);
Toshihiro Shimizu 890ddd
	} else if (magnitudeK >= magnitudeI && magnitudeK >= magnitudeJ) {
Toshihiro Shimizu 890ddd
		axis[0] = sqrt(K[0] / n);
Toshihiro Shimizu 890ddd
		axis[1] = sqrt(K[1] / n);
Toshihiro Shimizu 890ddd
		axis[2] = sqrt(K[2] / n);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#define METODO_USATO_SU_TOONZ46
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void buildPaletteForBlendedImages(std::set<tpixel32> &palette, const TRaster32P &raster, int maxColorCount)</tpixel32>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int lx = raster->getLx();
Toshihiro Shimizu 890ddd
	int ly = raster->getLy();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ClusterContainer clusters;
Toshihiro Shimizu 890ddd
	Cluster *cluster = new Cluster;
Toshihiro Shimizu 890ddd
	raster->lock();
Toshihiro Shimizu 890ddd
	for (int y = 0; y < ly; ++y) {
Toshihiro Shimizu 890ddd
		TPixel32 *pix = raster->pixels(y);
Toshihiro Shimizu 890ddd
		for (int x = 0; x < lx; ++x) {
Toshihiro Shimizu 890ddd
			TPixel32 color = *(pix + x);
Toshihiro Shimizu 890ddd
			ClusterElem *ce = new ClusterElem(color.r, color.g, color.b, (float)(color.m / 255.0));
Toshihiro Shimizu 890ddd
			cluster->insert(ce);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	raster->unlock();
Toshihiro Shimizu 890ddd
	cluster->computeStatistics();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	clusters.push_back(cluster);
Toshihiro Shimizu 890ddd
	clusterize(clusters, maxColorCount);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	palette.clear();
Toshihiro Shimizu 890ddd
	//palette.reserve( clusters.size());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < clusters.size(); ++i) {
Toshihiro Shimizu 890ddd
		ClusterStatistic &stat = clusters[i]->statistic;
Toshihiro Shimizu 890ddd
		TPixel32 col((int)(stat.sumComponents[0] / stat.elemsCount * 255),
Toshihiro Shimizu 890ddd
					 (int)(stat.sumComponents[1] / stat.elemsCount * 255),
Toshihiro Shimizu 890ddd
					 (int)(stat.sumComponents[2] / stat.elemsCount * 255),
Toshihiro Shimizu 890ddd
					 255);
Toshihiro Shimizu 890ddd
		palette.insert(col);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		clearPointerContainer(clusters[i]->data);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	clearPointerContainer(clusters);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#define DISTANCE 3
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool inline areNear(const TPixel &c1, const TPixel &c2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (abs(c1.r - c2.r) > DISTANCE)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	if (abs(c1.g - c2.g) > DISTANCE)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	if (abs(c1.b - c2.b) > DISTANCE)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	if (abs(c1.m - c2.m) > DISTANCE)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool find(const std::set<tpixel32> &palette, const TPixel &color)</tpixel32>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::set<tpixel32>::const_iterator it = palette.begin();</tpixel32>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (it != palette.end()) {
Toshihiro Shimizu 890ddd
		if (areNear(*it, color))
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
		++it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-- 似ている色をまとめて1つのStyleにする --*/
Toshihiro Shimizu 890ddd
void TColorUtils::buildPalette(std::set<tpixel32> &palette, const TRaster32P &raster, int maxColorCount)</tpixel32>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int lx = raster->getLx();
Toshihiro Shimizu 890ddd
	int ly = raster->getLy();
Toshihiro Shimizu 890ddd
	int wrap = raster->getWrap();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int x, y;
Toshihiro Shimizu 890ddd
	TPixel old = TPixel::Black;
Toshihiro Shimizu 890ddd
	int solidColors = 0;
Toshihiro Shimizu 890ddd
	int count = maxColorCount;
Toshihiro Shimizu 890ddd
	raster->lock();
Toshihiro Shimizu 890ddd
	for (y = 1; y < ly - 1 && count > 0; y++) {
Toshihiro Shimizu 890ddd
		TPixel *pix = raster->pixels(y);
Toshihiro Shimizu 890ddd
		for (x = 1; x < lx - 1 && count > 0; x++, pix++) {
Toshihiro Shimizu 890ddd
			TPixel color = *pix;
Toshihiro Shimizu 890ddd
			if (areNear(color, *(pix - 1)) && areNear(color, *(pix + 1)) &&
Toshihiro Shimizu 890ddd
				areNear(color, *(pix - wrap)) && areNear(color, *(pix + wrap)) &&
Toshihiro Shimizu 890ddd
				areNear(color, *(pix - wrap - 1)) && areNear(color, *(pix - wrap + 1)) &&
Toshihiro Shimizu 890ddd
				areNear(color, *(pix + wrap - 1)) && areNear(color, *(pix + wrap + 1))) {
Toshihiro Shimizu 890ddd
				solidColors++;
Toshihiro Shimizu 890ddd
				if (!areNear(*pix, old) && !find(palette, *pix)) {
Toshihiro Shimizu 890ddd
					old = color;
Toshihiro Shimizu 890ddd
					count--;
Toshihiro Shimizu 890ddd
					palette.insert(color);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	raster->unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (solidColors < lx * ly / 2) {
Toshihiro Shimizu 890ddd
		palette.clear();
Toshihiro Shimizu 890ddd
		buildPaletteForBlendedImages(palette, raster, maxColorCount);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-- 全ての異なるピクセルの色を別のStyleにする --*/
Toshihiro Shimizu 890ddd
void TColorUtils::buildPrecisePalette(std::set<tpixel32> &palette, const TRaster32P &raster, int maxColorCount)</tpixel32>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int lx = raster->getLx();
Toshihiro Shimizu 890ddd
	int ly = raster->getLy();
Toshihiro Shimizu 890ddd
	int wrap = raster->getWrap();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int x, y;
Toshihiro Shimizu 890ddd
	int count = maxColorCount;
Toshihiro Shimizu 890ddd
	raster->lock();
Toshihiro Shimizu 890ddd
	for (y = 1; y < ly - 1 && count > 0; y++) {
Toshihiro Shimizu 890ddd
		TPixel *pix = raster->pixels(y);
Toshihiro Shimizu 890ddd
		for (x = 1; x < lx - 1 && count > 0; x++, pix++) {
Toshihiro Shimizu 890ddd
			if (!find(palette, *pix)) {
Toshihiro Shimizu 890ddd
				TPixel color = *pix;
Toshihiro Shimizu 890ddd
				count--;
Toshihiro Shimizu 890ddd
				palette.insert(color);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	raster->unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*-- 色数が最大値を超えたら、似ている色をまとめて1つのStyleにする手法を行う --*/
Toshihiro Shimizu 890ddd
	if (count == 0) {
Toshihiro Shimizu 890ddd
		palette.clear();
Toshihiro Shimizu 890ddd
		buildPalette(palette, raster, maxColorCount);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------