;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; LUSH Lisp Universal Shell
;;;   Copyright (C) 2002 Leon Bottou, Yann Le Cun, AT&T Corp, NECI.
;;; Includes parts of TL3:
;;;   Copyright (C) 1987-1999 Leon Bottou and Neuristique.
;;; Includes selected parts of SN3.2:
;;;   Copyright (C) 1991-2001 AT&T Corp.
;;;
;;; Includes information derived from the GSL (Gnu Scientific Library)
;;;   header files which are copyrighted and distributed under the GPL
;;;   by their respective authors.
;;;
;;; This program 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 2 of the License, or
;;; (at your option) any later version.
;;;
;;; This program 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 this program; if not, write to the Free Software
;;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(libload "opencv/cv-config")



#? *** hmm

;; dummy function that adds OpenCV C header files in C file
(eval `(de dummy_hmm () ,cv-cpheader-cmd ()))

;; #? * (dummy_hmm)
;; #? * (cvcreate2dhmm <statenumber> <nummix> <obssize>)
;; #? * (cvrelease2dhmm <hmm>)
;; #? * (cvcreateobsinfo <numobs> <obssize>)
;; #? * (cvreleaseobsinfo <obs_info>)
;; #? * (cvimgtoobs_dct <array> <obs> <dctsize> <obssize> <delta>)
;; #? * (cvuniformimgsegm <obs_info> <ehmm>)
;; #? * (cvinitmixsegm <obs_info_array> <num_img> <hmm>)
;; #? * (cvestimatehmmstateparams <obs_info_array> <num_img> <hmm>)
;; #? * (cvestimatetransprob <obs_info_array> <num_img> <hmm>)
;; #? * (cvestimateobsprob <obs_info> <hmm>)
;; #? * (cveviterbi <obs_info> <hmm>)
;; #? * (cvmixsegml2 <obs_info_array> <num_img> <hmm>)
;; #? * (cvkmeans <num_clusters> <samples> <num_samples> <vec_size> <termcrit> <cluster>)

;; ********************************************************

;;  //*F//////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvCreate2DHMM
;;  //    Purpose: The function allocates memory for 2-dimensional embedded HMM model
;;  //             after you finish work with created HMM you must free memory
;;  //             by calling cvRelease2DHMM function
;;  //    Context:
;;  //    Parameters: stateNumber - array of hmm sizes(size of array == state_number[0]+1 )
;;  //                numMix - number of gaussian mixtures in low-level HMM states
;;  //                          size of array is defined by previous array values
;;  //                obsSize - length of observation vectors
;;  //
;;  //    Returns:
;;  //      Created 2D HMM.
;;  //    Notes: stateNumber[0] - number of states in external HMM.
;;  //           stateNumber[i] - number of states in embedded HMM
;;  //
;;  //           example for face recognition: state_number = { 5 3 6 6 6 3 },
;;  //                                         length of num_mix array = 3+6+6+6+3 = 24
;;  //
;;  //F*/
;;  OPENCVAPI  CvEHMM*  cvCreate2DHMM( int* stateNumber, int* numMix, int obsSize );

(de cvCreate2DHMM (statenumber nummix  obssize)
    ((-gptr- "int *") statenumber  nummix)
    ((-int-) obssize)
    (gptr #{ cvCreate2DHMM($statenumber, $nummix, $obssize) #} ))

;;  //*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvRelease2DHMM
;;  //    Purpose: The function free memory used by CvEHMM structure
;;  //    Context:
;;  //    Parameters: hmm - address of pointer to CvEHMM structure
;;  //    Returns:
;;  //    Notes:  function set *hmm = 0
;;  //F*/
;;  OPENCVAPI  void  cvRelease2DHMM( CvEHMM** hmm );

(de cvRelease2DHMM (hmm)
    ((-gptr- "CvEHMM **") hmm)
    #{ cvRelease2DHMM($hmm); #}
    ())

;;  //*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvCreateObsInfo
;;  //    Purpose: The function allocates memory for CvImgObsInfo structure
;;  //             after you finish working with allocated structure - destroy it
;;  //             by  cvReleaseObsInfo
;;  //
;;  //    Context:
;;  //    Parameters: numObs  - number of horizontal and vertical observations.
;;  //                          Total number of allocated observation vectors
;;  //                          will be   num_obs.width*num_obs.height
;;  //                obsSize - length of observation vector
;;  //
;;  //    Returns:  Parameter obs_info is filled.
;;  //
;;  //    Notes: If you extract observations from an image, use CV_COUNT_OBS macro
;;  //           to compute "numObs" parameter:
;;  //
;;  //           CV_COUNT_OBS( &roi, &obs, &delta, &numObs),
;;  //
;;  //                          where CvSize roi   - image ROI
;;  //                                CvSize obs   - size of image block (a single observation)
;;  //                                CvSize delta - horizontal and vertical shift
;;  //                                           (i.e. because observation blocks overlap if
;;  //                                            delta.width < obs.width or
;;  //                                            delta.height < obs.height )
;;  //                                CvSize numObs - output parameter to be computed
;;  //
;;  //F*/
;;  OPENCVAPI  CvImgObsInfo*  cvCreateObsInfo( CvSize numObs, int obsSize );

(de cvCreateObsInfo( numobs   obssize)
    ((-gptr- "CvSize *") numobs)
    ((-int-) obssize)
    (gptr #{ cvCreateObsInfo(*$numobs, $obssize) #} ))


;;  //*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvReleaseObsInfo
;;  //    Purpose: The function free memory used by CvImgObsInfo structure
;;  //
;;  //    Context:
;;  //    Parameters: obs_info - address of pointer to CvImgObsInfo structure
;;  //    Returns:
;;  //    Notes:  function sets *obs_info = 0
;;  //F*/
;;  OPENCVAPI  void  cvReleaseObsInfo( CvImgObsInfo** obs_info );

(de cvReleaseObsInfo( obs_info)
    ((-gptr- "CvImgObsInfo **") obs_info)
    #{ cvReleaseObsInfo($obs_info); #}
    ())

;;  //*F//////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvImgToObs_DCT
;;  //    Purpose: The function takes as input an image and returns the sequnce of observations
;;  //             to be used with an embedded HMM; Each observation is top-left block of DCT
;;  //             coefficient matrix.
;;  //    Context:
;;  //    Parameters: img     - pointer to the original image
;;  //                obs     - pointer to resultant observation vectors
;;  //                dctSize - size of the block for which DCT is calculated
;;  //                obsSize - size of top-left block of DCT coeffs matrix, which is treated
;;  //                          as observation. Each observation vector consists of
;;  //                          obsSize.width * obsSize.height floats.
;;  //                          The following conditions should be satisfied:
;;  //                          0 < objSize.width <= dctSize.width,
;;  //                          0 < objSize.height <= dctSize.height.
;;  //                delta   - dctBlocks are overlapped and this parameter specifies horizontal
;;  //                          and vertical shift.
;;  //    Returns:
;;  //
;;  //    Notes:
;;  //      The algorithm is following:
;;  //          1. First, number of observation vectors per row and per column are calculated:
;;  //
;;  //             Nx = floor((roi.width - dctSize.width + delta.width)/delta.width);
;;  //             Ny = floor((roi.height - dctSize.height + delta.height)/delta.height);
;;  //
;;  //             So, total number of observation vectors is Nx*Ny, and total size of
;;  //             array obs must be >= Nx*Ny*obsSize.width*obsSize.height*sizeof(float).
;;  //          2. Observation vectors are calculated in the following loop
;;  //             ( actual implementation may be different ), where
;;  //               I[x1:x2,y1:y2] means block of pixels from source image with
;;  //               x1 <= x < x2, y1 <= y < y2,
;;  //               D[x1:x2,y1:y2] means sub matrix of DCT matrix D.
;;  //               O[x,y] means observation vector that corresponds to position
;;  //              (x*delta.width,y*delta.height) in the source image
;;  //             ( all indices are counted from 0 ).
;;  //
;;  //               for( y = 0; y < Ny; y++ )
;;  //               {
;;  //                   for( x = 0; x < Nx; x++ )
;;  //                   {
;;  //                       D = DCT(I[x*delta.width : x*delta.width + dctSize.width,
;;  //                                  y*delta.height : y*delta.height + dctSize.height]);
;;  //                       O[x,y] = D[0:obsSize.width, 0:obsSize.height];
;;  //                   }
;;  //               }
;;  //F*/
;;  OPENCVAPI  void  cvImgToObs_DCT( const CvArr* array, float* obs, CvSize dctSize,
;;                                   CvSize obsSize, CvSize delta );

(de cvImgToObs_DCT (array  obs  dctsize  obssize  delta)
    ((-gptr- "const CvArr *") array)
    ((-gptr- "float *") obs)
    ((-gptr- "CvSize *") dctsize  obssize  delta)
    #{ cvImgToObs_DCT($array, $obs, *$dctsize, *$obssize, *$delta); #}
    ())

;;  //*F//////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvUniformImgSegm
;;  //    Purpose: The uniformly segments all observation vectors extracted from image
;;  //    Context:
;;  //    Parameters: obs_info - observations structure
;;  //                hmm      - 2D embedded HMM structure
;;  //
;;  //    Returns:
;;  //    Notes:
;;  //F*/
;;  OPENCVAPI  void  cvUniformImgSegm( CvImgObsInfo* obs_info, CvEHMM* ehmm );

(de cvUniformImgSegm( obs_info  ehmm)
    ((-gptr- "CvImgObsInfo *") obs_info)
    ((-gptr- "CvEHMM *") ehmm)
    #{ cvUniformImgSegm ($obs_info, $ehmm); #}
    ())

;;  /*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvInitMixSegm
;;  //    Purpose: The function implements the mixture segmentation of the states
;;  //             of the embedded HMM
;;  //
;;  //    Context: used with the Viterbi training of the embedded HMM
;;  //             Function uses K-Means algorithm for clustering.
;;  //
;;  //    Parameters:  obs_info_array - array of pointers to image observations
;;  //                 num_img - length of above array
;;  //                 hmm - pointer to HMM structure
;;  //
;;  //    Returns:
;;  //    Notes:
;;  //F*/
;;  OPENCVAPI  void  cvInitMixSegm( CvImgObsInfo** obs_info_array,
;;                                 int num_img, CvEHMM* hmm );

(de cvInitMixSegm (obs_info_array   num_img   hmm)
    ((-gptr- "CvImgObsInfo **") obs_info_array)
    ((-int-) num_img)
    ((-gptr- "CvEHMM *") hmm)
    #{  cvInitMixSegm($obs_info_array, $num_img, $hmm); #}
    ())

;;  /*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvEstimHMMStateParams
;;  //    Purpose: function calculates means, variances, weights of every Gaussian mixture
;;  //             of every low-level state of embedded HMM
;;  //    Context:
;;  //    Parameters:  obs_info_array - array of pointers to observation structures
;;  //                 num_img  - length of above array
;;  //                 hmm      - hmm structure
;;  //
;;  //    Returns:
;;  //
;;  //    Notes:
;;  //F*/
;;  OPENCVAPI  void  cvEstimateHMMStateParams( CvImgObsInfo** obs_info_array,
;;                                          int num_img, CvEHMM* hmm );

(de cvEstimateHMMStateParams (obs_info_array  num_img  hmm)
    ((-gptr- "CvImgObsInfo **") obs_info_array)
    ((-int-) num_img)
    ((-gptr- "CvEHMM *") hmm)
    #{ cvEstimateHMMStateParams($obs_info_array, $num_img, $hmm); #}
    ())

;;  /*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvEstimateTransProb
;;  //    Purpose: function computes transition probability matrices of embedded HMM
;;  //             given observations segmentation
;;  //
;;  //    Context:
;;  //    Parameters:  obs_info_array - array of pointers to observation structures
;;  //                 num_img  - length of above array
;;  //                 hmm      - hmm structure
;;  //
;;  //    Returns:
;;  //
;;  //    Notes:
;;  //F*/
;;  OPENCVAPI  void  cvEstimateTransProb( CvImgObsInfo** obs_info_array,
;;                                     int num_img, CvEHMM* hmm );

(de cvEstimateTransProb (obs_info_array  num_img  hmm)
    ((-gptr- "CvImgObsInfo **") obs_info_array)
    ((-int-) num_img)
    ((-gptr- "CvEHMM *") hmm)
    #{  cvEstimateTransProb($obs_info_array, $num_img, $hmm); #}
    ())

;;  /*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvEstimateTransProb
;;  //    Purpose: function computes probabilities of appearing observations at any state
;;  //           ( i.e. compute P(obs|state) for every pair(obs,state) )
;;  //    Context:
;;  //    Parameters:  obs_info - observations structure
;;  //                 hmm      - hmm structure
;;  //
;;  //    Returns:
;;  //    Notes:
;;  //F*/
;;  OPENCVAPI  void  cvEstimateObsProb( CvImgObsInfo* obs_info,
;;                                     CvEHMM* hmm );

(de cvEstimateObsProb (obs_info  hmm)
    ((-gptr- "CvImgObsInfo *") obs_info)
    ((-gptr- "CvEHMM *") hmm)
    #{ cvEstimateObsProb($obs_info, $hmm); #}
    ())

;;  /*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvEViterbi  (Embedded Viterbi)
;;  //    Purpose: The function calculates the embedded Viterbi algorithm
;;  //    Context:
;;  //    Parameters:
;;  //                obs_info - observations structure
;;  //                hmm      - hmm structure
;;  //
;;  //    Returns: the Embedded Viterbi logarithmic probability.
;;  //             Observations, stored in of obs_info structure are segmented
;;  //           ( but new segmentation does not affect mixture segmentation or
;;  //               states parameters )
;;  //    Notes:
;;  //F*/
;;  OPENCVAPI  float  cvEViterbi( CvImgObsInfo* obs_info, CvEHMM* hmm );

(de cvEViterbi (obs_info  hmm)
    ((-gptr- "CvImgObsInfo *") obs_info)
    ((-gptr- "CvEHMM *") hmm)
    (double #{ cvEViterbi($obs_info, $hmm) #}))

;;  /*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: cvMixSegmL2
;;  //    Purpose: function clusters observation vectors from several images
;;  //             given observations segmentation.
;;  //             Euclidean distance used for clustering vectors.
;;  //             Centers of clusters are given means of every mixture
;;  //
;;  //    Context: in HMM face recognition used after Viterbi segmentation
;;  //    Parameters:  obs_info_array - array of pointers to observation structures
;;  //                 num_img  - length of above array
;;  //                 hmm      - hmm structure
;;  //
;;  //    Returns:
;;  //    Notes:
;;  //F*/
;;  OPENCVAPI  void  cvMixSegmL2( CvImgObsInfo** obs_info_array,
;;                               int num_img, CvEHMM* hmm );
;;  /* end of HMM functions*/

(de cvMixSegmL2 (obs_info_array   num_img   hmm)
    ((-gptr- "CvImgObsInfo **") obs_info_array)
    ((-int-) num_img)
    ((-gptr- "CvEHMM *") hmm)
    #{ cvMixSegmL2($obs_info_array, $num_img, $hmm); #}
    ())

;;  /*F///////////////////////////////////////////////////////////////////////////////////////
;;  //    Name: KMeans
;;  //    Purpose: The function implements the K means algorithm, to cluster an array of sample
;;  //             vectors in a number of classes specified by numClusters
;;  //    Context:
;;  //    Parameters:  numClunster - the number of clusters
;;  //                 samples - the array of sample vectors
;;  //                 numSamples - the number of samples
;;  //                 VecSize - the size of each sample vector
;;  //                 termcrit.eps - the convergence error; the iterations to find the best cluster
;;  //                         centers will stop, when the value of the cost function at consecutive
;;  //                         iterations falls below this threshold
;;  //                 cluster - characteristic array. for every input vector indicates cluster
;;  //
;;  //    Returns: error code
;;  //
;;  //    Notes:
;;  //F*/
;;  OPENCVAPI  void  cvKMeans( int num_clusters, CvVect32f* samples, int num_samples,
;;                            int vec_size, CvTermCriteria termcrit, int* cluster  );
(de cvKMeans ( num_clusters  samples   num_samples  vec_size  termcrit  cluster)
    ((-int-) num_clusters num_samples  vec_size)
    ((-gptr- "CvVect32f *") samples)
    ((-gptr- "CvTermCriteria *") termcrit)
    ((-gptr- "int *") cluster)
    #{ cvKMeans($num_clusters, $samples, $num_samples, $vec_size, *$termcrit, $cluster); #}
    ())
;; ********************************************************

(dhc-make ()
  dummy_hmm
  cvcreate2dhmm
  cvrelease2dhmm
  cvcreateobsinfo
  cvreleaseobsinfo
  cvimgtoobs_dct
  cvuniformimgsegm
  cvinitmixsegm
  cvestimatehmmstateparams
  cvestimatetransprob
  cvestimateobsprob
  cveviterbi
  cvmixsegml2
  cvkmeans
)
