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
import System.IO.Unsafe
import Control.Exception
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)
simpleTemplateMatch :: MatchType -> Image GrayScale D32 -> Image GrayScale D32 -> ((Int,Int),Double)
simpleTemplateMatch mt image template
| image `biggerThan` 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); }
| otherwise = throw $CvSizeError "simpleTemplateMatch: template is bigger than the image"
matchTemplate :: MatchType-> Image GrayScale D32 -> Image GrayScale D32 -> Image GrayScale D32
matchTemplate mt image template
| image `biggerThan` 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
| otherwise = throw $ CvSizeError $ "MatchTemplate: template larger than the image"
subPixelTemplateMatch :: MatchType -> Image GrayScale D32 -> Image GrayScale D32 -> Double -> (Double,Double)
subPixelTemplateMatch mt image template n
= (fromIntegral (tx)+fromIntegral sbx/n
,fromIntegral (ty)+fromIntegral sby/n)
where
(otw,oth) = getSize template
((orX,orY),_) = simpleTemplateMatch CCORR_NORMED image template
(tx,ty) = (orXotw`div`2, orYoth`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)
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)))))