HOpenCV (empty) → 0.1
raw patch · 10 files changed
+698/−0 lines, 10 filesdep +MaybeTdep +basedep +containerssetup-changed
Dependencies added: MaybeT, base, containers, mtl
Files
- HOpenCV.cabal +42/−0
- Setup.hs +2/−0
- src/AI/CV/OpenCV/CV.hsc +92/−0
- src/AI/CV/OpenCV/CxCore.hsc +230/−0
- src/AI/CV/OpenCV/HOpenCV_wrap.c +146/−0
- src/AI/CV/OpenCV/HOpenCV_wrap.h +36/−0
- src/AI/CV/OpenCV/HighGui.hs +65/−0
- src/AI/CV/OpenCV/Types.hs +16/−0
- src/Foreign/ForeignPtrWrap.hs +29/−0
- src/Test.hs +40/−0
+ HOpenCV.cabal view
@@ -0,0 +1,42 @@+name: HOpenCV+version: 0.1+license: BSD3+maintainer: Noam Lewis <jones.noamle@gmail.com>+bug-reports: mailto:jones.noamle@gmail.com+category: AI, Graphics+synopsis: A binding for the OpenCV computer vision library+description:+ Initial version with very limited bindings to OpenCV+build-type: Simple+cabal-version: >= 1.2+extra-source-files:+ src/AI/CV/OpenCV/HOpenCV_wrap.h++library+ exposed-modules:+ AI.CV.OpenCV.CV+ AI.CV.OpenCV.CxCore+ AI.CV.OpenCV.HighGui+ AI.CV.OpenCV.Types+ Foreign.ForeignPtrWrap+ c-sources:+ src/AI/CV/OpenCV/HOpenCV_wrap.c+ hs-Source-Dirs: src+ include-dirs: /usr/include/opencv+ extra-libraries: cv,highgui+ build-depends: base >= 3 && < 5, containers, MaybeT, mtl+ ghc-options: -Wall++executable test-hopencv+ c-sources:+ src/AI/CV/OpenCV/HOpenCV_wrap.c+ include-dirs: /usr/include/opencv+ hs-source-dirs: src+ Build-Depends: base >= 4+ main-is: Test.hs+ Ghc-Options: -Wall + Ghc-Prof-Options: -prof -auto-all + extra-libraries: cv,highgui+ other-modules: AI.CV.OpenCV.CxCore, AI.CV.OpenCV.CV, AI.CV.OpenCV.HighGui, AI.CV.OpenCV.Types++
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/AI/CV/OpenCV/CV.hsc view
@@ -0,0 +1,92 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++module AI.CV.OpenCV.CV where++import Foreign.C.Types+import Foreign.Ptr+ +import Data.Bits++import AI.CV.OpenCV.CxCore++#include <cv.h>+++foreign import ccall unsafe "cv.h cvCanny"+ c_cvCanny :: Ptr CvArr -> Ptr CvArr -> CDouble -> CDouble -> CInt -> IO ()++cvCanny :: (IplArrayType i1, IplArrayType i2) =>+ Ptr i1 -> Ptr i2 -> CDouble -> CDouble -> CInt -> IO ()+cvCanny src dst threshold1 threshold2 apertureSize = + c_cvCanny (fromArr src) (fromArr dst) (realToFrac threshold1) (realToFrac threshold2) apertureSize+++data InterpolationMethod = CV_INTER_NN + | CV_INTER_LINEAR + | CV_INTER_CUBIC+ | CV_INTER_AREA+ deriving (Enum,Eq)++foreign import ccall unsafe "cv.h cvResize"+ c_cvResize :: Ptr CvArr -> Ptr CvArr -> CInt -> IO ()++cvResize :: (IplArrayType i1, IplArrayType i2) => Ptr i1 -> Ptr i2 -> InterpolationMethod -> IO ()+cvResize src dst interp = c_cvResize (fromArr src) (fromArr dst) (fromIntegral . fromEnum $ interp)++foreign import ccall unsafe "HOpenCV_warp.h dilate"+ c_dilate :: Ptr CvArr -> Ptr CvArr -> CInt -> IO ()++cvDilate :: (IplArrayType i1, IplArrayType i2) => Ptr i1 -> Ptr i2 -> CInt -> IO ()+cvDilate src dst iter = c_dilate (fromArr src) (fromArr dst) iter+++foreign import ccall unsafe "cv.h cvPyrDown"+ c_cvPyrDown :: Ptr CvArr -> Ptr CvArr -> CInt -> IO ()++-- for now only one filter type is supported so no need for the CInt (filter type)+constCvGaussian5x5 :: CInt+constCvGaussian5x5 = 7+cvPyrDown :: (IplArrayType i1, IplArrayType i2) => Ptr i1 -> Ptr i2 -> IO ()+cvPyrDown src dst = c_cvPyrDown (fromArr src) (fromArr dst) constCvGaussian5x5++------------------------------------------------------------------------------++data CvHaarClassifierCascade++-- thanks to http://book.realworldhaskell.org/read/interfacing-with-c-the-ffi.html+newtype HaarDetectFlag = HaarDetectFlag { unHaarDetectFlag :: CInt }+ deriving (Eq, Show)+ +#{enum HaarDetectFlag, HaarDetectFlag+ , cvHaarFlagNone = 0+ , cvHaarDoCannyPruning = CV_HAAR_DO_CANNY_PRUNING + , cvHaarScaleImage = CV_HAAR_SCALE_IMAGE + , cvHaarFindBiggestObject = CV_HAAR_FIND_BIGGEST_OBJECT + , cvHaarDoRoughSearch = CV_HAAR_DO_ROUGH_SEARCH+ }++combineHaarFlags :: [HaarDetectFlag] -> HaarDetectFlag+combineHaarFlags = HaarDetectFlag . foldr ((.|.) . unHaarDetectFlag) 0+ +foreign import ccall unsafe "HOpenCV_warp.h c_cvHaarDetectObjects"+ c_cvHaarDetectObjects :: Ptr CvArr -- ^ image+ -> Ptr CvHaarClassifierCascade -- ^ cascade+ -> Ptr CvMemStorage -- ^ storage+ -> CDouble -- ^ scale_factor+ -> CInt -- ^ min_neighbors+ -> CInt -- ^ flags+ -> CInt -> CInt -- ^ min_size+ -> IO (Ptr (CvSeq CvRect))++cvHaarDetectObjects :: (IplArrayType i) => + Ptr i -- ^ image+ -> Ptr CvHaarClassifierCascade -- ^ cascade+ -> Ptr CvMemStorage -- ^ storage+ -> CDouble -- ^ scale_factor+ -> CInt -- ^ min_neighbors+ -> HaarDetectFlag -- ^ flags+ -> CvSize -- ^ min_size+ -> IO (Ptr (CvSeq CvRect))+cvHaarDetectObjects image cascade storage scaleFactor minNeighbors flags minSize = + c_cvHaarDetectObjects (fromArr image) cascade storage scaleFactor minNeighbors (unHaarDetectFlag flags) (sizeWidth minSize) (sizeHeight minSize)+
+ src/AI/CV/OpenCV/CxCore.hsc view
@@ -0,0 +1,230 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++module AI.CV.OpenCV.CxCore where++import Foreign.ForeignPtrWrap+import Foreign.C.Types+import Foreign.C.String+import Foreign+++#include <cxcore.h>++------------------------------------------------------++data CvSize = CvSize { sizeWidth :: CInt, sizeHeight :: CInt }+ deriving (Show, Eq)+instance Storable CvSize where+ sizeOf _ = (#size CvSize)+ alignment _ = alignment (undefined :: CInt)+ peek ptr = do+ w <- (#peek CvSize, width) ptr+ h <- (#peek CvSize, height) ptr+ return (CvSize w h)+ poke ptr (CvSize w h) = do+ (#poke CvSize, width) ptr w+ (#poke CvSize, height) ptr h++data CvRect = CvRect { rectX :: CInt, rectY :: CInt, rectWidth :: CInt, rectHeight :: CInt }+ deriving (Show, Eq)+ +instance Storable CvRect where+ sizeOf _ = (#size CvRect)+ alignment _ = alignment (undefined :: CInt)+ peek ptr = do+ x <- (#peek CvRect, x) ptr+ y <- (#peek CvRect, y) ptr+ w <- (#peek CvRect, width) ptr+ h <- (#peek CvRect, height) ptr+ return (CvRect x y w h)+ poke ptr (CvRect x y w h) = do+ (#poke CvRect, x) ptr x+ (#poke CvRect, y) ptr y+ (#poke CvRect, width) ptr w+ (#poke CvRect, height) ptr h++------------------------------------------------------+class IplArrayType a++data CvArr+instance IplArrayType CvArr++data IplImage+instance IplArrayType IplImage++data CvMemStorage++data CvSeq a++fromArr :: IplArrayType a => Ptr a -> Ptr CvArr+fromArr = castPtr ++newtype Depth = Depth { unDepth :: CInt } + deriving (Eq, Show)+ +#{enum Depth, Depth + , iplDepth1u = IPL_DEPTH_1U+ , iplDepth8u = IPL_DEPTH_8U+ , iplDepth8s = IPL_DEPTH_8S+ , iplDepth16u = IPL_DEPTH_16U+ , iplDepth16s = IPL_DEPTH_16S+ , iplDepth32s = IPL_DEPTH_32S+ , iplDepth32f = IPL_DEPTH_32F+ , iplDepth64f = IPL_DEPTH_64F+} ++validDepths :: [Depth]+validDepths = [iplDepth1u, iplDepth8u, iplDepth8s, iplDepth16u, iplDepth16s, iplDepth32s, iplDepth32f, iplDepth64f]++depthsLookupList :: [(CInt, Depth)]+depthsLookupList = map (\d -> (unDepth d, d)) validDepths++numToDepth :: CInt -> Maybe Depth+numToDepth x = lookup x depthsLookupList+ ++---------------------------------------------------------------+-- mem storage+foreign import ccall unsafe "cxcore.h cvCreateMemStorage"+ c_cvCreateMemStorage :: CInt -> IO (Ptr CvMemStorage)++cvCreateMemStorage :: CInt -> IO (Ptr CvMemStorage)+cvCreateMemStorage = errorName "Failed to create mem storage" . checkPtr . c_cvCreateMemStorage ++foreign import ccall unsafe "HOpenCV_warp.h release_mem_storage"+ cvReleaseMemStorage :: Ptr CvMemStorage -> IO ()++foreign import ccall unsafe "HOpenCV_warp.h &release_mem_storage"+ cp_release_mem_storage :: FunPtr (Ptr CvMemStorage -> IO ())++createMemStorageF :: CInt -> IO (ForeignPtr CvMemStorage)+createMemStorageF = (createForeignPtr cp_release_mem_storage) . cvCreateMemStorage+ ++-- images / matrices / arrays++foreign import ccall unsafe "HOpenCV_warp.h create_image"+ c_cvCreateImage :: CInt -> CInt -> CInt -> CInt -> IO (Ptr IplImage)++cvCreateImage :: CvSize -> CInt -> Depth -> IO (Ptr IplImage)+cvCreateImage size numChans depth = errorName "Failed to create image" . checkPtr $ c_cvCreateImage (sizeWidth size) (sizeHeight size) (unDepth depth) numChans++foreign import ccall unsafe "HOpenCV_warp.h release_image"+ cvReleaseImage :: Ptr IplImage -> IO ()++foreign import ccall unsafe "HOpenCV_warp.h &release_image"+ cp_release_image :: FunPtr (Ptr IplImage -> IO ())++createImageF :: CvSize -> CInt -> Depth -> IO (ForeignPtr IplImage)+createImageF x y z = createForeignPtr cp_release_image $ cvCreateImage x y z++foreign import ccall unsafe "cxcore.h cvCloneImage"+ c_cvCloneImage :: Ptr IplImage -> IO (Ptr IplImage)++cvCloneImage :: Ptr IplImage -> IO (Ptr IplImage)+cvCloneImage = errorName "Failed to clone image" . checkPtr . c_cvCloneImage+ +cloneImageF :: Ptr IplImage -> IO (ForeignPtr IplImage)+cloneImageF x = createForeignPtr cp_release_image $ cvCloneImage x+ +foreign import ccall unsafe "HOpenCV_warp.h get_size"+ c_get_size :: Ptr CvArr -> Ptr CvSize -> IO ()++foreign import ccall unsafe "cxcore.h cvCopy"+ c_cvCopy :: Ptr CvArr -> Ptr CvArr -> Ptr CvArr -> IO ()+ +-- todo add mask support+cvCopy :: IplArrayType a => Ptr a -> Ptr a -> IO ()+cvCopy src dst = c_cvCopy (fromArr src) (fromArr dst) nullPtr++cvGetSize :: IplArrayType a => Ptr a -> CvSize+cvGetSize p = unsafePerformIO $+ alloca $ \cvSizePtr -> do+ c_get_size (castPtr p) cvSizePtr+ size <- peek cvSizePtr+ return size++foreign import ccall unsafe "HOpenCV_warp.h get_depth"+ c_get_depth :: Ptr IplImage -> IO CInt++getDepth :: Ptr IplImage -> IO Depth+getDepth img = do+ depthInt <- c_get_depth img+ case numToDepth depthInt of+ Nothing -> fail "Bad depth in image struct"+ Just depth -> return depth++foreign import ccall unsafe "HOpenCV_warp.h get_nChannels"+ c_get_nChannels :: Ptr IplImage -> IO CInt++getNumChannels :: Integral a => Ptr IplImage -> IO a+getNumChannels img = fmap fromIntegral $ c_get_nChannels img+++foreign import ccall unsafe "cxcore.h cvConvertScale"+ cvConvertScale :: Ptr CvArr -> Ptr CvArr -> CDouble -> CDouble -> IO ()++ +foreign import ccall unsafe "HOpenCV_warp.h cv_free"+ cvFree :: Ptr a -> IO ()+ +foreign import ccall unsafe "cxcore.h cvLoad"+ c_cvLoad :: CString -> Ptr CvMemStorage -> CString -> Ptr CString -> IO (Ptr a)++cvLoad :: String -> Ptr CvMemStorage -> Maybe String -> IO (Ptr a, Maybe String)+cvLoad filename memstorage name = withCString filename cvLoad'+ where cvLoad' filenameC = do+ case name of+ Nothing -> cvLoad'' filenameC nullPtr+ Just n' -> withCString n' $ cvLoad'' filenameC+ cvLoad'' filenameC nameC = alloca $ \ptrRealNameC -> do+ ptrObj <- errorName "cvLoad failed" . checkPtr $ c_cvLoad filenameC memstorage nameC ptrRealNameC+ realNameC <- peek ptrRealNameC+ realName <- if realNameC == nullPtr + then return Nothing + else fmap Just $ peekCString realNameC+ cvFree realNameC+ return (ptrObj, realName)+ +foreign import ccall unsafe "cxcore.h cvGetSeqElem"+ cvGetSeqElem :: Ptr (CvSeq a) -> CInt -> IO (Ptr a)+ +-- foreign import ccall unsafe "HOpenCV_warp.h c_rect_cvGetSeqElem"+-- cvGetSeqElemRect :: Ptr (CvSeq (Ptr CvRect)) -> CInt -> IO (Ptr CvRect)++foreign import ccall unsafe "HOpenCV_warp.h seq_total"+ seqNumElems :: Ptr (CvSeq a) -> IO CInt++seqToPList :: Ptr (CvSeq a) -> IO [Ptr a]+seqToPList pseq = do+ numElems <- seqNumElems pseq+ mapM (cvGetSeqElem pseq) [1..(numElems)]++seqToList :: Storable a => Ptr (CvSeq a) -> IO [a]+seqToList pseq = do+ numElems <- seqNumElems pseq+ flip mapM [1..(numElems)] $ \i -> do+ elemP <- cvGetSeqElem pseq i+ elem' <- peek elemP+ return elem'++-- seqToRectList :: Ptr (CvSeq (Ptr CvRect)) -> IO [CvRect]+-- seqToRectList pseq = do+-- numElems <- seqNumElems pseq+-- flip mapM [1..(numElems)] $ \i -> do+-- rectP <- cvGetSeqElemRect pseq i+-- rect <- peek rectP+-- return rect++foreign import ccall unsafe "HOpenCV_warp.h c_cvRectangle"+ c_cvRectangle :: Ptr CvArr -> CInt -> CInt -> CInt -> CInt -> IO ()++cvRectangle :: IplArrayType a => Ptr a -> CvRect -> IO ()+cvRectangle dst (CvRect x y w h) = c_cvRectangle (fromArr dst) x y w h++------------------------------------------------------------------------------+-- Debugging stuff, not part of opencv++-- | Debugging function to print some of the internal details of an IplImage structure+foreign import ccall unsafe "HOpenCV_warp.h debug_print_image_header"+ c_debug_print_image_header :: Ptr IplImage -> IO ()
+ src/AI/CV/OpenCV/HOpenCV_wrap.c view
@@ -0,0 +1,146 @@+#include <cxcore.h>+#include <cv.h>+#include <highgui.h>++#include <stdio.h>++void debug_print_image_header(IplImage *image)+{+ printf("IplImage: \n"+ "\tnSize: %d\n"+ "\tID: %d\n"+ "\tnChannels: %d\n"+ "\talphaChannel: %d\n"+ "\tdepth: %d\n"+ "\tdataOrder: %d\n"+ "\torigin: %d\n"+ "\talign: %d\n"+ "\twidth: %d\n"+ "\theight: %d\n"+ "\timageSize: %d\n"+ "\twidthStep: %d\n",+ image->nSize, image->ID, image->nChannels, image->alphaChannel,+ image->depth, image->dataOrder, image->origin, image->align,+ image->width, image->height, image->imageSize, image->widthStep);+}++/****************************************************************************/++void release_capture(CvCapture *capture)+{+ CvCapture *temp = capture;+ cvReleaseCapture(&temp);+}++/****************************************************************************/++void num_to_name(int num, char *name, int length)+{+ snprintf(name, length, "win-%d", num);+}++void new_window(int num, int flags)+{+ char name[100];+ num_to_name(num, name, sizeof(name));+ cvNamedWindow(name, flags);+}++void del_window(int num)+{+ char name[100];+ num_to_name(num, name, sizeof(name));+ cvDestroyWindow(name);+}++void show_image(int num, IplImage *image)+{+ char name[100];+ num_to_name(num, name, sizeof(name));+ cvShowImage(name, image);+}++/**********************************************************/++/* Haskell's FFI doesn't know how to pass structs by value, I think. */+IplImage *create_image(int width, int height, int depth, int channels)+{+ return cvCreateImage(cvSize(width,height), depth, channels);+}++void release_image(IplImage *image)+{+ IplImage *temp = image;+ return cvReleaseImage(&temp);+}++/* Notice that according to opencv docs, cvGetSize returns the ROI for images, not the image.width and .height */+void get_size(const CvArr *arr, CvSize *size)+{+ *size = cvGetSize(arr);+}++/* TODO instead of get_depth, get_nChannels maybe we should allow serialization of the IplImage struct itself, as we do+ for CvSize? */+int get_depth(const IplImage *image)+{+ return image->depth;+}++int get_nChannels(const IplImage *image)+{+ return image->nChannels;+}++void dilate(const CvArr *src, CvArr *dest, int iterations)+{+ cvDilate(src, dest, NULL, iterations);+}++/**********************************************************/++void release_mem_storage(CvMemStorage *mem_store)+{+ CvMemStorage *temp = mem_store;+ cvReleaseMemStorage(&temp);+}++void cv_free(void *obj)+{+ void *temp = obj;+ cvFree(&temp);+}++/****************************************************************************/++int seq_total(const CvSeq *seq) {+ return seq->total;+}++/* Commonly used case of CV_GET_SEQ_ELEM is CvRect-typed elements.+ The macro CV_GET_SEQ_ELEM is supposed to be faster in some cases+ than the function cvGetSeqElem. */+/*CvRect *c_rect_cvGetSeqElem(const CvSeq *seq, int index) {+ return CV_GET_SEQ_ELEM( CvRect, seq, index);+ }*/+++void c_cvRectangle(CvArr *img, int x, int y, int width, int height)+{+ cvRectangle(img, cvPoint(x,y),+ cvPoint((x+width),+ (y+height)),+ CV_RGB(255,0,0), 3 , 8, 0);+}++/****************************************************************************/++CvSeq *c_cvHaarDetectObjects( const CvArr* image,+ CvHaarClassifierCascade* cascade,+ CvMemStorage* storage, double scale_factor,+ int min_neighbors , int flags,+ int width, int height)+{+ return cvHaarDetectObjects(image, cascade, storage, scale_factor, min_neighbors, flags, cvSize(width, height));+}+
+ src/AI/CV/OpenCV/HOpenCV_wrap.h view
@@ -0,0 +1,36 @@+#include <cv.h>+#include <cxcore.h>++void debug_print_image_header(IplImage *image);++void release_capture(CvCapture *capture);++ +void new_window(int num, int flags);+void del_window(int num);+void show_image(int num, IplImage *image);++IplImage *create_image(int width, int height, int depth, int channels);+void release_image(IplImage *image);++void get_size(const CvArr *arr, CvSize *size);+int get_depth(const IplImage *image);+int get_nChannels(const IplImage *image);++void dilate(const CvArr *src, CvArr *dest, int iterations);++void release_mem_storage(CvMemStorage *mem_store);+void cv_free(void *obj);++int seq_total(const CvSeq *seq);+/* CvRect *c_rect_cvGetSeqElem(const CvSeq *seq, int index); */++void c_cvRectangle(CvArr *img, int x, int y, int width, int height);+++CvSeq *c_cvHaarDetectObjects( const CvArr* image,+ CvHaarClassifierCascade* cascade,+ CvMemStorage* storage, double scale_factor,+ int min_neighbors , int flags,+ int width, int height);+
+ src/AI/CV/OpenCV/HighGui.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}+ +module AI.CV.OpenCV.HighGui where+ +import Foreign.ForeignPtrWrap+import Foreign.C.Types+import Foreign.Ptr+import Foreign.ForeignPtr+ +import AI.CV.OpenCV.CxCore+++------------------------------------------------+-- General+foreign import ccall unsafe "highgui.h cvConvertImage"+ c_cvConvertImage :: Ptr CvArr -> Ptr CvArr -> CInt -> IO ()++cvConvertImage :: (IplArrayType a, IplArrayType a1) => Ptr a -> Ptr a1 -> CInt -> IO ()+cvConvertImage src dst flags = c_cvConvertImage (fromArr src) (fromArr dst) flags++------------------------------------------------+-- Capturing+data CvCapture+++foreign import ccall unsafe "highgui.h cvCreateCameraCapture"+ c_cvCreateCameraCapture :: CInt -> IO (Ptr CvCapture)+ +cvCreateCameraCapture :: CInt -> IO (Ptr CvCapture)+cvCreateCameraCapture x = errorName "Failed to create camera" . checkPtr $ c_cvCreateCameraCapture . fromIntegral $ x+ ++foreign import ccall unsafe "HOpenCV_warp.h release_capture"+ cvReleaseCapture :: Ptr CvCapture -> IO ()++foreign import ccall unsafe "HOpenCV_warp.h &release_capture"+ cp_release_capture :: FunPtr (Ptr CvCapture -> IO () )+ +createCameraCaptureF :: CInt -> IO (ForeignPtr CvCapture)+createCameraCaptureF = (createForeignPtr cp_release_capture) . cvCreateCameraCapture++++foreign import ccall unsafe "highgui.h cvQueryFrame"+ c_cvQueryFrame :: Ptr CvCapture -> IO (Ptr IplImage)++cvQueryFrame :: Ptr CvCapture -> IO (Ptr IplImage)+cvQueryFrame cap = errorName "Failed to query frame from camera" . checkPtr $ c_cvQueryFrame cap++-------------------------------------------------+-- Windows+foreign import ccall unsafe "HOpenCV_wrap.h new_window"+ c_newWindow :: CInt -> CInt -> IO ()++newWindow :: CInt -> Bool -> IO ()+newWindow num autoSize = c_newWindow num (if autoSize then 1 else 0)++foreign import ccall unsafe "HOpenCV_wrap.h del_window"+ delWindow :: CInt -> IO ()++foreign import ccall unsafe "HOpenCV_wrap.h show_image"+ showImage :: CInt -> Ptr IplImage -> IO ()++foreign import ccall unsafe "highgui.h cvWaitKey"+ waitKey :: CInt -> IO CInt
+ src/AI/CV/OpenCV/Types.hs view
@@ -0,0 +1,16 @@+module AI.CV.OpenCV.Types where+++import AI.CV.OpenCV.CxCore+import AI.CV.OpenCV.HighGui++import Foreign+import Foreign.ForeignPtr++++type PImage = Ptr IplImage+type PCapture = Ptr CvCapture++type FPImage = ForeignPtr IplImage+type FPCapture = ForeignPtr CvCapture
+ src/Foreign/ForeignPtrWrap.hs view
@@ -0,0 +1,29 @@+module Foreign.ForeignPtrWrap where++import Foreign.Ptr+import Foreign.ForeignPtr++import System.IO.Error++-- A wrapper for newForeignPtr that handles nullPtrs, and can be chained to an IO Ptr creator.+-- usage:+-- myPtrCreator = (createForeignPtr deallocFunc) . allocFunc+-- where, allocFunc :: a->b->c->...-> IO (Ptr z)+createForeignPtr :: (FunPtr (Ptr a -> IO () )) -> IO (Ptr a) -> IO (ForeignPtr a)+createForeignPtr dealloc allocedPtr = do+ ptr <- checkPtr allocedPtr+ newForeignPtr dealloc ptr+++checkPtr :: IO (Ptr a) -> IO (Ptr a)+checkPtr x = do + res <- x+ if res /= nullPtr + then return res + else fail "Null Pointer"++------------------------------------------------+errorName :: String -> IO a -> IO a+errorName = modifyIOError . const . userError++
+ src/Test.hs view
@@ -0,0 +1,40 @@+module Main where++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types++import AI.CV.OpenCV.CxCore+import AI.CV.OpenCV.CV+import AI.CV.OpenCV.HighGui++import Control.Monad(when)++showFrames :: CInt -> Ptr IplImage -> Ptr CvCapture -> IO ()+showFrames winNum targetImage cvcapture = do+ frame <- cvQueryFrame cvcapture + cvConvertImage (fromArr frame) (fromArr targetImage) 0+ calcFrame targetImage+ where calcFrame targetSmall = do+ cvResize targetImage targetSmall CV_INTER_LINEAR+ cvCanny targetSmall targetSmall 30 190 3+ showImage winNum targetSmall+ key <- waitKey 5+ when (key == -1) (showFrames winNum targetImage cvcapture)++ +processImages :: Ptr CvCapture -> IO ()+processImages capture = do+ frame <- cvQueryFrame capture+ let winNum = 0+ newWindow winNum True+ target <- createImageF (cvGetSize frame) 1 iplDepth8u+ withForeignPtr target $ (\target' -> showFrames winNum target' capture) + +main :: IO ()+main = do+ capture <- createCameraCaptureF 0+ withForeignPtr capture processImages+++