I am trying to perform not very complex image analysis to try and find distinct shapes and calculate some of their parameters like area and perimeter (in pixels) and I am trying to do this in Haskell (I wanted to do that to try and work with functional programming language).
The first task in line is to count the amount of spoons on the image:
I am using Friday Haskell package to work with images.
My idea was to use the Friday's edge detection and then fill all of the enclosed areas with it's fill function. The first one would require me to iterate over image's pixels until i've stumbled upon a black pixel. Than I would fill the area and continue the search in the image (which now has one of it's objects filled). I could color different objects with random colors and associate these colors with their objects to find their areas and perimeters.
Here is how this image looks after I've applied edge detection to it:
I was unable to find the way of iterating over all of the pixels though. I've found those read and readLinear functions in the following package: https://hackage.haskell.org/package/friday-0.2.2.0/docs/Vision-Image-Mutable.html#v:linearRead, but I am not sure how to use them and I was unable to deduce that from their type signature since I am very very new to Haskell.
Here is the code that does all of the image reading, grayscaling and edge detecting:
{-# LANGUAGE ScopedTypeVariables #-}
import Prelude hiding (filter)
import System.Environment (getArgs)
import Vision.Detector.Edge (canny)
import Vision.Image
import Vision.Image.Storage.DevIL (Autodetect (..), load, save)
detectEdges :: RGBA -> Grey
detectEdges img =
let grey = convert img :: Grey
-- Img blurring --
blurRadius = 2
blurred = gaussianBlur blurRadius (Nothing :: Maybe Double) grey :: Grey
-- Sobel applying --
sobelRadius = 2
lowThreshold = 256
highThreshold = 1024
in (canny sobelRadius lowThreshold highThreshold blurred) :: Grey
processImg :: RGBA -> RGBA
processImg img =
let edges = detectEdges img
-- Here goes all of the important stuff
in convert edges :: RGBA
main :: IO ()
main = do
[input, output] <- getArgs
io <- load Autodetect input
case io of
Left err -> do
putStrLn "Unable to load the image:"
print err
Right (img :: RGBA) -> do
mErr <- save Autodetect output (processImg img)
case mErr of
Nothing ->
putStrLn "Success."
Just err -> do
putStrLn "Unable to save the image:"
print err
Thank you in advance.