Haskell HIP : Apply Filter to an Image

210 views Asked by At

I'm trying to add a filter to an image using the Haskell Image Processing package HIP, I was able to read the image using the ByteString Package and convert the image to type Image VS YCbCr Word8 using HIP. Now, how do I convert from Image VS YCbCr Word8 to Border (Pixel cs e) or Pixel cs e? I'm still learning Haskell so please keep it simple. see code below :

addFilterJpg :: FilePath -> IO ()
addFilterJpg fc = do
    case validPath fc of 
        Left err -> putStrLn err
        Right img -> do
            case readImage img of
                Left err -> putStrLn err
                Right img -> do
                  -- convert img::(Image VS YCbCr Word8) to Border (Pixel cs e)
                  -- apply filter
                  -- save image
                  putStrLn "Convolution Filter"
1

There are 1 answers

0
lehins On BEST ANSWER

There are a couple of issues with your question:

  • Firstly you are missing a declaration of validPath function. I'll assume it does some file path validation, so I'll just ignore it in the answer.
  • readImage is an IO action, as such you can't just pattern match on Either, you need to execute it first.
  • You also need to output the result image somewhere, so you need out path as well

Some more image specific remarks:

  • Applying convolution to YCbCr encoded image doesn't really make sense, so you either need to convert to RGB or grayscale Y. I'll assume you want color so we'll use RGB
  • You didn't specify which filter you want, so'll just go with gaussian blur
applyFilterJpg :: FilePath -> FilePath -> IO ()
applyFilterJpg fcin fcout = do
  eImg <- readImageExact JPG fcin
  case eImg of
    Left err -> putStrLn err
    Right img -> do
      let imgRGB :: Image VS RGB Double
          imgRGB = convert (img :: Image VS YCbCr Word8)
          gaussianBlurKernel :: Image VS X Double
          gaussianBlurKernel = fromLists $ [ [ 1/16, 1/8, 1/16 ]
                                           , [  1/8, 1/4,  1/8 ]
                                           , [ 1/16, 1/8, 1/16 ] ]
          convRGB = convolve Edge gaussianBlurKernel imgRGB
      writeImage fcout convRGB

This is what we get when we run it:

enter image description here

That being said, there are already functions built in that will simplify this whole process for you:

  • Use import functions that already do the conversion for you, so you don't need to mess with manual conversion of color spaces.
  • Instead of supplying kernel for filter manually, check see if there is already one available in HIP that you need.
addFilterJpg' :: FilePath -> FilePath -> IO ()
addFilterJpg' fcin fcout = do
  imgRGB <- readImageRGB VS fcin
  let convRGB = applyFilter (gaussianBlur 1) imgRGB
  writeImage fcout convRGB

This is the outcome of the above function:

enter image description here