diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # phash
 
+## 0.1.0.2
+
+  * Performance improvements
+  * Mean filter implemented correctly
+
 ## 0.1.0.1
 
   * Update to work with latest `par-traverse`
diff --git a/perceptual-hash.cabal b/perceptual-hash.cabal
--- a/perceptual-hash.cabal
+++ b/perceptual-hash.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.0
 name: perceptual-hash
-version: 0.1.0.1
+version: 0.1.0.2
 license: BSD3
 license-file: LICENSE
 copyright: Copyright: (c) 2019 Vanessa McHale
@@ -26,7 +26,7 @@
         Median
     default-language: Haskell2010
     other-extensions: FlexibleContexts
-    ghc-options: -Wall
+    ghc-options: -Wall -O2
     build-depends:
         base >=4.3 && <5,
         hip -any,
diff --git a/src/PerceptualHash.hs b/src/PerceptualHash.hs
--- a/src/PerceptualHash.hs
+++ b/src/PerceptualHash.hs
@@ -23,11 +23,12 @@
           n = 32
 
 idMat :: (Fractional e, Array arr X e) => Image arr X e
-idMat = makeImage (7,7) gen
-    where gen (i,j) = PixelX $ if i == j then 1/7 else 0
+idMat = makeImage (7,7)
+    (\_ -> PixelX (1/49))
 
 meanFilter :: (Fractional e, Array arr X e, Array arr cs e) => Image arr cs e -> Image arr cs e
 meanFilter = convolve Edge idMat
+{-# SCC meanFilter #-}
 
 size32 :: Array arr cs e => Image arr cs e -> Image arr cs e
 size32 = resize Bilinear Edge (32,32)
@@ -38,9 +39,11 @@
 medianImmut :: (Ord e, V.Unbox e, Fractional e) => V.Vector e -> e
 medianImmut v = runST $
     median =<< V.thaw v
+{-# SCC medianImmut #-}
 
 dct :: (Floating e, Array arr Y e) => Image arr Y e -> Image arr Y e
 dct img = dct32 |*| img |*| transpose dct32
+{-# SCC dct #-}
 
 imgHash :: Image VU Y Double -> Word64
 imgHash = asWord64 . aboveMed . V.map (\(PixelY x) -> x) . toVector . crop8 . dct . size32 . meanFilter
