#include "MRegressionRGB.h"

//-------------------------------------------------------------------------------
// コンストラクタ
CMRegressionRGB::CMRegressionRGB(const int dim) : CMRegression(dim)
{
}

//-------------------------------------------------------------------------------
// デストラクタ
CMRegressionRGB::~CMRegressionRGB(void)
{
}

//-------------------------------------------------------------------------------
// 推定行列の算出に使う値を返す
double CMRegressionRGB::GetX(const CvMat *mat, const int sample, const int index)
{
	CvScalar v0 = cvGet2D(mat, sample, 0);
	CvScalar v1 = cvGet2D(mat, sample, 1);
	CvScalar v2 = cvGet2D(mat, sample, 2);

	switch (index)
	{
	case  0: return 1.0;
	case  1: return v0.val[0];
	case  2: return v1.val[0];
	case  3: return v2.val[0];
	case  4: return v0.val[0] * v1.val[0];
	case  5: return v1.val[0] * v2.val[0];
	case  6: return v2.val[0] * v0.val[0];
	case  7: return v0.val[0] * v0.val[0];
	case  8: return v1.val[0] * v1.val[0];
	case  9: return v2.val[0] * v2.val[0];
	case 10: return v0.val[0] * v1.val[0] * v2.val[0];
	case 11: return v0.val[0] * v0.val[0] * v0.val[0];
	case 12: return v1.val[0] * v1.val[0] * v1.val[0];
	case 13: return v2.val[0] * v2.val[0] * v2.val[0];
	}

	return 0;
}

//-------------------------------------------------------------------------------
// 推定行列の算出に使う値を返す
bool CMRegressionRGB::CalcCoef(const CvMat *data, const CvMat *observ)
{
	CALL(CMRegression::CalcCoef(data, observ));

#ifdef SHOW_REGRESSION_COEF
	GShowMat(m_Coef, "Conversion Matrix", "%8.3f");

	CALL(CMRegression::CalcError(data, observ));
	GShowMat(m_Error, "Estimation error", "%9.5f");
#endif // SHOW_REGRESSION_COEF

	return true;
}

//-------------------------------------------------------------------------------
// 変換した行列データを生成する
CvMat *CMRegressionRGB::GenConvert(const CvMat *data)
{
	// 従来の処理へ
	return CMRegression::GenConvert(data);
	// GenMatを使わないで計算する（遅い）
	//return GenConvertNoGetX(data);
}

//-------------------------------------------------------------------------------
// 変換した行列データを生成する（GenMatを使わないバージョン：遅い）
CvMat *CMRegressionRGB::GenConvertNoGenMat(const CvMat *data)
{
	// 行列の確保
	CvMat *convert = cvCreateMat(data->rows, data->cols, CV_64FC1);

	// 係数の取得
	double *b[COLOR];
	for (int col = 0; col < data->cols; col ++)
	{
		b[col] = new double [m_Dim];
		for (int i = 0; i < m_Dim; i ++) b[col][i] = cvmGet(m_Coef, i, col);
	}

#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic)
#endif
 	for (int sample = 0; sample < data->rows; sample ++)
	{
		for (int col = 0; col < data->cols; col ++)
		{
			double y = 0;
			for (int i = 0; i < m_Dim; i ++) 
				y += GetX(data, sample, i) * b[col][i];
			cvmSet(convert, sample, col, y);
		}
	}

	return convert;
}

//-------------------------------------------------------------------------------
// 画像を変換しデータを生成する（係数行列が計算済みであることが前提）
IplImage *CMRegressionRGB::GenConvert(const IplImage *dataImg)
{
	return CMRegression::GenConvert(dataImg);
}
