cv-combinators 0.1.3 → 0.2.0
raw patch · 2 files changed
+43/−46 lines, 2 filesdep ~HOpenCVPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: HOpenCV
API changes (from Hackage documentation)
Files
- cv-combinators.cabal +3/−3
- src/AI/CV/ImageProcessors.hs +40/−43
cv-combinators.cabal view
@@ -1,5 +1,5 @@ name: cv-combinators-version: 0.1.3+version: 0.2.0 license: GPL-2 license-file: LICENSE maintainer: Noam Lewis <jones.noamle@gmail.com>@@ -28,7 +28,7 @@ library exposed-modules: AI.CV.ImageProcessors hs-Source-Dirs: src- build-depends: base >=4 && <5, HOpenCV >= 0.3, allocated-processor >= 0.0.2, vector-space+ build-depends: base >=4 && <5, HOpenCV >= 0.4, allocated-processor >= 0.0.2, vector-space ghc-options: -Wall Ghc-Prof-Options: -Wall @@ -37,7 +37,7 @@ if flag(Demos) Buildable: True hs-source-dirs: src- Build-Depends: base >=4 && <5, HOpenCV >= 0.3, allocated-processor >= 0.0.2, vector-space+ Build-Depends: base >=4 && <5, HOpenCV >= 0.4, allocated-processor >= 0.0.2, vector-space main-is: Test.hs ghc-options: -Wall Ghc-Prof-Options: -Wall
src/AI/CV/ImageProcessors.hs view
@@ -1,6 +1,6 @@ ----------------------------------------------------------------- | +-- | -- Module : AI.CV.ImageProcessors -- Copyright : (c) Noam Lewis 2010 -- License : BSD3@@ -20,16 +20,16 @@ -- > cam = camera 0 -- Autodetect camera -- > edge = canny 30 190 3 -- Edge detecting processor using canny operator -- >--- > test = cam >>> edge >>> win +-- > test = cam >>> edge >>> win -- -- The last expression is a processor that captures frames from camera and displays edge-detected version in the window. ---------------------------------------------------------------module AI.CV.ImageProcessors - (ImageSink, - ImageSource, - ImageProcessor, - Image, - +module AI.CV.ImageProcessors+ (ImageSink,+ ImageSource,+ ImageProcessor,+ Image,+ camera, videoFile, @@ -84,23 +84,23 @@ ------------------------------------------------------------------ capture :: IO HighGui.Capture -> ImageSource capture getCap = processor processQueryFrame allocateCamera fromState releaseNext- where processQueryFrame :: () -> (Image, HighGui.Capture) + where processQueryFrame :: () -> (Image, HighGui.Capture) -> IO (Image, HighGui.Capture) processQueryFrame _ (_, cap) = do newFrame <- HighGui.queryFrame cap return (newFrame, cap)- + allocateCamera :: () -> IO (Image, HighGui.Capture) allocateCamera _ = do cap <- getCap newFrame <- HighGui.queryFrame cap return (newFrame, cap)- + fromState (image, _) = return image- - releaseNext (_, cap) = HighGui.releaseCapture cap + releaseNext (_, cap) = return () + -- | A capture device, using OpenCV's HighGui lib's cvCreateCameraCapture -- should work with most webcames. See OpenCV's docs for information. -- This processor outputs the latest image from the camera at each invocation.@@ -111,8 +111,8 @@ videoFile fileName = capture (HighGui.createFileCapture fileName) --------------------------------------------------------------------- GUI stuff - +-- GUI stuff+ -- | A window that displays images. -- Note: windows with the same index will be the same window....is this ok? -- Response: Yes. It will display whatever images you give it.@@ -123,15 +123,15 @@ namedWindow s a = processor procFunc allocFunc return return where procFunc :: (Image -> () -> IO ()) procFunc src x = HighGui.showImage s src >> return x- + allocFunc :: (Image -> IO ()) allocFunc _ = HighGui.namedWindow s a ------------------------------------------------------------------ -- | A convenience function for constructing a common type of processors that work exclusively on images-imageProcessor :: (Image -> Image -> IO Image) -> (Image -> IO Image) +imageProcessor :: (Image -> Image -> IO Image) -> (Image -> IO Image) -> ImageProcessor-imageProcessor procFunc allocFunc = processor procFunc allocFunc return CxCore.releaseImage+imageProcessor procFunc allocFunc = processor procFunc allocFunc return (const $ return ()) -- | OpenCV's cvResize resize :: Int -- Width@@ -141,86 +141,83 @@ where processResize src dst = do CV.resize src dst interp return dst- + allocateResize src = do nChans <- CxCore.getNumChannels src :: IO Int depth <- CxCore.getDepth src CxCore.createImage (CxCore.CvSize (fromIntegral width) (fromIntegral height)) depth (fromIntegral nChans)- + -- | OpenCV's cvDilate dilate :: Int -> ImageProcessor dilate iterations = imageProcessor procDilate CxCore.cloneImage where procDilate src dst = do- CV.dilate src dst (fromIntegral iterations) + CV.dilate src dst (fromIntegral iterations) return dst -- todo: Int is not really correct here, because it's really CInt. should we just expose CInt?--- | OpenCV's cvCanny +-- | OpenCV's cvCanny canny :: Int -- ^ Threshold 1 -> Int -- ^ Threshold 2 -> Int -- ^ Size -> ImageProcessor canny thres1 thres2 size = processor processCanny allocateCanny convertState releaseState where processCanny src (gray, dst) = do- HighGui.convertImage src gray 0 + HighGui.convertImage src gray 0 CV.canny gray dst (fromIntegral thres1) (fromIntegral thres2) (fromIntegral size) return (gray, dst)- + allocateCanny src = do srcSize <- CxCore.getSize src target <- CxCore.createImage srcSize CxCore.iplDepth8u 1 gray <- CxCore.createImage srcSize CxCore.iplDepth8u 1 return (gray, target)- + convertState = return . snd- - releaseState (gray, target) = do- CxCore.releaseImage gray- CxCore.releaseImage target + releaseState (gray, target) = return ()+ ------------------------------------------------------------------ -- | Wrapper for OpenCV's cvHaarDetectObjects and the surrounding required things (mem storage, cascade loading, etc). haarDetect :: String -- ^ Cascade filename (OpenCV comes with several, including ones for face detection)- -> Double -- ^ scale factor + -> Double -- ^ scale factor -> Int -- ^ min neighbors -> CV.HaarDetectFlag -- ^ flags -> CvSize -- ^ min size -> IOProcessor Image [CvRect]-haarDetect cascadeFileName scaleFactor minNeighbors flags minSize = processor procFunc allocFunc convFunc freeFunc - where procFunc :: Image -> ([CvRect], (HaarClassifierCascade, MemStorage)) +haarDetect cascadeFileName scaleFactor minNeighbors flags minSize = processor procFunc allocFunc convFunc freeFunc+ where procFunc :: Image -> ([CvRect], (HaarClassifierCascade, MemStorage)) -> IO ([CvRect], (HaarClassifierCascade, MemStorage)) procFunc image (_, x@(cascade, storage)) = do seqP <- CV.haarDetectObjects image cascade storage (realToFrac scaleFactor) (fromIntegral minNeighbors) flags minSize recs <- CxCore.seqToList seqP return (recs, x)- + allocFunc :: Image -> IO ([CvRect], (HaarClassifierCascade, MemStorage)) allocFunc _ = do storage <- CxCore.createMemStorage 0 (cascade, name) <- CxCore.load cascadeFileName storage Nothing print name -- todo verify that this is a haar cascade return ([], (cascade, storage))- + convFunc = return . fst- - freeFunc (_, (_, storage)) = do- CxCore.releaseMemStorage storage++ freeFunc (_, (_, storage)) = return () -- todo release the cascade usign cvReleaseHaarClassifierCascade- - ------------------------------------------------------------------------------ ++-----------------------------------------------------------------------------+ -- Add a processor that takes a list of any shape (rect, ellipse, etc.) and draws them all on the image? -- need a datatype that combines the shape types for that.- + -- | OpenCV's cvRectangle, currently without width, color or line type control drawRects :: IOProcessor (Image, [CvRect]) Image-drawRects = processor procFunc (CxCore.cloneImage . fst) return CxCore.releaseImage+drawRects = processor procFunc (CxCore.cloneImage . fst) return (const $ return ()) where procFunc (src,rects) dst = do CxCore.copy src dst mapM_ (CxCore.rectangle dst) rects return dst- +