packages feed

friday-0.2.1.2: test/Test/Vision/Histogram.hs

{-# LANGUAGE BangPatterns
           , CPP
           , FlexibleContexts
           , FlexibleInstances
           , UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Test.Vision.Histogram (tests) where

#if __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<$>))
#endif

import Data.Int
import qualified Data.Vector.Storable as V
import Test.Framework (Test)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck (Arbitrary (..), Positive, getPositive)

import Vision.Histogram
import Vision.Image (Grey)
import qualified Vision.Image as I
import Vision.Primitive (Z (..), (:.) (..), DIM1, ix1, ix3)
import Test.Vision.Image ()

instance (Arbitrary (Positive p), Bounded p, Integral p, V.Storable p)
    => Arbitrary (Histogram DIM1 p) where
    arbitrary = do
        let !maxVal = maxBound `quot` 256 -- Sum musn't overflow.
        vec <- V.replicateM 256 (getPositive <$> arbitrary)
        return $ Histogram (Z :. 256) $ V.map (`rem` maxVal) vec

tests :: [Test]
tests = [
      testProperty "Sum of bins equals the number of pixels" propCalcHist

    , testProperty "The reduction of a 2D histogram gives the linear one."
                   propReduceHist

    , testProperty "Resizing an histogram equals computing the smallest one."
                   propResizeHist

    , testProperty "Cumulative histogram last bin equals original's sum"
                   propCumulatHist

    , testProperty "Sum of an normalized histogram equals its size"
                   propNormalizedHist

    , testProperty "Comparing the same histogram returns a perfect correlation"
                   propCorrelation
    , testProperty "Comparing the same histogram returns a 0 chi-square value"
                   propChiSquare
    , testProperty
        "The intersection of an histogram with itself is the sum of its values."
        propIntersec
    , testProperty "Comparing the same histogram returns a 0 EMD value"
                   propEMD
    ]

-- | The sum of the values of the histogram is equal to the number of pixels of
-- the image.
propCalcHist :: Grey -> Bool
propCalcHist img =
    let Z :. h :. w     = I.shape img
        Histogram _ vec = histogram Nothing img
    in V.sum vec == w * h

-- | Checks the identity @histogram == reduce . histogram2D@.
propReduceHist :: Grey -> Bool
propReduceHist img =
    let hist1 = histogram Nothing img :: Histogram DIM1 Int32
        hist2 = reduce (histogram2D (ix3 256 3 3) img)
    in hist1 == hist2

-- | Checks the resizing of an histogram equals the direct computation of the
-- smallest one.
propResizeHist :: Grey -> Bool
propResizeHist img =
    let hist1 = histogram (Just (ix1 128)) img :: Histogram DIM1 Int32
        hist2 = resize (ix1 128) (histogram (Just (ix1 256)) img)
    in hist1 == hist2

-- | Checks if the last bin of the cumulative histogram equals the sum of the
-- values of the original histogram.
propCumulatHist :: Histogram DIM1 Int32 -> Bool
propCumulatHist hist@(Histogram _ vec) =
    let Histogram _ vec' = cumulative hist
    in V.sum vec == vec' V.! 255

-- | Checks that the sums of an equalized histogram equals the desired value.
propNormalizedHist :: Double -> Histogram DIM1 Int32 -> Bool
propNormalizedHist val hist =
    let Histogram _ vec = normalize val hist
    in round (V.sum vec) == (round val :: Integer)

-- | Checks that the comparison of two identical histograms gives the
-- correlation value 1.
propCorrelation :: Histogram DIM1 Int32 -> Bool
propCorrelation hist = round (compareCorrel hist hist :: Double) == (1 :: Int)

-- | Checks that the comparison of two identical histograms gives the zero
-- Chi-square value.
propChiSquare :: Histogram DIM1 Int32 -> Bool
propChiSquare hist = round (compareChi hist hist :: Double) == (0 :: Int)

-- | Checks that the comparison of two identical histograms gives the sum of the
-- values of the histogram.
propIntersec :: Histogram DIM1 Int32 -> Bool
propIntersec hist@(Histogram _ vec) = compareIntersect hist hist == V.sum vec

-- | Checks that the comparison of two identical histograms gives a zero
-- EMD value.
propEMD :: Histogram DIM1 Int32 -> Bool
propEMD hist = compareEMD hist hist == 0