#include <FaceClassifier/WholeSVMFaceClassifier.h>

#include <opencv/cvaux.h>

namespace face {

void WholeSVMFaceClassifier::init()
{
	nOfFeatures = height * width;
}

WholeSVMFaceClassifier::WholeSVMFaceClassifier()
{
}

WholeSVMFaceClassifier::WholeSVMFaceClassifier(const std::string name, const std::map<float, std::string> classLabel, const int width, const int height) : SVMFaceClassifier(name, classLabel, width, height)
{
	init();
	std::cout << ToString() << " constructed.\n";
}

WholeSVMFaceClassifier::WholeSVMFaceClassifier(const std::string name, const std::map<float, std::string> classLabel, const int width, const int height, const std::string modelFile) : SVMFaceClassifier(name, classLabel, width, height, modelFile)
{
	init();
	std::cout << ToString() << " constructed.\n";
}

WholeSVMFaceClassifier::~WholeSVMFaceClassifier()
{
}

std::string WholeSVMFaceClassifier::ToString()
{
	std::stringstream ss;
	ss << "WholeSVMClassifier [\n" <<
		"\tname = \"" + name + "\"\n";
	if (modelFile != "") ss << "\tmodelFile = \"" + modelFile + "\"\n";
	ss << "\tclassLabels [\n";
	if (!classLabel.empty()) {
		std::map<float, std::string>::iterator itr;
		for (itr = classLabel.begin(); itr != classLabel.end(); itr++) {
			ss << "\t\t" << (*itr).first << " refers to \"" + (*itr).second + "\"\n";
		}
	}
	ss << "\t]\n\twidth = " << width << "\n\theight = " << height << "\n\tnOfFeatures = " << nOfFeatures << "\n]";
	return ss.str();
}

IplImage *WholeSVMFaceClassifier::Preprocess(const IplImage * const img)
{
	IplImage *grayImg = cvCreateImage(cvSize(img->width, img->height), img->depth, 1);
	IplImage *ret = cvCreateImage(cvSize(this->width, this->height), img->depth, 1);
	if (img->nChannels == 1) {
		cvCopyImage(img, grayImg);
	}
	else {
		cvCvtColor(img, grayImg, CV_RGB2GRAY);
	}
	cvEqualizeHist(grayImg, grayImg);
	cvResize(grayImg, ret, CV_INTER_LINEAR);
	cvReleaseImage(&grayImg);
	return ret;
}

void WholeSVMFaceClassifier::CreateFeatureVector(const IplImage * const img, CvMat * const fv)
{
	IplImage *preprocessedImg = Preprocess(img);
	IplImage *floatImg = cvCreateImage(cvGetSize(preprocessedImg), IPL_DEPTH_32F, 1);
	cvCvtScale(preprocessedImg, floatImg, 1.0 / 255);
	CvMat *cpyMtx = cvCreateMatHeader(floatImg->height, floatImg->width, CV_32FC1);
	float *row = (float*)cvPtr2D(fv, 0, 0);
	cvSetData(cpyMtx, row, cpyMtx->step);
	cvCopy(floatImg, cpyMtx);
	cvReleaseImage(&preprocessedImg);
	cvReleaseImage(&floatImg);
	cvReleaseMatHeader(&cpyMtx);
}

}
