/* +---------------------------------------------------------------------------+
   |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
   |                                                                           |
   |                   http://mrpt.sourceforge.net/                            |
   |                                                                           |
   |   Copyright (C) 2005-2008  University of Malaga                           |
   |                                                                           |
   |    This software was written by the Perception and Robotics               |
   |      research group, University of Malaga (Spain).                        |
   |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
   |                                                                           |
   |  This file is part of the MRPT project.                                   |
   |                                                                           |
   |     MRPT is free software: you can redistribute it and/or modify          |
   |     it under the terms of the GNU General Public License as published by  |
   |     the Free Software Foundation, either version 3 of the License, or     |
   |     (at your option) any later version.                                   |
   |                                                                           |
   |   MRPT is distributed in the hope that it will be useful,                 |
   |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
   |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
   |     GNU General Public License for more details.                          |
   |                                                                           |
   |     You should have received a copy of the GNU General Public License     |
   |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
   |                                                                           |
   +---------------------------------------------------------------------------+ */
#ifndef CFeatureExtraction_H
#define CFeatureExtraction_H

#include <MRPT/UTILS/CMRPTImage.h>
#include <MRPT/UTILS/CMRPTImageFloat.h>
#include <MRPT/UTILS/CTicTac.h>
#include <MRPT/MRVL/CImageConvolution.h>
#include <MRPT/MRVL/VisionUtils.h>
#include <MRPT/MRVL/CFeature.h>

namespace MRVL
{
	class CFeatureExtraction
	{
	public:
		enum TMethodExtraction
		{
			extMethodKLT = 0,
			extMethodHarris,
			extMethodBCD,
			extMethodSIFT
		};

		struct TOptions
		{
			/** Initalizer
			*/
			TOptions();

			/** Method of the extraction
			*/
			TMethodExtraction method;

			/** Size of the patch to extract
			*/
			unsigned int patchSize;

			struct TKLTOptions
			{
				/** KLT Options
				  */
				unsigned int window_width, window_height;
			} KLTOptions;

			struct THarrisOptions
			{
				/** Harris Options
				  */
				float threshold;
				float k;
				float sigma;
				int radius;		//pixels measured
			} harrisOptions;

			struct TBCDOptions
			{
				/** BCD Options
				  */
			} BCDOptions;

			struct TSIFTOptions
			{
				/** SIFT Options
				  */
			} SIFTOptions;

		} options;

		/** Constructor
		*/
		CFeatureExtraction();

		/** Virtual destructor.
		*/
		virtual ~CFeatureExtraction();

		/** Extract features from the image based on the method defined in TOptions.
		* \param img (input) The image from where to extract the images.
		* \param feats (output) A complete list of features (containing a patch for each one of them).
		* \param nDesiredFeatures (op. input) Number of features to be extracted. Default: authomatic.
		* \param x_min (op. input) Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param x_length (op. input) X Length of the region of interest. Default: All the image.
		* \param y_min (op. input) Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_length (op. input) Y Length of the region of interest. Default: All the image.
		*/
		void  extractFeatures(
			const CMRPTImage		&img,
			CFeatureList			&feats,
			unsigned int			nDesiredFeatures = 0,
			unsigned int			x_min = 0,
			unsigned int			x_length = 0,
			unsigned int			y_min = 0,
			unsigned int			y_length = 0);

		//// ********************** FAMD ***********************//
		//// Por ahora he puesto esta funcion en la seccion publica para que se pueda llamar desde fuera y no meterla en el 'switch' principal
		///** Extract features from the image based on the SIFT binary provided by Lowe Demo.
		//* \param img File name of the image to be processed (must be in PGM format).
		//* \param features (out) List of detected features (all field in the feature struct are filled).
		//*/
		//void  extractFeaturesSIFT(
		//	std::string &img,
		//	TSIFTFeatureList &features,
		//	unsigned int nFeatures = 0);
		// ********************** END FAMD ***********************//

	private:
		/** Extract features from the image based on the Harris method.
		* \param img The image from where to extract the images.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param nDesiredFeatures Number of features to be extracted. Default: authomatic.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param x_length X Length of the region of interest. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_length X Length of the region of interest. Default: All the image.
		*/
		void  extractFeaturesHarris(
			const CMRPTImageFloat	&img,
			vector_float			&x,
			vector_float			&y,
			int						nDesiredFeatures = -1,
			unsigned int			x_min = 0,
			unsigned int			x_length = 0,
			unsigned int			y_min = 0,
			unsigned int			y_length = 0);

		/** Extract features from the image based on the Harris method employing the classical algorithm.
		* \param img The image from where to extract the images.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param nDesiredFeatures Number of features to be extracted. Default: authomatic.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		*/
		void  HarrisCommon(
			const CMRPTImageFloat	&imgR,
			vector_float			&x,
			vector_float			&y,
			int						nDesiredFeatures,
			unsigned int			x_min,
			unsigned int			y_min);


		/** Extract features from the image based on the Harris method and distributing the features over the image.
		* \param img The image from where to extract the images.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param nDesiredFeatures Number of features to be extracted. Default: authomatic.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		*/
		void  HarrisMask(
			const CMRPTImageFloat	&imgR,
			vector_float			&x,
			vector_float			&y,
			int						nDesiredFeatures,
			unsigned int			x_min,
			unsigned int			y_min);

		/** Extract features from the image based on the KLT method.
		* \param img The image from where to extract the images.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param nDesiredFeatures Number of features to be extracted. Default: authomatic.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param x_length X Length of the region of interest. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_length X Length of the region of interest. Default: All the image.
		*/
		void  extractFeaturesKLT(
			const CMRPTImage		&img,
			CFeatureList			&feats,
			unsigned int			nDesiredFeatures = 0,
			unsigned int			x_min = 0,
			unsigned int			x_length = 0,
			unsigned int			y_min = 0,
			unsigned int			y_length = 0);

		/** Extract features from the image based on the BCD method.
		* \param img The image from where to extract the images.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param nDesiredFeatures Number of features to be extracted. Default: authomatic.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param x_length X Length of the region of interest. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_length X Length of the region of interest. Default: All the image.
		*/
		void  extractFeaturesBCD(
			const CMRPTImage 		&img,
			CFeatureList			&feats,
			unsigned int			nDesiredFeatures = 0,
			unsigned int			x_min = 0,
			unsigned int			x_length = 0,
			unsigned int			y_min = 0,
			unsigned int			y_length = 0);

		/** Extract features from the image based on the SIFT method.
		* \param img The image from where to extract the images.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param nDesiredFeatures Number of features to be extracted. Default: authomatic.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param x_length X Length of the region of interest. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_length X Length of the region of interest. Default: All the image.
		*/
		void  extractFeaturesSIFT(
			const CMRPTImage		&img,
			CFeatureList			&feats,
			unsigned int			nDesiredFeatures = 0,
			unsigned int			x_min = 0,
			unsigned int			x_length = 0,
			unsigned int			y_min = 0,
			unsigned int			y_length = 0);

		/** Select good features using the openCV implementation of the KLT method.
		* \param img (input) The image from where to select extract the images.
		* \param feats (output) A complete list of features (containing a patch for each one of them).
		* \param nDesiredFeatures (op. input) Number of features to be extracted. Default: authomatic.
		* \param omitPixels (op. input) A mask for determining the ROI. (0: do not omit this pixel, 1: omit this pixel)
		*/
		void  selectGoodFeaturesKLT( 
			const CMRPTImage	&inImg,
			CFeatureList		&feats,
			unsigned int		nDesiredFeatures = 0,
			CMatrix				*omitPixels = NULL);


	}; // end of class
} // end of namespace
#endif
