friday 0.2.2.0 → 0.2.3.0
raw patch · 4 files changed
+470/−2 lines, 4 filesdep +containersdep ~basedep ~transformersnew-uploaderPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: containers
Dependency ranges changed: base, transformers
API changes (from Hackage documentation)
- Vision.Histogram: instance (Eq sh, Eq a, Storable a) => Eq (Histogram sh a)
- Vision.Histogram: instance (Ord sh, Ord a, Storable a) => Ord (Histogram sh a)
- Vision.Histogram: instance (Show sh, Show a, Storable a) => Show (Histogram sh a)
- Vision.Histogram: instance HistogramShape Z
- Vision.Histogram: instance HistogramShape sh => HistogramShape (sh :. Int)
- Vision.Histogram: instance ToHistogram GreyPixel
- Vision.Histogram: instance ToHistogram HSVPixel
- Vision.Histogram: instance ToHistogram RGBAPixel
- Vision.Histogram: instance ToHistogram RGBPixel
- Vision.Histogram: shape :: Histogram sh a -> !sh
- Vision.Histogram: vector :: Histogram sh a -> !(Vector a)
- Vision.Image.Class: instance Pixel Bool
- Vision.Image.Class: instance Pixel Double
- Vision.Image.Class: instance Pixel Float
- Vision.Image.Class: instance Pixel Int
- Vision.Image.Class: instance Pixel Int16
- Vision.Image.Class: instance Pixel Int32
- Vision.Image.Class: instance Pixel Word
- Vision.Image.Class: instance Pixel Word16
- Vision.Image.Class: instance Pixel Word32
- Vision.Image.Class: instance Pixel Word8
- Vision.Image.Conversion: instance Convertible GreyPixel GreyPixel
- Vision.Image.Conversion: instance Convertible GreyPixel HSVPixel
- Vision.Image.Conversion: instance Convertible GreyPixel RGBAPixel
- Vision.Image.Conversion: instance Convertible GreyPixel RGBPixel
- Vision.Image.Conversion: instance Convertible HSVPixel GreyPixel
- Vision.Image.Conversion: instance Convertible HSVPixel HSVPixel
- Vision.Image.Conversion: instance Convertible HSVPixel RGBAPixel
- Vision.Image.Conversion: instance Convertible HSVPixel RGBPixel
- Vision.Image.Conversion: instance Convertible RGBAPixel GreyPixel
- Vision.Image.Conversion: instance Convertible RGBAPixel HSVPixel
- Vision.Image.Conversion: instance Convertible RGBAPixel RGBAPixel
- Vision.Image.Conversion: instance Convertible RGBAPixel RGBPixel
- Vision.Image.Conversion: instance Convertible RGBPixel GreyPixel
- Vision.Image.Conversion: instance Convertible RGBPixel HSVPixel
- Vision.Image.Conversion: instance Convertible RGBPixel RGBAPixel
- Vision.Image.Conversion: instance Convertible RGBPixel RGBPixel
- Vision.Image.Filter.Internal: fFold :: Filter src kernel init fold acc res -> !fold
- Vision.Image.Filter.Internal: fInit :: Filter src kernel init fold acc res -> !(Point -> src -> init)
- Vision.Image.Filter.Internal: fInterpol :: Filter src kernel init fold acc res -> !(BorderInterpolate src)
- Vision.Image.Filter.Internal: fKernel :: Filter src kernel init fold acc res -> !kernel
- Vision.Image.Filter.Internal: fKernelCenter :: Filter src kernel init fold acc res -> !KernelAnchor
- Vision.Image.Filter.Internal: fKernelSize :: Filter src kernel init fold acc res -> !Size
- Vision.Image.Filter.Internal: fPost :: Filter src kernel init fold acc res -> !(Point -> src -> init -> acc -> res)
- Vision.Image.Filter.Internal: instance (Image src, FromFunction res, src_pix ~ ImagePixel src, res_pix ~ FromFunctionPixel res) => Filterable src res (BoxFilter src_pix init acc res_pix)
- Vision.Image.Filter.Internal: instance (Image src, FromFunction res, src_pix ~ ImagePixel src, res_pix ~ FromFunctionPixel res) => Filterable src res (BoxFilter1 src_pix init res_pix)
- Vision.Image.Filter.Internal: instance (Image src, FromFunction res, src_pix ~ ImagePixel src, res_pix ~ FromFunctionPixel res, SeparatelyFiltrable src res acc) => Filterable src res (SeparableFilter src_pix init acc res_pix)
- Vision.Image.Filter.Internal: instance (Image src, FromFunction res, src_pix ~ ImagePixel src, res_pix ~ FromFunctionPixel res, SeparatelyFiltrable src res src_pix) => Filterable src res (SeparableFilter1 src_pix init res_pix)
- Vision.Image.Filter.Internal: instance Storable acc => SeparatelyFiltrable src (Delayed p) acc
- Vision.Image.Filter.Internal: instance Storable acc => SeparatelyFiltrable src (Manifest p) acc
- Vision.Image.Filter.Internal: skHorizontal :: SeparableKernel src init acc -> !(init -> DIM1 -> acc -> acc -> acc)
- Vision.Image.Filter.Internal: skVertical :: SeparableKernel src init acc -> !(init -> DIM1 -> src -> acc -> acc)
- Vision.Image.Grey.Type: instance Bits GreyPixel
- Vision.Image.Grey.Type: instance Bounded GreyPixel
- Vision.Image.Grey.Type: instance Enum GreyPixel
- Vision.Image.Grey.Type: instance Eq GreyPixel
- Vision.Image.Grey.Type: instance Integral GreyPixel
- Vision.Image.Grey.Type: instance Interpolable GreyPixel
- Vision.Image.Grey.Type: instance Num GreyPixel
- Vision.Image.Grey.Type: instance Ord GreyPixel
- Vision.Image.Grey.Type: instance Pixel GreyPixel
- Vision.Image.Grey.Type: instance Read GreyPixel
- Vision.Image.Grey.Type: instance Real GreyPixel
- Vision.Image.Grey.Type: instance Show GreyPixel
- Vision.Image.Grey.Type: instance Storable GreyPixel
- Vision.Image.HSV.Type: hsvHue :: HSVPixel -> {-# UNPACK #-} !Word8
- Vision.Image.HSV.Type: hsvSat :: HSVPixel -> {-# UNPACK #-} !Word8
- Vision.Image.HSV.Type: hsvValue :: HSVPixel -> {-# UNPACK #-} !Word8
- Vision.Image.HSV.Type: instance Eq HSVPixel
- Vision.Image.HSV.Type: instance Interpolable HSVPixel
- Vision.Image.HSV.Type: instance Pixel HSVPixel
- Vision.Image.HSV.Type: instance Show HSVPixel
- Vision.Image.HSV.Type: instance Storable HSVPixel
- Vision.Image.Interpolate: instance Interpolable Bool
- Vision.Image.Interpolate: instance Interpolable Double
- Vision.Image.Interpolate: instance Interpolable Float
- Vision.Image.Interpolate: instance Interpolable Int
- Vision.Image.Interpolate: instance Interpolable Int16
- Vision.Image.Interpolate: instance Interpolable Int32
- Vision.Image.Interpolate: instance Interpolable Word
- Vision.Image.Interpolate: instance Interpolable Word16
- Vision.Image.Interpolate: instance Interpolable Word32
- Vision.Image.Interpolate: instance Interpolable Word8
- Vision.Image.Mutable: instance Storable p => MutableImage (MutableManifest p)
- Vision.Image.Mutable: mmSize :: MutableManifest p s -> !Size
- Vision.Image.Mutable: mmVector :: MutableManifest p s -> !(MVector s p)
- Vision.Image.RGB.Type: instance Eq RGBPixel
- Vision.Image.RGB.Type: instance Interpolable RGBPixel
- Vision.Image.RGB.Type: instance Pixel RGBPixel
- Vision.Image.RGB.Type: instance Show RGBPixel
- Vision.Image.RGB.Type: instance Storable RGBPixel
- Vision.Image.RGB.Type: rgbBlue :: RGBPixel -> {-# UNPACK #-} !Word8
- Vision.Image.RGB.Type: rgbGreen :: RGBPixel -> {-# UNPACK #-} !Word8
- Vision.Image.RGB.Type: rgbRed :: RGBPixel -> {-# UNPACK #-} !Word8
- Vision.Image.RGBA.Type: instance Eq RGBAPixel
- Vision.Image.RGBA.Type: instance Interpolable RGBAPixel
- Vision.Image.RGBA.Type: instance Pixel RGBAPixel
- Vision.Image.RGBA.Type: instance Show RGBAPixel
- Vision.Image.RGBA.Type: instance Storable RGBAPixel
- Vision.Image.RGBA.Type: rgbaAlpha :: RGBAPixel -> {-# UNPACK #-} !Word8
- Vision.Image.RGBA.Type: rgbaBlue :: RGBAPixel -> {-# UNPACK #-} !Word8
- Vision.Image.RGBA.Type: rgbaGreen :: RGBAPixel -> {-# UNPACK #-} !Word8
- Vision.Image.RGBA.Type: rgbaRed :: RGBAPixel -> {-# UNPACK #-} !Word8
- Vision.Image.Threshold: BinaryThreshold :: res -> res -> ThresholdType src res
- Vision.Image.Threshold: GaussianKernel :: Maybe acc -> AdaptiveThresholdKernel acc
- Vision.Image.Threshold: MeanKernel :: AdaptiveThresholdKernel acc
- Vision.Image.Threshold: Truncate :: src -> ThresholdType src src
- Vision.Image.Threshold: TruncateInv :: src -> ThresholdType src src
- Vision.Image.Type: delayedFun :: Delayed p -> !(Point -> p)
- Vision.Image.Type: delayedMaskFun :: DelayedMask p -> !(Point -> Maybe p)
- Vision.Image.Type: delayedMaskSize :: DelayedMask p -> !Size
- Vision.Image.Type: delayedSize :: Delayed p -> !Size
- Vision.Image.Type: instance (Eq p, Storable p) => Eq (Manifest p)
- Vision.Image.Type: instance (Image src, Storable p) => FunctorImage src (Delayed p)
- Vision.Image.Type: instance (Image src, Storable p) => FunctorImage src (Manifest p)
- Vision.Image.Type: instance (MaskedImage src, Storable p) => FunctorImage src (DelayedMask p)
- Vision.Image.Type: instance (Ord p, Storable p) => Ord (Manifest p)
- Vision.Image.Type: instance (Show p, Storable p) => Show (Manifest p)
- Vision.Image.Type: instance (Storable p1, Storable p2, Convertible p1 p2) => Convertible (Delayed p1) (Delayed p2)
- Vision.Image.Type: instance (Storable p1, Storable p2, Convertible p1 p2) => Convertible (Delayed p1) (Manifest p2)
- Vision.Image.Type: instance (Storable p1, Storable p2, Convertible p1 p2) => Convertible (Manifest p1) (Delayed p2)
- Vision.Image.Type: instance (Storable p1, Storable p2, Convertible p1 p2) => Convertible (Manifest p1) (Manifest p2)
- Vision.Image.Type: instance FromFunction (Delayed p)
- Vision.Image.Type: instance NFData (Manifest p)
- Vision.Image.Type: instance Storable p => FromFunction (DelayedMask p)
- Vision.Image.Type: instance Storable p => FromFunction (Manifest p)
- Vision.Image.Type: instance Storable p => Image (Delayed p)
- Vision.Image.Type: instance Storable p => Image (Manifest p)
- Vision.Image.Type: instance Storable p => MaskedImage (Delayed p)
- Vision.Image.Type: instance Storable p => MaskedImage (DelayedMask p)
- Vision.Image.Type: instance Storable p => MaskedImage (Manifest p)
- Vision.Image.Type: manifestSize :: Manifest p -> !Size
- Vision.Image.Type: manifestVector :: Manifest p -> !(Vector p)
- Vision.Primitive: instance Eq RPoint
- Vision.Primitive: instance Eq Rect
- Vision.Primitive: instance Ord RPoint
- Vision.Primitive: instance Ord Rect
- Vision.Primitive: instance Read RPoint
- Vision.Primitive: instance Read Rect
- Vision.Primitive: instance Show RPoint
- Vision.Primitive: instance Show Rect
- Vision.Primitive: rHeight :: Rect -> {-# UNPACK #-} !Int
- Vision.Primitive: rWidth :: Rect -> {-# UNPACK #-} !Int
- Vision.Primitive: rX :: Rect -> {-# UNPACK #-} !Int
- Vision.Primitive: rY :: Rect -> {-# UNPACK #-} !Int
- Vision.Primitive: rpX :: RPoint -> {-# UNPACK #-} !RatioInt
- Vision.Primitive: rpY :: RPoint -> {-# UNPACK #-} !RatioInt
- Vision.Primitive.Shape: instance (Eq tail, Eq head) => Eq (tail :. head)
- Vision.Primitive.Shape: instance (Ord tail, Ord head) => Ord (tail :. head)
- Vision.Primitive.Shape: instance (Read tail, Read head) => Read (tail :. head)
- Vision.Primitive.Shape: instance (Show tail, Show head) => Show (tail :. head)
- Vision.Primitive.Shape: instance Eq Z
- Vision.Primitive.Shape: instance Ord Z
- Vision.Primitive.Shape: instance Read Z
- Vision.Primitive.Shape: instance Shape Z
- Vision.Primitive.Shape: instance Shape sh => Shape (sh :. Int)
- Vision.Primitive.Shape: instance Show Z
- Vision.Primitive.Shape: instance Storable Z
- Vision.Primitive.Shape: instance Storable sh => Storable (sh :. Int)
+ Vision.Histogram: [shape] :: Histogram sh a -> !sh
+ Vision.Histogram: [vector] :: Histogram sh a -> !(Vector a)
+ Vision.Histogram: instance (Foreign.Storable.Storable a, GHC.Show.Show a, GHC.Show.Show sh) => GHC.Show.Show (Vision.Histogram.Histogram sh a)
+ Vision.Histogram: instance (GHC.Classes.Eq a, GHC.Classes.Eq sh, Foreign.Storable.Storable a) => GHC.Classes.Eq (Vision.Histogram.Histogram sh a)
+ Vision.Histogram: instance (GHC.Classes.Ord a, GHC.Classes.Ord sh, Foreign.Storable.Storable a) => GHC.Classes.Ord (Vision.Histogram.Histogram sh a)
+ Vision.Histogram: instance Vision.Histogram.HistogramShape Vision.Primitive.Shape.Z
+ Vision.Histogram: instance Vision.Histogram.HistogramShape sh => Vision.Histogram.HistogramShape (sh Vision.Primitive.Shape.:. GHC.Types.Int)
+ Vision.Histogram: instance Vision.Histogram.ToHistogram Vision.Image.Grey.Type.GreyPixel
+ Vision.Histogram: instance Vision.Histogram.ToHistogram Vision.Image.HSV.Type.HSVPixel
+ Vision.Histogram: instance Vision.Histogram.ToHistogram Vision.Image.RGB.Type.RGBPixel
+ Vision.Histogram: instance Vision.Histogram.ToHistogram Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Histogram: type family PixelValueSpace p;
+ Vision.Histogram: }
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Int.Int16
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Int.Int32
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Types.Bool
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Types.Double
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Types.Float
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Types.Int
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Types.Word
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Word.Word16
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Word.Word32
+ Vision.Image.Class: instance Vision.Image.Class.Pixel GHC.Word.Word8
+ Vision.Image.Class: type family FromFunctionPixel i;
+ Vision.Image.Class: }
+ Vision.Image.Contour: AllOutlines :: ContourDrawStyle
+ Vision.Image.Contour: Contour :: OneContour -> [OneContour] -> Contour
+ Vision.Image.Contour: Contours :: Map ContourId Contour -> !(Vector Int) -> Contours
+ Vision.Image.Contour: Fill :: ContourDrawStyle
+ Vision.Image.Contour: FillWithHoles :: ContourDrawStyle
+ Vision.Image.Contour: OuterOutline :: ContourDrawStyle
+ Vision.Image.Contour: [contourOutlines] :: Contours -> Map ContourId Contour
+ Vision.Image.Contour: [contourSizes] :: Contours -> !(Vector Int)
+ Vision.Image.Contour: [innerContours] :: Contour -> [OneContour]
+ Vision.Image.Contour: [outerContour] :: Contour -> OneContour
+ Vision.Image.Contour: allContourIds :: Contours -> [ContourId]
+ Vision.Image.Contour: contourPerimeter :: Contours -> ContourId -> [Point]
+ Vision.Image.Contour: contourSize :: Contours -> ContourId -> Int
+ Vision.Image.Contour: contours :: (Image src, Num (ImagePixel src), Eq (ImagePixel src)) => src -> Contours
+ Vision.Image.Contour: data Contour
+ Vision.Image.Contour: data ContourDrawStyle
+ Vision.Image.Contour: data ContourId
+ Vision.Image.Contour: data Contours
+ Vision.Image.Contour: drawContour :: Contours -> Size -> ContourDrawStyle -> ContourId -> Grey
+ Vision.Image.Contour: drawContours :: Contours -> Size -> ContourDrawStyle -> [ContourId] -> Grey
+ Vision.Image.Contour: instance Foreign.Storable.Storable Vision.Image.Contour.ContourId
+ Vision.Image.Contour: instance GHC.Classes.Eq Vision.Image.Contour.ContourDrawStyle
+ Vision.Image.Contour: instance GHC.Classes.Eq Vision.Image.Contour.ContourId
+ Vision.Image.Contour: instance GHC.Classes.Eq Vision.Image.Contour.ContourPos
+ Vision.Image.Contour: instance GHC.Classes.Eq Vision.Image.Contour.ContourType
+ Vision.Image.Contour: instance GHC.Classes.Ord Vision.Image.Contour.ContourDrawStyle
+ Vision.Image.Contour: instance GHC.Classes.Ord Vision.Image.Contour.ContourId
+ Vision.Image.Contour: instance GHC.Enum.Bounded Vision.Image.Contour.ContourDrawStyle
+ Vision.Image.Contour: instance GHC.Enum.Bounded Vision.Image.Contour.ContourPos
+ Vision.Image.Contour: instance GHC.Enum.Enum Vision.Image.Contour.ContourDrawStyle
+ Vision.Image.Contour: instance GHC.Enum.Enum Vision.Image.Contour.ContourPos
+ Vision.Image.Contour: instance GHC.Num.Num Vision.Image.Contour.ContourId
+ Vision.Image.Contour: instance GHC.Read.Read Vision.Image.Contour.ContourDrawStyle
+ Vision.Image.Contour: instance GHC.Show.Show Vision.Image.Contour.ContourDrawStyle
+ Vision.Image.Contour: instance GHC.Show.Show Vision.Image.Contour.ContourId
+ Vision.Image.Contour: instance GHC.Show.Show Vision.Image.Contour.ContourPos
+ Vision.Image.Contour: lookupContour :: Contours -> ContourId -> Maybe Contour
+ Vision.Image.Contour: rowContour :: [ContourValue] -> RowContour
+ Vision.Image.Contour: type ContourValue = (Point, Bool)
+ Vision.Image.Contour: type OneContour = Vector ContourValue
+ Vision.Image.Contour: type RowContour = Vector (Point, Point)
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.Grey.Type.GreyPixel Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.Grey.Type.GreyPixel Vision.Image.HSV.Type.HSVPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.Grey.Type.GreyPixel Vision.Image.RGB.Type.RGBPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.Grey.Type.GreyPixel Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.HSV.Type.HSVPixel Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.HSV.Type.HSVPixel Vision.Image.HSV.Type.HSVPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.HSV.Type.HSVPixel Vision.Image.RGB.Type.RGBPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.HSV.Type.HSVPixel Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.RGB.Type.RGBPixel Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.RGB.Type.RGBPixel Vision.Image.HSV.Type.HSVPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.RGB.Type.RGBPixel Vision.Image.RGB.Type.RGBPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.RGB.Type.RGBPixel Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.RGBA.Type.RGBAPixel Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.RGBA.Type.RGBAPixel Vision.Image.HSV.Type.HSVPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.RGBA.Type.RGBAPixel Vision.Image.RGB.Type.RGBPixel
+ Vision.Image.Conversion: instance Data.Convertible.Base.Convertible Vision.Image.RGBA.Type.RGBAPixel Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Image.Filter.Internal: [fFold] :: Filter src kernel init fold acc res -> !fold
+ Vision.Image.Filter.Internal: [fInit] :: Filter src kernel init fold acc res -> !(Point -> src -> init)
+ Vision.Image.Filter.Internal: [fInterpol] :: Filter src kernel init fold acc res -> !(BorderInterpolate src)
+ Vision.Image.Filter.Internal: [fKernelCenter] :: Filter src kernel init fold acc res -> !KernelAnchor
+ Vision.Image.Filter.Internal: [fKernelSize] :: Filter src kernel init fold acc res -> !Size
+ Vision.Image.Filter.Internal: [fKernel] :: Filter src kernel init fold acc res -> !kernel
+ Vision.Image.Filter.Internal: [fPost] :: Filter src kernel init fold acc res -> !(Point -> src -> init -> acc -> res)
+ Vision.Image.Filter.Internal: [skHorizontal] :: SeparableKernel src init acc -> !(init -> DIM1 -> acc -> acc -> acc)
+ Vision.Image.Filter.Internal: [skVertical] :: SeparableKernel src init acc -> !(init -> DIM1 -> src -> acc -> acc)
+ Vision.Image.Filter.Internal: instance (Vision.Image.Class.Image src, Vision.Image.Class.FromFunction res, src_pix ~ Vision.Image.Class.ImagePixel src, res_pix ~ Vision.Image.Class.FromFunctionPixel res) => Vision.Image.Filter.Internal.Filterable src res (Vision.Image.Filter.Internal.BoxFilter src_pix init acc res_pix)
+ Vision.Image.Filter.Internal: instance (Vision.Image.Class.Image src, Vision.Image.Class.FromFunction res, src_pix ~ Vision.Image.Class.ImagePixel src, res_pix ~ Vision.Image.Class.FromFunctionPixel res) => Vision.Image.Filter.Internal.Filterable src res (Vision.Image.Filter.Internal.BoxFilter1 src_pix init res_pix)
+ Vision.Image.Filter.Internal: instance (Vision.Image.Class.Image src, Vision.Image.Class.FromFunction res, src_pix ~ Vision.Image.Class.ImagePixel src, res_pix ~ Vision.Image.Class.FromFunctionPixel res, Vision.Image.Filter.Internal.SeparatelyFiltrable src res acc) => Vision.Image.Filter.Internal.Filterable src res (Vision.Image.Filter.Internal.SeparableFilter src_pix init acc res_pix)
+ Vision.Image.Filter.Internal: instance (Vision.Image.Class.Image src, Vision.Image.Class.FromFunction res, src_pix ~ Vision.Image.Class.ImagePixel src, res_pix ~ Vision.Image.Class.FromFunctionPixel res, Vision.Image.Filter.Internal.SeparatelyFiltrable src res src_pix) => Vision.Image.Filter.Internal.Filterable src res (Vision.Image.Filter.Internal.SeparableFilter1 src_pix init res_pix)
+ Vision.Image.Filter.Internal: instance Foreign.Storable.Storable acc => Vision.Image.Filter.Internal.SeparatelyFiltrable src (Vision.Image.Type.Delayed p) acc
+ Vision.Image.Filter.Internal: instance Foreign.Storable.Storable acc => Vision.Image.Filter.Internal.SeparatelyFiltrable src (Vision.Image.Type.Manifest p) acc
+ Vision.Image.Filter.Internal: type family SeparableFilterAccumulator src res acc;
+ Vision.Image.Filter.Internal: }
+ Vision.Image.Grey.Type: instance Data.Bits.Bits Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance Foreign.Storable.Storable Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance GHC.Classes.Eq Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance GHC.Classes.Ord Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance GHC.Enum.Bounded Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance GHC.Enum.Enum Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance GHC.Num.Num Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance GHC.Read.Read Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance GHC.Real.Integral Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance GHC.Real.Real Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance GHC.Show.Show Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance Vision.Image.Class.Pixel Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.Grey.Type: instance Vision.Image.Interpolate.Interpolable Vision.Image.Grey.Type.GreyPixel
+ Vision.Image.HSV.Type: [hsvHue] :: HSVPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.HSV.Type: [hsvSat] :: HSVPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.HSV.Type: [hsvValue] :: HSVPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.HSV.Type: instance Foreign.Storable.Storable Vision.Image.HSV.Type.HSVPixel
+ Vision.Image.HSV.Type: instance GHC.Classes.Eq Vision.Image.HSV.Type.HSVPixel
+ Vision.Image.HSV.Type: instance GHC.Show.Show Vision.Image.HSV.Type.HSVPixel
+ Vision.Image.HSV.Type: instance Vision.Image.Class.Pixel Vision.Image.HSV.Type.HSVPixel
+ Vision.Image.HSV.Type: instance Vision.Image.Interpolate.Interpolable Vision.Image.HSV.Type.HSVPixel
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Int.Int16
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Int.Int32
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Types.Bool
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Types.Double
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Types.Float
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Types.Int
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Types.Word
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Word.Word16
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Word.Word32
+ Vision.Image.Interpolate: instance Vision.Image.Interpolate.Interpolable GHC.Word.Word8
+ Vision.Image.Mutable: [mmSize] :: MutableManifest p s -> !Size
+ Vision.Image.Mutable: [mmVector] :: MutableManifest p s -> !(MVector s p)
+ Vision.Image.Mutable: instance Foreign.Storable.Storable p => Vision.Image.Mutable.MutableImage (Vision.Image.Mutable.MutableManifest p)
+ Vision.Image.Mutable: type family Freezed i;
+ Vision.Image.Mutable: }
+ Vision.Image.RGB.Type: [rgbBlue] :: RGBPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.RGB.Type: [rgbGreen] :: RGBPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.RGB.Type: [rgbRed] :: RGBPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.RGB.Type: instance Foreign.Storable.Storable Vision.Image.RGB.Type.RGBPixel
+ Vision.Image.RGB.Type: instance GHC.Classes.Eq Vision.Image.RGB.Type.RGBPixel
+ Vision.Image.RGB.Type: instance GHC.Show.Show Vision.Image.RGB.Type.RGBPixel
+ Vision.Image.RGB.Type: instance Vision.Image.Class.Pixel Vision.Image.RGB.Type.RGBPixel
+ Vision.Image.RGB.Type: instance Vision.Image.Interpolate.Interpolable Vision.Image.RGB.Type.RGBPixel
+ Vision.Image.RGBA.Type: [rgbaAlpha] :: RGBAPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.RGBA.Type: [rgbaBlue] :: RGBAPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.RGBA.Type: [rgbaGreen] :: RGBAPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.RGBA.Type: [rgbaRed] :: RGBAPixel -> {-# UNPACK #-} !Word8
+ Vision.Image.RGBA.Type: instance Foreign.Storable.Storable Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Image.RGBA.Type: instance GHC.Classes.Eq Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Image.RGBA.Type: instance GHC.Show.Show Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Image.RGBA.Type: instance Vision.Image.Class.Pixel Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Image.RGBA.Type: instance Vision.Image.Interpolate.Interpolable Vision.Image.RGBA.Type.RGBAPixel
+ Vision.Image.Threshold: [BinaryThreshold] :: res -> res -> ThresholdType src res
+ Vision.Image.Threshold: [GaussianKernel] :: (Floating acc, RealFrac acc) => Maybe acc -> AdaptiveThresholdKernel acc
+ Vision.Image.Threshold: [MeanKernel] :: Integral acc => AdaptiveThresholdKernel acc
+ Vision.Image.Threshold: [TruncateInv] :: src -> ThresholdType src src
+ Vision.Image.Threshold: [Truncate] :: src -> ThresholdType src src
+ Vision.Image.Type: [delayedFun] :: Delayed p -> !(Point -> p)
+ Vision.Image.Type: [delayedMaskFun] :: DelayedMask p -> !(Point -> Maybe p)
+ Vision.Image.Type: [delayedMaskSize] :: DelayedMask p -> !Size
+ Vision.Image.Type: [delayedSize] :: Delayed p -> !Size
+ Vision.Image.Type: [manifestSize] :: Manifest p -> !Size
+ Vision.Image.Type: [manifestVector] :: Manifest p -> !(Vector p)
+ Vision.Image.Type: instance (Foreign.Storable.Storable p, GHC.Show.Show p) => GHC.Show.Show (Vision.Image.Type.Manifest p)
+ Vision.Image.Type: instance (Foreign.Storable.Storable p1, Foreign.Storable.Storable p2, Data.Convertible.Base.Convertible p1 p2) => Data.Convertible.Base.Convertible (Vision.Image.Type.Delayed p1) (Vision.Image.Type.Delayed p2)
+ Vision.Image.Type: instance (Foreign.Storable.Storable p1, Foreign.Storable.Storable p2, Data.Convertible.Base.Convertible p1 p2) => Data.Convertible.Base.Convertible (Vision.Image.Type.Delayed p1) (Vision.Image.Type.Manifest p2)
+ Vision.Image.Type: instance (Foreign.Storable.Storable p1, Foreign.Storable.Storable p2, Data.Convertible.Base.Convertible p1 p2) => Data.Convertible.Base.Convertible (Vision.Image.Type.Manifest p1) (Vision.Image.Type.Delayed p2)
+ Vision.Image.Type: instance (Foreign.Storable.Storable p1, Foreign.Storable.Storable p2, Data.Convertible.Base.Convertible p1 p2) => Data.Convertible.Base.Convertible (Vision.Image.Type.Manifest p1) (Vision.Image.Type.Manifest p2)
+ Vision.Image.Type: instance (GHC.Classes.Eq p, Foreign.Storable.Storable p) => GHC.Classes.Eq (Vision.Image.Type.Manifest p)
+ Vision.Image.Type: instance (GHC.Classes.Ord p, Foreign.Storable.Storable p) => GHC.Classes.Ord (Vision.Image.Type.Manifest p)
+ Vision.Image.Type: instance (Vision.Image.Class.Image src, Foreign.Storable.Storable p) => Vision.Image.Class.FunctorImage src (Vision.Image.Type.Delayed p)
+ Vision.Image.Type: instance (Vision.Image.Class.Image src, Foreign.Storable.Storable p) => Vision.Image.Class.FunctorImage src (Vision.Image.Type.Manifest p)
+ Vision.Image.Type: instance (Vision.Image.Class.MaskedImage src, Foreign.Storable.Storable p) => Vision.Image.Class.FunctorImage src (Vision.Image.Type.DelayedMask p)
+ Vision.Image.Type: instance Control.DeepSeq.NFData (Vision.Image.Type.Manifest p)
+ Vision.Image.Type: instance Foreign.Storable.Storable p => Vision.Image.Class.FromFunction (Vision.Image.Type.DelayedMask p)
+ Vision.Image.Type: instance Foreign.Storable.Storable p => Vision.Image.Class.FromFunction (Vision.Image.Type.Manifest p)
+ Vision.Image.Type: instance Foreign.Storable.Storable p => Vision.Image.Class.Image (Vision.Image.Type.Delayed p)
+ Vision.Image.Type: instance Foreign.Storable.Storable p => Vision.Image.Class.Image (Vision.Image.Type.Manifest p)
+ Vision.Image.Type: instance Foreign.Storable.Storable p => Vision.Image.Class.MaskedImage (Vision.Image.Type.Delayed p)
+ Vision.Image.Type: instance Foreign.Storable.Storable p => Vision.Image.Class.MaskedImage (Vision.Image.Type.DelayedMask p)
+ Vision.Image.Type: instance Foreign.Storable.Storable p => Vision.Image.Class.MaskedImage (Vision.Image.Type.Manifest p)
+ Vision.Image.Type: instance Vision.Image.Class.FromFunction (Vision.Image.Type.Delayed p)
+ Vision.Primitive: [rHeight] :: Rect -> {-# UNPACK #-} !Int
+ Vision.Primitive: [rWidth] :: Rect -> {-# UNPACK #-} !Int
+ Vision.Primitive: [rX] :: Rect -> {-# UNPACK #-} !Int
+ Vision.Primitive: [rY] :: Rect -> {-# UNPACK #-} !Int
+ Vision.Primitive: [rpX] :: RPoint -> {-# UNPACK #-} !RatioInt
+ Vision.Primitive: [rpY] :: RPoint -> {-# UNPACK #-} !RatioInt
+ Vision.Primitive: instance GHC.Classes.Eq Vision.Primitive.RPoint
+ Vision.Primitive: instance GHC.Classes.Eq Vision.Primitive.Rect
+ Vision.Primitive: instance GHC.Classes.Ord Vision.Primitive.RPoint
+ Vision.Primitive: instance GHC.Classes.Ord Vision.Primitive.Rect
+ Vision.Primitive: instance GHC.Read.Read Vision.Primitive.RPoint
+ Vision.Primitive: instance GHC.Read.Read Vision.Primitive.Rect
+ Vision.Primitive: instance GHC.Show.Show Vision.Primitive.RPoint
+ Vision.Primitive: instance GHC.Show.Show Vision.Primitive.Rect
+ Vision.Primitive.Shape: instance (Data.Vector.Unboxed.Base.Unbox t, Data.Vector.Unboxed.Base.Unbox h) => Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector (t Vision.Primitive.Shape.:. h)
+ Vision.Primitive.Shape: instance (Data.Vector.Unboxed.Base.Unbox t, Data.Vector.Unboxed.Base.Unbox h) => Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector (t Vision.Primitive.Shape.:. h)
+ Vision.Primitive.Shape: instance (Data.Vector.Unboxed.Base.Unbox t, Data.Vector.Unboxed.Base.Unbox h) => Data.Vector.Unboxed.Base.Unbox (t Vision.Primitive.Shape.:. h)
+ Vision.Primitive.Shape: instance (GHC.Classes.Eq head, GHC.Classes.Eq tail) => GHC.Classes.Eq (tail Vision.Primitive.Shape.:. head)
+ Vision.Primitive.Shape: instance (GHC.Classes.Ord head, GHC.Classes.Ord tail) => GHC.Classes.Ord (tail Vision.Primitive.Shape.:. head)
+ Vision.Primitive.Shape: instance (GHC.Read.Read head, GHC.Read.Read tail) => GHC.Read.Read (tail Vision.Primitive.Shape.:. head)
+ Vision.Primitive.Shape: instance (GHC.Show.Show head, GHC.Show.Show tail) => GHC.Show.Show (tail Vision.Primitive.Shape.:. head)
+ Vision.Primitive.Shape: instance Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector Vision.Primitive.Shape.Z
+ Vision.Primitive.Shape: instance Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector Vision.Primitive.Shape.Z
+ Vision.Primitive.Shape: instance Data.Vector.Unboxed.Base.Unbox Vision.Primitive.Shape.Z
+ Vision.Primitive.Shape: instance Foreign.Storable.Storable Vision.Primitive.Shape.Z
+ Vision.Primitive.Shape: instance Foreign.Storable.Storable sh => Foreign.Storable.Storable (sh Vision.Primitive.Shape.:. GHC.Types.Int)
+ Vision.Primitive.Shape: instance GHC.Classes.Eq Vision.Primitive.Shape.Z
+ Vision.Primitive.Shape: instance GHC.Classes.Ord Vision.Primitive.Shape.Z
+ Vision.Primitive.Shape: instance GHC.Read.Read Vision.Primitive.Shape.Z
+ Vision.Primitive.Shape: instance GHC.Show.Show Vision.Primitive.Shape.Z
+ Vision.Primitive.Shape: instance Vision.Primitive.Shape.Shape Vision.Primitive.Shape.Z
+ Vision.Primitive.Shape: instance Vision.Primitive.Shape.Shape sh => Vision.Primitive.Shape.Shape (sh Vision.Primitive.Shape.:. GHC.Types.Int)
- Vision.Histogram: class (Pixel p, Shape (PixelValueSpace p)) => ToHistogram p where type family PixelValueSpace p
+ Vision.Histogram: class (Pixel p, Shape (PixelValueSpace p)) => ToHistogram p where type PixelValueSpace p where {
- Vision.Image.Class: class FromFunction i where type family FromFunctionPixel i fromFunctionLine size line f = fromFunction size (\ pt@(Z :. y :. _) -> f (line y) pt) fromFunctionCol size col f = fromFunction size (\ pt@(Z :. _ :. x) -> f (col x) pt) fromFunctionCached size line col f = fromFunction size (\ pt@(Z :. y :. x) -> f (line y) (col x) pt)
+ Vision.Image.Class: class FromFunction i where type FromFunctionPixel i fromFunctionLine size line f = fromFunction size (\ pt@(Z :. y :. _) -> f (line y) pt) fromFunctionCol size col f = fromFunction size (\ pt@(Z :. _ :. x) -> f (col x) pt) fromFunctionCached size line col f = fromFunction size (\ pt@(Z :. y :. x) -> f (line y) (col x) pt) where {
- Vision.Image.Class: class Storable (ImagePixel i) => MaskedImage i where type family ImagePixel i maskedIndex img = (img `maskedLinearIndex`) . toLinearIndex (shape img) maskedLinearIndex img = (img `maskedIndex`) . fromLinearIndex (shape img) values !img = unfoldr step 0 where !n = shapeLength (shape img) step !i | i >= n = Nothing | Just p <- img `maskedLinearIndex` i = Just (p, i + 1) | otherwise = step (i + 1)
+ Vision.Image.Class: class Storable (ImagePixel i) => MaskedImage i where type ImagePixel i maskedIndex img = (img `maskedLinearIndex`) . toLinearIndex (shape img) maskedLinearIndex img = (img `maskedIndex`) . fromLinearIndex (shape img) values !img = unfoldr step 0 where !n = shapeLength (shape img) step !i | i >= n = Nothing | Just p <- img `maskedLinearIndex` i = Just (p, i + 1) | otherwise = step (i + 1) where {
- Vision.Image.Class: class Pixel p where type family PixelChannel p
+ Vision.Image.Class: class Pixel p where type PixelChannel p where {
- Vision.Image.Filter.Internal: class (Image (SeparableFilterAccumulator src res acc), ImagePixel (SeparableFilterAccumulator src res acc) ~ acc, FromFunction (SeparableFilterAccumulator src res acc), FromFunctionPixel (SeparableFilterAccumulator src res acc) ~ acc) => SeparatelyFiltrable src res acc where type family SeparableFilterAccumulator src res acc
+ Vision.Image.Filter.Internal: class (Image (SeparableFilterAccumulator src res acc), ImagePixel (SeparableFilterAccumulator src res acc) ~ acc, FromFunction (SeparableFilterAccumulator src res acc), FromFunctionPixel (SeparableFilterAccumulator src res acc) ~ acc) => SeparatelyFiltrable src res acc where type SeparableFilterAccumulator src res acc where {
- Vision.Image.Mutable: class Image (Freezed i) => MutableImage i where type family Freezed i read !img !ix = img `linearRead` toLinearIndex (mShape img) ix linearRead !img !ix = img `read` fromLinearIndex (mShape img) ix write !img !ix !val = linearWrite img (toLinearIndex (mShape img) ix) val linearWrite !img !ix !val = write img (fromLinearIndex (mShape img) ix) val unsafeFreeze = freeze
+ Vision.Image.Mutable: class Image (Freezed i) => MutableImage i where type Freezed i read !img !ix = img `linearRead` toLinearIndex (mShape img) ix linearRead !img !ix = img `read` fromLinearIndex (mShape img) ix write !img !ix !val = linearWrite img (toLinearIndex (mShape img) ix) val linearWrite !img !ix !val = write img (fromLinearIndex (mShape img) ix) val unsafeFreeze = freeze where {
- Vision.Image.Mutable: create :: MutableImage i => (forall s. ST s (i s)) -> Freezed i
+ Vision.Image.Mutable: create :: (MutableImage i) => (forall s. ST s (i s)) -> Freezed i
Files
- changelog +5/−0
- friday.cabal +4/−2
- src/Vision/Image/Contour.hs +405/−0
- src/Vision/Primitive/Shape.hs +56/−0
changelog view
@@ -1,5 +1,10 @@ -*-change-log-*- +v0.2.3.0 December 2016+ * Add Contour Tracing (Vision.Image.Contour)+ * Add pointer to friday-juicypixels+ * First release by TomMD - Raphael is MIA but it remains his package.+ v0.2.2.0 June 2015 * New 'computeP' function to compute an image in parallel.
friday.cabal view
@@ -2,7 +2,7 @@ -- +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.2.2.0+version: 0.2.3.0 synopsis: A functional image processing library for Haskell. homepage: https://github.com/RaphaelJ/friday license: LGPL-3@@ -50,6 +50,7 @@ Vision.Image Vision.Image.Class Vision.Image.Conversion+ Vision.Image.Contour Vision.Image.Grey Vision.Image.Grey.Specialize Vision.Image.Grey.Type@@ -78,12 +79,13 @@ default-language: Haskell2010 build-depends: base >= 4 && < 5+ , containers >= 0.4 && < 0.6 , convertible >= 1 && < 2 , deepseq >= 1.3 && < 2 , primitive >= 0.5.2.1 && < 0.7 , ratio-int >= 0.1.2 && < 0.2 , vector >= 0.10.0.1 && < 1- , transformers >= 0.3 && < 0.5+ , transformers >= 0.3 && < 0.6 Test-Suite test type: exitcode-stdio-1.0
+ src/Vision/Image/Contour.hs view
@@ -0,0 +1,405 @@+{-# LANGUAGE BangPatterns+ , FlexibleContexts+ , CPP+ , GeneralizedNewtypeDeriving+ , ScopedTypeVariables+ , FlexibleInstances+ , MultiWayIf #-}+-- | Contour tracing of binary images (zero ~ background, nonzero ~ object).+--+-- Terminology:+--+-- A binary image is an image in which the pixel is boolean (represented+-- here using 'Grey' and zero or non-zero pixel values).+--+-- All zero-value pixels are part of the "background".+--+-- An object is an connected group of non-zero pixels.+--+-- A 'Contour' is a trace of an objects' outer or inner edges. Some+-- objects are solid, having no inner contours (consider a filled circle,+-- or letters such as 'h', 's', 'k' and 'l'). Other objects have "holes", also known as inner+-- contours. The letters 'a' and 'e' have one hole while the letter 'B' has two.+--+-- After obtaining a 'Contours' structure (via the 'contours' function) the+-- raw traces ('Contour' type) can be used for further processing or the contours can be+-- filtered by aspects of interest and selectively re-drawn ('drawContour') , perhaps used to+-- mask the original image.+--+-- About Holes:+--+-- In cases where there is only one hole it is uniquely recorded in the+-- 'Contours' structure. Objects with more than one hole record all inner+-- contours in one vector making them hard to extract separately - this is+-- due to the main data structure not being rich enough to record the holes+-- separately. As of writing, this is not seen as an issue because the+-- desired operation, drawContour, can still be achieved. Changing this+-- behavior should be trivial if desired.+--+-- Use:+--+-- To use this library it is advised that you preprocess the image,+-- including thresholding (ex: 'otsu' on a grey scale image), to obtain a binary image then call:+--+-- @+-- cs = contours img+-- @+--+-- The 'Contours' structure can be accessed directly if desired. It+-- includes an 'Map' of all contours (numbered counting from 1) and+-- a vector of the contour sizes (indexed by contour number, zero index is+-- unused/zero).+--+-- The algorithm implemented in this module follows the design laid out in+-- 'A Linear-Time Component-Labeling Algorithm Using Contour Tracing Technique' [1].+--+-- [1] http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.6330&rep=rep1&type=pdf+module Vision.Image.Contour (+ -- * Main Interface+ Contours(..), ContourId, OneContour, ContourValue, Contour(..), RowContour+ , contours+ -- * ADT style interface (hides 'Contours' internals)+ , allContourIds, lookupContour, rowContour, contourSize, contourPerimeter+ -- * Reconstructing Image Elements+ , ContourDrawStyle(..), drawContour, drawContours+ ) where++#if __GLASGOW_HASKELL__ < 710+import Control.Applicative+#endif++import Control.Monad (when)+import Control.Monad.ST+import qualified Data.Map.Strict as Map+import Data.Map.Strict (Map)+import Data.Maybe (catMaybes)+import Data.List (groupBy,sort)+import Data.Function (on)+import qualified Data.Vector.Unboxed as VU+import qualified Data.Vector.Unboxed.Mutable as VM+import Foreign.Storable++import Vision.Image.Mutable (MutableManifest, new', write)+import qualified Vision.Image.Mutable as Mut+import Vision.Image.Grey (Grey,GreyPixel)+import Vision.Image.Type (Delayed)+import Vision.Image.Class (+ MaskedImage (..), Image (..), FromFunction (..), index+ )+import Vision.Primitive (+ Z (..), (:.) (..), Point, ix2, Size+ )++--------------------------------------------------------------------------------+-- Types and ADT-Style Interface++-- | Contours of an image include:+-- * A map from contour number to outer points and negative contour number of inner contour points.+-- * A vector of sizes for each contour for domain [1..size contourOutlines] (the zero index is meaningless)+data Contours =+ Contours { contourOutlines :: Map ContourId Contour+ , contourSizes :: !(VU.Vector Int)+ }++allContourIds :: Contours -> [ContourId]+allContourIds = Map.keys . contourOutlines++contourPerimeter :: Contours -> ContourId -> [Point]+contourPerimeter m i =+ maybe [] (map fst . VU.toList . outerContour) (lookupContour m i)++contourSize :: Contours -> ContourId -> Int+contourSize (Contours _ s) i+ | unCID i < 0 || unCID i >= VU.length s = 0+ | otherwise = s VU.! unCID i++lookupContour :: Contours -> ContourId -> Maybe Contour+lookupContour m i = Map.lookup i (contourOutlines m)++-- |Contours are identified by a numeric ID number.+newtype ContourId = CID { unCID :: Int } deriving (Eq, Ord, Storable, Num, Show)++-- |A contour is described by the points on the perimeter and a boolean+-- indicating if that point is "terminal" (next pixel to+-- the right is background iff the point is terminal). The terminal+-- information allows for a slightly simpler 'drawContour' implementation.+type OneContour = VU.Vector ContourValue+type ContourValue = (Point,Bool)+data Contour = Contour { outerContour :: OneContour+ , innerContours :: [OneContour]+ } -- Pair of outer and inner contours++insOuterContour :: ContourId -> OneContour -> Map ContourId Contour+ -> Map ContourId Contour+insOuterContour cid o mp =+ let c = Contour o []+ in Map.insert cid c mp++insInnerContour :: ContourId -> OneContour -> Map ContourId Contour+ -> Map ContourId Contour+insInnerContour cid i mp =+ let c = Contour (error "Impossible: Inner contour with no outer!") [i]+ f _ (Contour o is) = Contour o (i:is)+ in Map.insertWith f cid c mp++-- |RowContour is a method of expressing contours by, for each row,+-- recording the start of an object and the end (due to reaching the other+-- side or a hole/inner contour) for each row.+type RowContour = VU.Vector (Point,Point)++--------------------------------------------------------------------------------+-- Image Reconstruction++-- | Outline: Just draw the edge.+--+-- OuterOutline: Outline the outer contours only, no hole contours+-- AllOutlines: Draw all contours+-- Fill: Draw the object but fill it in, ignoring holes.+-- FillWithHoles: Draw the object and do not fill in the holes.+data ContourDrawStyle = OuterOutline | AllOutlines | Fill | FillWithHoles+ deriving (Eq, Ord, Show, Read, Enum, Bounded)++-- | Draws a given contour. The size specified must be large enough to+-- include the coordinate originally occupied by the contour being drawn,+-- no cropping or other transformation is done.+drawContour :: Contours -> Size -> ContourDrawStyle -> ContourId -> Grey+drawContour master sz sty c = drawContours master sz sty [c]++-- |Draws many contours. See 'drawContour'.+drawContours :: Contours -> Size -> ContourDrawStyle -> [ContourId] -> Grey+drawContours m sz AllOutlines ids = drawOutlines listOfUVec m ids sz+ where listOfUVec (Contour o is) = o:is+drawContours m sz OuterOutline ids = drawOutlines listOfUVec m ids sz+ where listOfUVec (Contour o _) = [o]+drawContours m sz sty ids = drawRows pnts sz+ where lk = lookupContour m+ pnts = case sty of+ Fill -> map (VU.toList . outerContour) $ catMaybes $ map lk ids -- map (map (\(a,x) -> (a,not x)) . lk) innerIds ++ map lk outerIds+ FillWithHoles -> map (concatMap VU.toList . maybe [] (\x -> outerContour x : innerContours x) . lk) ids+ _ -> error "Impossible: Style is not Fill, FillWithHoles"++drawOutlines :: (Contour -> [VU.Vector ContourValue]) -> Contours -> [ContourId] -> Size -> Grey+drawOutlines oper m ids sz = runST f+ where+ f = do+ i <- new' sz 0 :: ST s (MutableManifest GreyPixel s)+ let vs = map fst $ concatMap VU.toList $ concatMap oper $ catMaybes $ map (lookupContour m) ids+ mapM_ (\p -> write i p 255) vs+ Mut.unsafeFreeze i+++-- | Draws rows, throwing an exception when the size is too small for the+-- coordinates.+drawRows :: [[ContourValue]] -> Size -> Grey+drawRows vs sz = runST $ do+ i <- new' sz 0+ mapM_ (drawMutable i) vs+ Mut.unsafeFreeze i++drawMutable :: MutableManifest GreyPixel s -> [ContourValue] -> ST s ()+drawMutable i cs = VU.mapM_ (f i) rs+ where+ rs = rowContour cs+ f img (start,stop) = go (start, stop)+ where go (s@(Z:.row:.col),t) = do+ write img s 255+ when (s /= t) $ go (Z :. row :. (col+1),t)++-- |Given a vector including outer (and optionally inner) contour points,+-- make 'row contour' from which is easier to transform back into a binary+-- image. By not including the inner contour points the row will be filled, making+-- traces of objects with holes appear solid.+rowContour :: [ContourValue] -> RowContour+rowContour cs =+ let rows :: [[(Point,Bool)]]+ rows = groupBy ((==) `on` ((\(Z:.r:._) -> r) . fst)) $ sort cs -- XXX consider vector quick/tim sort+ in VU.fromList $ concatMap walkM rows+ where+ walkM :: [(Point,Bool)] -> [(Point,Point)]+ walkM [x] = [(fst x,fst x)]+ walkM x = maybe (error $ "Impossible: No terminal when walking contour: " ++ show (x,cs)) id $ walk x+ walk :: [(Point,Bool)] -> Maybe [(Point,Point)]+ walk [] = Just []+ walk xs@(x:_) = case dropWhile (not . snd) xs of+ [] -> Nothing+ (t:ys) -> ((fst x,fst t) :) <$> walk ys++-- |The meat of this module is the 'contours' function, which extracts+-- the contours (outer and inner outlines) of a binary image.+-- Zero-valued pixels are the background and non-zero are active/objects to+-- trace. The output, 'Contours', contains enough information to determine+-- the number of contours, their traces, the size in pixels (filled size+-- and perimeter), number of holes, etc.+contours :: (Image src, Num (ImagePixel src), Eq (ImagePixel src)) => src -> Contours+contours src = runST $ do+ let bsrc = fromFunction (Z :. y+2 :. x+2) mkBorder+ mutImg <- new' (shape bsrc) zid+ (outlines,sz) <- doLabeling bsrc mutImg+ sizes <- freezeBlobSizes sz+ return (Contours outlines sizes)+ where+ (Z :. y :. x) = shape src++ mkBorder (Z :. j :. i)+ | j == 0 || j == (y+1) || i == 0 || i == (x+1) = background+ | otherwise = index src (Z :. j-1 :. i-1)++-- The image is assumed to be binary and should have values of either 0 (black) or... nonzero (white)+-- here we assume the background is black. Nonzero would require more+-- change elsewhere!+background :: Num a => a+background = 0++zid :: ContourId+zid = CID 0++data BlobSizes s = BS (VM.MVector s Int)++freezeBlobSizes :: BlobSizes s -> ST s (VU.Vector Int)+freezeBlobSizes (BS v) = VU.unsafeFreeze v++incBlobSizes :: ContourId -> BlobSizes s -> ST s (BlobSizes s)+incBlobSizes (CID i) s@(BS v)+ | i > 0 =+ if VM.length v <= i+ then do nv <- VM.unsafeGrow v (i*2)+ mapM_ (\ix -> VM.unsafeWrite nv ix 0) [i..i*2-1]+ VM.unsafeWrite nv i 1+ return (BS nv)+ else do p <- VM.unsafeRead v i+ VM.unsafeWrite v i (p+1)+ return s+ | otherwise = return s++zeroBlobSizes :: ST s (BlobSizes s)+zeroBlobSizes = BS <$> VM.replicate 1024 0++-- Make a contour image of the same dimension but with ContourIDs instead+-- of pixels.+doLabeling :: forall s p. (Storable p, Num p, Eq p) => Delayed p -> MutableManifest ContourId s -> ST s (Map ContourId Contour,BlobSizes s)+doLabeling src mutImg = zeroBlobSizes >>= go (Just $ ix2 1 1) (CID 0) (CID 1) mempty+ where+ getCID :: Point -> ST s ContourId+ getCID = Mut.read mutImg+ setCID i c = write mutImg i c+ getPixel :: Point -> ImagePixel (Delayed p)+ getPixel = index src++ incIx :: Point -> Maybe Point+ incIx !(Z :. (!y) :. (!x))+ | x < xMax-1 = Just $ Z :. y :. (x+1)+ | y < yMax-1 = Just $ Z :. (y+1) :. 1+ | otherwise = Nothing++ (Z :. yMax :. xMax) = shape src++ -- Traverse the source image top to bottom, left to right. If the pixel+ -- has an ID then propagate that ID to all the following active pixels in+ -- the row. If the pixel is active and has no ID then trace either an+ -- inner or outer contour. If the pixel is inactive then skip it.+ go Nothing _ _ !mp v = return (mp,v)+ go (Just idx) leftCID !newCID !mp v =+ do thisCID <- getCID idx+ if | val == background -> skipForward -- this step doesn't appear in the paper! D'oh+ | thisCID == zid && above == background ->+ do -- Step 1: Outer contour trace (active pixel with id=0 and above is background)+ newContour <- traceContour src mutImg ExternalContour idx newCID+ go (Just idx) newCID (newCID + 1) (insOuterContour newCID newContour mp) v+ | below == background -> -- Step 2: P is an white pixel+ do belowCID <- getCID belowIdx -- ^ ^+ if | belowCID == zid -> -- ^ unmarked ^+ do -- Step 2a: Inner contour trace, below pixel was unmarked+ let innerCID = if zid == thisCID then leftCID else thisCID+ inner <- traceContour src mutImg InternalContour idx innerCID+ go (incIx idx) innerCID newCID (insInnerContour innerCID inner mp) v+ -- there can be more than one inner contour, make a richer container structure than IntMap?+ -- Notice this isn't entirely necessary, one+ -- CID can contain all inner contours and they can be redrawn correctly.+ | otherwise -> stepForward -- Step 2b: Previously-observed contour+ | otherwise -> stepForward -- Active pixel not on a contour+ where val = getPixel idx+ above = getPixel (Z :. y-1 :. x)+ below = getPixel belowIdx+ belowIdx = Z :. y+1 :. x+ Z :. y :. x = idx+ stepForward = do xId <- if leftCID <= zid+ then getCID idx+ else return leftCID+ setCID idx xId+ nv <- incBlobSizes xId v+ go (incIx idx) xId newCID mp nv+ skipForward = go (incIx idx) (-2) newCID mp v++-- Mark surrounding background pixels+-- label non-background pixels with CID+--+-- Unroll the loop one step to account for the lone-pixel case. Without+-- lone pixels the tight inner loop can save a check (See 'Impossible')+--+-- TODO: optimize later, duplicate tracer and remove the p==pos, after a benchmarking method is setup.+traceContour :: forall p s. (Storable p, Num p, Eq p) => Delayed p -> MutableManifest ContourId s -> ContourType -> Point -> ContourId -> ST s OneContour+traceContour src mutImg contourTy origPnt assignedCID =+ do next <- tracer origPnt startPos+ case next of+ Nothing -> return (VU.fromList $ fixList [(origPnt,True)])+ Just (sndPnt,sndPos) -> do+ let f pnt pos = do (nPnt,nPos) <- maybe (error "Impossible: Nothing in inner") id <$> tracer pnt pos+ if pnt == origPnt && nPnt == sndPnt+ then return [] -- XXX some algorithms duplicate the start point, pnt, as the last point `return [pnt]`. Should we?+ else ((pnt,terminal pnt) :) <$> f nPnt nPos+ VU.fromList . fixList . ((origPnt, terminal origPnt):) <$> f sndPnt sndPos++ where+ terminal (Z :. row :. col) = 0 == getPixel (Z :. row :. (col+1))+ -- Translate between indexes in our border-added image and the original+ fixList xs = let f (Z :. a :. b, t) = (Z :. a-1 :. b-1,t) in map f xs+ startPos = case contourTy of { ExternalContour -> UR ; InternalContour -> LL }+ setCID i c = write mutImg i c+ getPixel :: Point -> ImagePixel (Delayed p)+ getPixel = index src++ {-# INLINE tracer #-}+ tracer pnt pos =+ let tracer' True p | p == pos = setCID pnt assignedCID >> return Nothing+ tracer' _ p = do let rpnt = relPoint pnt p+ v = getPixel rpnt+ if | v == background -> do setCID rpnt (-1)+ tracer' True (incCP p)+ | otherwise -> do setCID pnt assignedCID+ return (Just (rpnt, decCP2 p))+ in tracer' False pos+++--------------------------------------------------------------------------------+-- Internal Types and Utilities++data ContourType = ExternalContour | InternalContour deriving (Eq)++-- A contour position is Upper/Lower/Middle Left/Center/Right pixel+-- relative to the current. Because we add a border to the image prior+-- to processing, all original pixels `cross` contours positions are+-- a valid point.+data ContourPos = MR | LR | LC | LL+ | ML | UL | UC | UR+ deriving (Enum, Bounded, Eq, Show)++relPoint :: Point -> ContourPos -> Point+relPoint (Z :. row :. col) pos = Z :. row' :. col'+ where !row' = row + y+ !col' = col + x+ x = colOffset VU.! fromEnum pos+ y = rowOffset VU.! fromEnum pos++-- Rather than have branching (and expected poor performance),+-- use a table of x/y offsets for the relative pixel position.+colOffset,rowOffset :: VU.Vector Int+rowOffset = VU.fromList [0,1,1,1,0,-1,-1,-1]+colOffset = VU.fromList [1,1,0,-1,-1,-1,0,1]++-- Position clockwise by one tick+incCP :: ContourPos -> ContourPos+incCP = toEnum . ((`rem` 8) . (+ 1)) . fromEnum++-- Position counter-clockwise by two ticks+decCP2 :: ContourPos -> ContourPos+decCP2 = toEnum . ((`rem` 8) . (+ 6)) . fromEnum
src/Vision/Primitive/Shape.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE BangPatterns , CPP , FlexibleInstances+ , TypeFamilies, MultiParamTypeClasses, FlexibleContexts , TypeOperators #-} -- | 'Shape's are similar to what you could found in @repa@. 'Shape' are used@@ -28,6 +29,10 @@ import Foreign.Storable (Storable (..)) import Foreign.Ptr (castPtr, plusPtr)+import Data.Vector.Unboxed (Unbox)+import qualified Data.Vector.Unboxed as VU+import Data.Vector.Generic.Mutable (MVector(..))+import qualified Data.Vector.Generic as VG -- | Class of types that can be used as array shapes and indices. class Eq sh => Shape sh where@@ -70,6 +75,57 @@ infixl 3 :. data tail :. head = !tail :. !head deriving (Show, Read, Eq, Ord)++newtype instance VU.MVector s Z = MV_Z (VU.MVector s ())+newtype instance VU.Vector Z = V_Z (VU.Vector ())++instance MVector VU.MVector Z where+ {-# INLINE basicLength #-}+ basicLength (MV_Z v) = basicLength v+ basicUnsafeSlice s e (MV_Z v) = MV_Z $ basicUnsafeSlice s e v+ basicUnsafeRead (MV_Z v) i = basicUnsafeRead v i >>= \_ -> return Z+ basicUnsafeNew i = MV_Z `fmap` basicUnsafeNew i+ basicUnsafeWrite (MV_Z v) i a = a `seq` basicUnsafeWrite v i ()+ basicOverlaps (MV_Z a) (MV_Z b) = basicOverlaps a b++instance VG.Vector VU.Vector Z where+ {-# INLINE basicLength #-}+ basicLength (V_Z v) = VG.basicLength v+ basicUnsafeFreeze (MV_Z v) = V_Z `fmap` VG.basicUnsafeFreeze v+ basicUnsafeThaw (V_Z v) = MV_Z `fmap` VG.basicUnsafeThaw v+ basicUnsafeSlice s e (V_Z v) = V_Z $ VG.basicUnsafeSlice s e v+ basicUnsafeIndexM (V_Z v) i = VG.basicUnsafeIndexM v i >>= \_ -> return Z++instance Unbox Z++newtype instance VU.MVector s (t :. h) = MV_Dim (VU.MVector s (t , h))+newtype instance VU.Vector (t :. h) = V_Dim (VU.Vector (t , h))++instance (Unbox t, Unbox h) => MVector VU.MVector (t :. h) where+ {-# INLINE basicLength #-}+ basicLength (MV_Dim v) = basicLength v+ basicUnsafeSlice s e (MV_Dim v) = MV_Dim $ basicUnsafeSlice s e v+ basicUnsafeRead (MV_Dim v) i = pairToPoint `fmap` basicUnsafeRead v i+ basicUnsafeNew i = MV_Dim `fmap` basicUnsafeNew i+ basicUnsafeWrite (MV_Dim v) i a = basicUnsafeWrite v i (pointToPair a)+ basicOverlaps (MV_Dim a) (MV_Dim b) = basicOverlaps a b++instance (Unbox t, Unbox h) => VG.Vector VU.Vector (t :. h) where+ {-# INLINE basicLength #-}+ basicLength (V_Dim v) = VG.basicLength v+ basicUnsafeFreeze (MV_Dim v) = V_Dim `fmap` VG.basicUnsafeFreeze v+ basicUnsafeThaw (V_Dim v) = MV_Dim `fmap` VG.basicUnsafeThaw v+ basicUnsafeSlice s e (V_Dim v) = V_Dim $ VG.basicUnsafeSlice s e v+ basicUnsafeIndexM (V_Dim v) i = pairToPoint `fmap` VG.basicUnsafeIndexM v i++instance (Unbox t, Unbox h) => Unbox (t :. h)++pairToPoint :: (tail, head) -> tail :. head+pairToPoint (a,b) = a :. b++pointToPair :: tail :. head -> (tail, head)+pointToPair (a :. b) = (a,b)+ -- Common dimensions. type DIM0 = Z