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
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
= 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
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)))))