@@ -0,0 +1,70 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE ScopedTypeVariables #-}
4+{-# LANGUAGE StandaloneDeriving #-}
5+{-# LANGUAGE GADTs #-}
6+{-# LANGUAGE TypeOperators #-}
7+{-# LANGUAGE TypeFamilies #-}
8+{-# LANGUAGE MultiParamTypeClasses #-}
9+{-# LANGUAGE FlexibleInstances #-}
10+{-# LANGUAGE FlexibleContexts #-}
11+{-# LANGUAGE PolyKinds #-}
12+
13+module Grenade.Layers.Crop (
14+ Crop (..)
15+ ) where
16+
17+import Data.Maybe
18+import Data.Proxy
19+import Data.Singletons.TypeLits
20+import GHC.TypeLits
21+
22+import Grenade.Core.Network
23+import Grenade.Core.Shape
24+
25+import Numeric.LinearAlgebra (konst, subMatrix, diagBlock)
26+import Numeric.LinearAlgebra.Static (extract, create)
27+
28+-- | A cropping layer for a neural network.
29+data Crop :: Nat
30+ -> Nat
31+ -> Nat
32+ -> Nat -> * where
33+ Crop :: ( KnownNat cropLeft
34+ , KnownNat cropTop
35+ , KnownNat cropRight
36+ , KnownNat cropBottom
37+ ) => Crop cropLeft cropTop cropRight cropBottom
38+
39+instance Show (Crop cropLeft cropTop cropRight cropBottom) where
40+ show Crop = "Crop"
41+
42+-- | A two dimentional image can be cropped.
43+instance ( Monad m
44+ , KnownNat cropLeft
45+ , KnownNat cropTop
46+ , KnownNat cropRight
47+ , KnownNat cropBottom
48+ , KnownNat inputRows
49+ , KnownNat inputColumns
50+ , KnownNat outputRows
51+ , KnownNat outputColumns
52+ , (inputRows - cropTop - cropBottom) ~ outputRows
53+ , (inputColumns - cropLeft - cropRight) ~ outputColumns
54+ ) => Layer m (Crop cropLeft cropTop cropRight cropBottom) ('D2 inputRows inputColumns) ('D2 outputRows outputColumns) where
55+ runForwards Crop (S2D' input) =
56+ let cropl = fromIntegral $ natVal (Proxy :: Proxy cropLeft)
57+ cropt = fromIntegral $ natVal (Proxy :: Proxy cropTop)
58+ nrows = fromIntegral $ natVal (Proxy :: Proxy outputRows)
59+ ncols = fromIntegral $ natVal (Proxy :: Proxy outputColumns)
60+ m = extract input
61+ r = subMatrix (cropt, cropl) (nrows, ncols) m
62+ in return . S2D' . fromJust . create $ r
63+ runBackards _ crop _ (S2D' dEdy) =
64+ let cropl = fromIntegral $ natVal (Proxy :: Proxy cropLeft)
65+ cropt = fromIntegral $ natVal (Proxy :: Proxy cropTop)
66+ cropr = fromIntegral $ natVal (Proxy :: Proxy cropRight)
67+ cropb = fromIntegral $ natVal (Proxy :: Proxy cropBottom)
68+ eo = extract dEdy
69+ vs = diagBlock [konst 0 (cropt,cropl), eo, konst 0 (cropb,cropr)]
70+ in return (crop, S2D' . fromJust . create $ vs)