module Graphics.Image.Processing.Filter
(
Filter
, applyFilter
, Direction(..)
, gaussianLowPass
, gaussianBlur
, sobelFilter
, sobelOperator
, prewittFilter
, prewittOperator
) where
import Graphics.Image.Interface as I
import Graphics.Image.Processing.Convolution
import Graphics.Image.ColorSpace (X)
data Filter arr cs e = Filter
{ applyFilter :: Image arr cs e -> Image arr cs e
}
data Direction
= Vertical
| Horizontal
gaussianLowPass :: (Array arr cs e, Array arr X e, Floating e, Fractional e) =>
Int
-> e
-> Border (Pixel cs e)
-> Filter arr cs e
gaussianLowPass !r !sigma border =
Filter (correlate border gV' . correlate border gV)
where
!gV = compute $ (gauss / scalar weight)
!gV' = compute $ transpose gV
!gauss = makeImage (1, n) getPx
!weight = I.fold (+) 0 gauss
!n = 2 * r + 1
!sigma2sq = 2 * sigma ^ (2 :: Int)
getPx (_, j) = promote $ exp (fromIntegral (((j r) ^ (2 :: Int))) / sigma2sq)
gaussianBlur :: (Array arr cs e, Array arr X e, Floating e, RealFrac e) =>
e
-> Filter arr cs e
gaussianBlur !sigma = gaussianLowPass (ceiling (2*sigma)) sigma Edge
sobelFilter :: (Array arr cs e, Array arr X e) =>
Direction -> Border (Pixel cs e) -> Filter arr cs e
sobelFilter dir !border =
Filter (correlate border kernel)
where
!kernel =
case dir of
Vertical -> fromLists $ [ [ 1, 2, 1 ]
, [ 0, 0, 0 ]
, [ 1, 2, 1 ] ]
Horizontal -> fromLists $ [ [ 1, 0, 1 ]
, [ 2, 0, 1 ]
, [ 1, 0, 1 ] ]
sobelOperator :: (Array arr cs e, Array arr X e, Floating e) => Image arr cs e -> Image arr cs e
sobelOperator !img = sqrt (sobelX ^ (2 :: Int) + sobelY ^ (2 :: Int))
where !sobelX = applyFilter (sobelFilter Horizontal Edge) img
!sobelY = applyFilter (sobelFilter Vertical Edge) img
prewittFilter :: (Array arr cs e, Array arr X e) =>
Direction -> Border (Pixel cs e) -> Filter arr cs e
prewittFilter dir !border =
Filter (convolveCols border cV . convolveRows border rV)
where
!(rV, cV) =
case dir of
Vertical -> ([1, 1, 1], [1, 0, 1])
Horizontal -> ([1, 0, 1], [1, 1, 1])
prewittOperator :: (Array arr cs e, Array arr X e, Floating e) => Image arr cs e -> Image arr cs e
prewittOperator !img = sqrt (prewittX ^ (2 :: Int) + prewittY ^ (2 :: Int))
where !prewittX = applyFilter (prewittFilter Horizontal Edge) img
!prewittY = applyFilter (prewittFilter Vertical Edge) img