friday-0.2.1.2: test/Test/Vision/Image.hs
{-# LANGUAGE CPP
, FlexibleContexts
, FlexibleInstances
, TypeFamilies
, UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Test.Vision.Image (tests) where
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<*>), (<$>))
#endif
import Data.Vector.Storable (Storable, replicateM)
import Test.Framework (Test, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck (Arbitrary (..), choose)
import Vision.Image (
MaskedImage (..), Image (..), Interpolable, FromFunction (..)
, ImageChannel, Manifest (..), Delayed (..)
, Grey, GreyPixel (..), HSVPixel
, RGBA, RGBAPixel (..), RGBADelayed
, RGB, RGBPixel (..), InterpolMethod (..)
, convert, resize, horizontalFlip, verticalFlip
)
import Vision.Primitive (Z (..), (:.) (..), Size)
maxImageSize :: Int
maxImageSize = 100
instance (Arbitrary p, Storable p) => Arbitrary (Manifest p) where
arbitrary = do
w <- choose (1, maxImageSize)
h <- choose (1, maxImageSize)
vec <- replicateM (w * h) arbitrary
return $ Manifest (Z :. h :. w) vec
instance Arbitrary GreyPixel where
arbitrary = GreyPixel <$> arbitrary
instance Arbitrary RGBAPixel where
arbitrary = RGBAPixel <$> arbitrary <*> arbitrary <*> arbitrary
<*> arbitrary
instance Arbitrary RGBPixel where
arbitrary = RGBPixel <$> arbitrary <*> arbitrary <*> arbitrary
tests :: [Test]
tests = [
testGroup "Conversions identities" [
testProperty "RGB to/from RGBA" $ propRGBRGBA
, testProperty "RGB to/from HSV" $ propRGBHSV
]
, testGroup "Nearest-neighbor resize" [
testProperty "Grey" (propImageResize :: Grey -> Bool)
, testProperty "RGBA" (propImageResize :: RGBA -> Bool)
, testProperty "RGB" (propImageResize :: RGB -> Bool)
]
, testGroup "Horizontal flip is symetric" [
testProperty "Grey" (propHorizontalFlip :: Grey -> Bool)
, testProperty "RGBA" (propHorizontalFlip :: RGBA -> Bool)
, testProperty "RGB" (propHorizontalFlip :: RGB -> Bool)
]
, testGroup "Vertical flip is symetric" [
testProperty "Grey" (propVerticalFlip :: Grey -> Bool)
, testProperty "RGBA" (propVerticalFlip :: RGBA -> Bool)
, testProperty "RGB" (propVerticalFlip :: RGB -> Bool)
]
]
-- | Tests if the conversions between RGB and RGBA images give the same images.
propRGBRGBA :: RGB -> Bool
propRGBRGBA img =
let img' = convert (convert img :: RGBADelayed) :: RGB
in img == img'
-- | Tests if the conversions between RGB and HSV images give the same images.
propRGBHSV :: RGBPixel -> Bool
propRGBHSV pix =
same pix pix'
where
pix' = convert (convert pix :: HSVPixel) :: RGBPixel
err = 9
same (RGBPixel r g b) (RGBPixel r' g' b') =
abs (r - r') + abs (g - g') + abs (b - b') <= err
-- | Tests if by increasing the size of the image by a factor of two and then
-- reducing by a factor of two give the original image.
propImageResize :: (Image i, FromFunction i, FromFunctionPixel i ~ ImagePixel i
, Interpolable (ImagePixel i), Integral (ImageChannel i)
, Eq i)
=> i -> Bool
propImageResize img =
img == resize' size (resize' (Z :. (h * 2) :. (w * 2)) img)
where
size@(Z :. h :. w) = shape img
resize' :: (Image i, FromFunction i, FromFunctionPixel i ~ ImagePixel i
, Interpolable (ImagePixel i), Integral (ImageChannel i))
=> Size -> i -> i
resize' size' = resize NearestNeighbor size'
-- | Tests if applying the horizontal flip twice gives the original image.
propHorizontalFlip :: (Image i, FromFunction i
, FromFunctionPixel i ~ ImagePixel i, Eq i) => i -> Bool
propHorizontalFlip img =
img == horizontalFlip (delayedFlip img)
where
delayedFlip :: (Image i, ImagePixel i ~ p) => i -> Delayed p
delayedFlip = horizontalFlip
-- | Tests if applying the vertical flip twice gives the original image.
propVerticalFlip :: (Image i, FromFunction i
, FromFunctionPixel i ~ ImagePixel i, Eq i) => i -> Bool
propVerticalFlip img =
img == verticalFlip (delayedFlip img)
where
delayedFlip :: (Image i, ImagePixel i ~ p) => i -> Delayed p
delayedFlip = verticalFlip