-- GENERATED by C->Haskell Compiler, version 0.16.3 Crystal Seed, 24 Jan 2009 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "./CV/TemplateMatching.chs" #-}{-#LANGUAGE ForeignFunctionInterface, ScopedTypeVariables#-}
module CV.TemplateMatching where

import Foreign.C.Types
import Foreign.Ptr
import Foreign.Storable
import Foreign.Marshal.Alloc

import CV.Image
import CV.Transforms

import Utils.Function
import Utils.Point
import Utils.Rectangle hiding (scale)

import CV.Image
{-# LINE 17 "./CV/TemplateMatching.chs" #-}
import System.IO.Unsafe

getTemplateMap image template = unsafePerformIO $
	   withImage image $ \cvimg ->
	    withImage template $ \cvtemp ->
         creatingImage $ templateImage cvimg cvtemp
         

data MatchType = SQDIFF
               | SQDIFF_NORMED
               | CCORR
               | CCORR_NORMED
               | CCOEFF
               | CCOEFF_NORMED
               
instance Enum MatchType where
  fromEnum SQDIFF = 0
  fromEnum SQDIFF_NORMED = 1
  fromEnum CCORR = 2
  fromEnum CCORR_NORMED = 3
  fromEnum CCOEFF = 4
  fromEnum CCOEFF_NORMED = 5

  toEnum 0 = SQDIFF
  toEnum 1 = SQDIFF_NORMED
  toEnum 2 = CCORR
  toEnum 3 = CCORR_NORMED
  toEnum 4 = CCOEFF
  toEnum 5 = CCOEFF_NORMED
  toEnum unmatched = error ("MatchType.toEnum: Cannot match " ++ show unmatched)

{-# LINE 36 "./CV/TemplateMatching.chs" #-}


simpleTemplateMatch :: MatchType -> Image GrayScale D32 -> Image GrayScale D32 -> ((Int,Int),Double)
simpleTemplateMatch mt image template 
	= unsafePerformIO $ do
	   withImage image $ \cvimg ->
	    withImage template $ \cvtemp ->
	     alloca $ \(ptrintx :: Ptr CInt) ->
	      alloca $ \(ptrinty :: Ptr CInt)->
	       alloca $ \(ptrdblval :: Ptr CDouble) -> do {
	        simpleMatchTemplate cvimg cvtemp ptrintx ptrinty ptrdblval (fromIntegral $ fromEnum mt);
		    x <- peek ptrintx;
			y <- peek ptrinty;
			v <- peek ptrdblval;
		    return ((fromIntegral x,fromIntegral y),realToFrac v); }

matchTemplate :: MatchType-> Image GrayScale D32 -> Image GrayScale D32 -> Image GrayScale D32 
matchTemplate mt image template = unsafePerformIO $ do
     let isize = getSize image
         tsize = getSize template
         size  = isize - tsize + (1,1) 
     res <- create size 
     withGenImage image $ \cimg -> 
      withGenImage template $ \ctempl ->
       withGenImage res $ \cresult -> 
        cvMatchTemplate cimg ctempl cresult (fromIntegral . fromEnum $ mt)
     return res


-- | Perform subpixel template matching using intensity interpolation
subPixelTemplateMatch :: MatchType -> Image GrayScale D32 -> Image GrayScale D32 -> Double -> (Double,Double)
subPixelTemplateMatch mt image template n -- TODO: Make iterative #SpeedUp
    = (fromIntegral (tx)+fromIntegral sbx/n 
      ,fromIntegral (ty)+fromIntegral sby/n)
     where
        (otw,oth) = getSize template
        ((orX,orY),_) = simpleTemplateMatch CCORR_NORMED image template
        (tx,ty) = (orX-otw`div`2, orY-oth`div`2)

        bigTempl = scaleSingleRatio Linear n template
        (tw,th) = getSize bigTempl
        region = scaleSingleRatio Linear n . getRegion (tx,ty) (otw*2,oth*2)  $ image
        ((sbx,sby),_) = simpleTemplateMatch CCORR_NORMED region bigTempl
     
regionToInt rc = mkRectangle (floor x,floor y) (ceiling w,ceiling h)
    where
        (x,y) = topLeft rc
        (w,h) = rSize rc

data ShapeMatchMethod = Method1
                      | Method2
                      | Method3
                      
instance Enum ShapeMatchMethod where
  fromEnum Method1 = 1
  fromEnum Method2 = 2
  fromEnum Method3 = 3

  toEnum 1 = Method1
  toEnum 2 = Method2
  toEnum 3 = Method3
  toEnum unmatched = error ("ShapeMatchMethod.toEnum: Cannot match " ++ show unmatched)

{-# LINE 93 "./CV/TemplateMatching.chs" #-}


-- | Match shapes
matchShapes :: ShapeMatchMethod -> Image GrayScale D8 -> Image GrayScale D8 -> Double
matchShapes m a b = unsafePerformIO $ do
    withGenImage a $ \c_a ->
     withGenImage b $ \c_b ->
       cvMatchShapes c_a c_b (fromIntegral . fromEnum $ m) 0 
        >>= return.realToFrac

foreign import ccall safe "CV/TemplateMatching.chs.h templateImage"
  templateImage :: ((Ptr (BareImage)) -> ((Ptr (BareImage)) -> (IO (Ptr (BareImage)))))

foreign import ccall safe "CV/TemplateMatching.chs.h simpleMatchTemplate"
  simpleMatchTemplate :: ((Ptr (BareImage)) -> ((Ptr (BareImage)) -> ((Ptr CInt) -> ((Ptr CInt) -> ((Ptr CDouble) -> (CInt -> (IO ())))))))

foreign import ccall safe "CV/TemplateMatching.chs.h cvMatchTemplate"
  cvMatchTemplate :: ((Ptr ()) -> ((Ptr ()) -> ((Ptr ()) -> (CInt -> (IO ())))))

foreign import ccall safe "CV/TemplateMatching.chs.h cvMatchShapes"
  cvMatchShapes :: ((Ptr ()) -> ((Ptr ()) -> (CInt -> (CDouble -> (IO CDouble)))))