/** 
* @file PHOGFeature.h
* @author Alexander Lütz
* @date 15/11/2011

*/
#ifndef _NICE_OBJREC_PHOGFEATUREINCLUDE
#define _NICE_OBJREC_PHOGFEATUREINCLUDE

#include "core/basics/Config.h"
// #include "vislearning/cbaselib/MultiDataset.h"
#include "Image_tools.h"

namespace OBJREC {
  
/** @class PHOGFeature
 * Implementation of the PHOG-Features and corresponding Kernel as done by Anna Bosch et al.
 *
 * @author Alexander Lütz
 */


class PHOGFeature
{

	public:
		enum Histrogram_concatenation{NONE=0, LEVELWISE=1, ALL=2};

	protected:
		
	Image_tools image_tool;
	int number_Of_Bins;
	bool unsignedBins;
	int number_of_Levels;
	bool like_AnnaBosch;
	bool distances_only_between_levels;
	Histrogram_concatenation histrogram_concatenation;
	bool verbose;

	/** Calculates the PHOG-Pyramide for given gradient images (idea of Anna Bosch and Andrew Zisserman)*/
	void calculate_PHOG_Pyramide(const NICE::Image & gradient_orientations, const NICE::ImageT<float> & gradient_magnitudes,std::vector< std::vector<float> > & PHOG_descriptor);

	/** Calculates resulting PHOG-Features for the specified ROI in the given image*/
	std::vector< std::vector<float> > calculate_PHOG_Features(const NICE::Image & orig_Image, const NICE::Rect & roi);

    public:
		PHOGFeature();

		/** recommended constructor */
		PHOGFeature( const NICE::Config *conf, std::string section = "PHOGFeature");

		/** simple destructor */
		virtual ~PHOGFeature();

//  		std::vector<std::vector< std::vector<float> > > createAllFeatureVectors(const OBJREC::LabeledSet::Permutation & order);
// 
// 		std::vector<std::vector< std::vector<float> > > createAllFeatureVectors(const OBJREC::LabeledSet::Permutation & order, std::vector< NICE::Image > & gradient_orientations, std::vector< NICE::ImageT<float> > & gradient_magnitudes);
// 
// 		std::vector<std::vector< std::vector<float> > > createAllFeatureVectors(const OBJREC::LabeledSet::Permutation & order, const std::vector<int> & trainSelection);


		std::vector< std::vector<float> > createOneFeatureVector(const std::string & imgfilename, const NICE::Rect & ROI);
		std::vector< std::vector<float> > createOneFeatureVector(const NICE::Image img, const NICE::Rect & ROI);
		std::vector< std::vector<float> > createOneFeatureVector(const std::string & imgfilename);
		std::vector< std::vector<float> > createOneFeatureVector(const NICE::Image img);

		/** computes the featurevector for the given image, which is already converted to a gradient-image*/
		std::vector< std::vector<float> > createOneFeatureVectorDirect(NICE::Image & gradient_orientations, NICE::ImageT<float> & gradient_magnitudes, const NICE::Rect & ROI);
		std::vector< std::vector<float> > createOneFeatureVectorDirect(NICE::Image & gradient_orientations, NICE::ImageT<float> & gradient_magnitudes);

// 		std::vector< NICE::Image> calculate_gradient_orientations(const OBJREC::LabeledSet::Permutation & order);
// 		std::vector< NICE::ImageT<float> > calculate_gradient_magnitudes(const OBJREC::LabeledSet::Permutation &
		NICE::Image calculate_gradient_orientations(const std::string & imgfilename);
		NICE::ImageT<float> calculate_gradient_magnitudes(const std::string & imgfilename);

		/**Compute the resulting kernel measuring the distance between the given feature-vectores*/
		void calculate_Kernel_from_Features(const std::vector<std::vector< std::vector<float> > > & PHoG_Features, NICE::Matrix & PHoG_Kernel);

		virtual double measureDistance ( const std::vector< std::vector<float> > & a, const std::vector< std::vector<float> > & b  );

		virtual void sayYourName() {std::cerr << "I'm the PHOG-Feature." << std::endl;};

		void set_verbose(const bool & new_verbose);
		void set_histrogram_concatenation(const Histrogram_concatenation & _histrogram_concatenation){histrogram_concatenation = _histrogram_concatenation;};
};

}

#endif