#ifndef __POINTERRECOGNITION_HH
#define __POINTERRECOGNITION_HH

#include <boost/numeric/ublas/vector.hpp>
#include <boost/smart_ptr.hpp>
#include "image.h"
#include "cameraProjectorCalibration.hh"

/// Class for recognising pointer.
class PointerRecognition
{
///
public:
  ///
  typedef boost::numeric::ublas::vector< double > Vector;
  /** Constructor.
      @param _cameraProjectorCalibration Smart pointer to calibration object.
      @param _refImg Reference image with the colours to recognise the pointer. */
  PointerRecognition( CameraProjectorCalibrationPtr _cameraProjectorCalibration,
                      const mimas::image< mimas::rgba< unsigned char > > &_refImg );        
  /// Change reference image (and recompute colour histogram).
  void setReferenceImage
     ( const mimas::image< mimas::rgba< unsigned char > > &_refImg );
  /** Perform recognition.
      @param _frame Camera image
      @param camPos On success the estimated pointer position in the camera
      image.
      @param pos On success the estimated pointer position on the screen
      (computed using the camera calibration).
      @return \c true if pointer was recognised */
  bool findPointer
  ( const mimas::image< mimas::rgba< unsigned char > > &_frame,
    Vector &camPos, Vector &pos )
    throw (mimas::mimasexception);
  /** Segmented image from the last recognition step.
      The image is stored so that it can be displayed for information. */
  mimas::image< unsigned char > getSegmentedImage(void) const
    { return segmentedImage; }
  /** Set active screen area for recognition.
      Estimated pointer coordinates outside this area will be considered
      to be erroneous. */
  void setClip( int _x, int _y, int _w, int _h )
    { x =_x; y = _y; w = _w; h = _h; }
  ///
  void setThreshold( double _threshold ) { threshold = _threshold; }
  ///
  void setSigma( double _sigma );
  ///
  void setTrackingRange( int _trackingRange )
    { trackingRange = _trackingRange; }
  ///
  int getMinX(void) { return minX; }
  ///
  int getMinY(void) { return minY; }
  ///
  int getMaxX(void) { return maxX; }
  ///
  int getMaxY(void) { return maxY; }
protected:
  ///
  CameraProjectorCalibrationPtr cameraProjectorCalibration;
  /** Clipping coordinates (active screen are for recognition)
      @see setClip
      @name Clipping coordinates
      @{ */
  ///
  int x;
  ///
  int y;
  ///
  int w;
  ///
  int h;
  ///@}
  /// Colour histogram computed from reference image.
  boost::multi_array< int, 3 > histogram;
  ///
  int numPixels;
  /// Threshold used in colour segmentation.
  double threshold;
  ///
  double sigma;
  ///
  int minSize;
  /** Segmented image of last recognition step.
      @see getSegmentedImage */
  mimas::image< unsigned char > segmentedImage;
  ///
  bool haveOldPos;
  ///
  int oldX;
  ///
  int oldY;
  ///
  int deltaX;
  ///
  int deltaY;
  ///
  int minX;
  ///
  int minY;
  ///
  int maxX;
  ///
  int maxY;
  ///
  int trackingRange;
};

///
typedef boost::shared_ptr< PointerRecognition > PointerRecognitionPtr;

#endif