使用Haskell Repa数组库进行彩色图像文件IO

5
我正在通过尝试大量的编程示例来探索Haskell repa库。我旨在使用repa实现常见的图像处理算法。

Repa示例

在repa存储库中有一些有用的代码示例。它们都对类型为Array U DIM2 aArray DIM2 FloatArray U DIM2 Double的图像进行操作。

-- three image types used below
type Image = Array U DIM2 Double
type Image = Array DIM2 Float
type Image = Array U DIM2 (Word8, Word8, Word8)

-- examples/Blur/src-repa/Main.hs
blur :: Monad m => Int -> Array U DIM2 Double -> m (Array U DIM2 Double)

-- examples/Laplace/src-repa/SolverStencil.hs
solveLaplace :: Monad m => Int -> Array U DIM2 Double -> Array U DIM2 Double -> Array U DIM2 Double -> m (Array U DIM2 Double)

-- examples/Sobel/src-repa/SolverSeparated.hs
type Image = Array DIM2 Float
gradientX_sep :: Image -> Image
gradientX1    :: Image -> Image
gradientX2    :: Image -> Image
gradientY_sep :: Image -> Image
gradientY2    :: Image -> Image

-- examples/Canny/src-repa/Main.hs
type Image a = Array U DIM2 a
toGreyScale  :: Image (Word8, Word8, Word8) -> IO (Image Float)
blurSepX     :: Image Float -> IO (Image Float)
blurSepY     :: Image Float -> IO (Image Float)
gradientX    :: Image Float -> IO (Image Float)
gradientY    :: Image Float -> IO (Image Float)
suppress     :: Float -> Float -> Image (Float, Word8) -> IO (Image Word8)
wildfire     :: Image Word8 -> Array U DIM1 Int -> IO (Image Word8)
selectStrong :: Image Word8 -> IO (Array U DIM1 Int)
gradientMagOrient :: Float -> Image Float -> Image Float -> IO (Image (Float, Word8))

图像文件IO

有两个选项可用于图像文件IO:

  1. repa-devil 包支持PNG、BMP、JPG、TIF格式。不幸的是,它们被解析为一个数组类型,与上面的repa示例不符,如repa-devil维护者在这里确认的那样。
  2. repa-io 包更接近于repa-examples中图像的数组类型参数,但仅支持BMP文件。

repa-devil(与repa-examples不兼容)

repa-examples包中的图像类型为Array F DIM3 Word8,如果是灰度图像,则为Array F DIM2 Word8。这意味着无法使用repa-devil读取要用于repa-examples示例处理的图像,因为repa-examples中的图像是二维数组,而repa-devil中的图像是三维数组。

readImage :: FilePath -> IL Image
writeImage :: FilePath -> Image -> IL ()
data Image = RGBA (Array F DIM3 Word8)
           | RGB  (Array F DIM3 Word8)
           | BGRA (Array F DIM3 Word8)
           | BGR  (Array F DIM3 Word8)
           | Grey (Array F DIM2 Word8)

repa-io(与repa-examples有一定的兼容性)

repa-examples和repa-io之间存在更紧密的联系。

readImageFromBMP :: FilePath -> IO (Either Error (Array U DIM2 (Word8,Word8, Word8)))
writeImageToBMP  :: FilePath -> Array U DIM2 (Word8, Word8, Word8) -> IO ()

这次,一个BMP图像文件正在被解析成一个二维数组,其元素类型为(Word8, Word8, Word8),可能表示R、G和B值。即使如此,repa-examples包中唯一兼容的函数是上面提到的toGreyScale。所有其他函数都操作Array U DIM2 FloatArray DIM2 FloatArray U DIM2 Double类型的值。

问题

  1. 除了 toGreyScale,repa-examples 中的所有示例都只适用于灰度图像吗?虽然从类型上看这是有道理的,但令人惊讶的是,没有针对彩色图像的 repa 示例。例如,为什么 blur 的类型不是这样的: blur :: Monad m => Int -> Array U DIM2 (Word8, Word8, Word8) -> m (Array U DIM2 (Word8, Word8, Word8))
  2. Array U DIM2 Float 中的浮点数捕获了什么值?它是在 0 到 255 之间的灰度值吗?
  3. repa-io 包中是否有添加 JPG/PNG/TIF IO 支持的工作?

Juicy Pixels 还有一个 repa 库,我相信作者刚刚完成了对过渡性 jpg 的支持。 - DiegoNolan
@DiegoNolan 谢谢。看起来这个JuicyPixels repa库采用了与repa-devil相同的类型,而不是repa-examples中使用的DIM3类型参数,即http://hackage.haskell.org/package/JuicyPixels-repa-0.7/docs/Codec-Picture-Repa.html#v:imgData。 - Rob Stewart
'blur' 示例使用 readImageFromBMP 函数,该函数返回一个三维数组,其中上标是像素位置,下标是单个通道的值。因此,如果有3个通道,则每个(x,y)对将有3个值。如果这更容易,您可以使用 readComponentsFromBMP 函数,它返回一个三元组数组,每个颜色分量一个。模糊示例简单地使用 fromIntegraltruncateWord8 转换为 Double,然后再转回去。 - user2407038
2个回答

5
  1. 没有理由。对于彩色图像,您可以将单通道模糊函数应用于每个RGB通道。
  2. 将图像表示为Array U DIM2 Float时,元素通常具有0.0 - 1.0的范围。
  3. 我认为不应该在repa-io包中加载JPG/PNG图像,因为这会引入对外部编解码器库的依赖。使用其他包(如repa-devil)来加载图像。

repa-devil包封装了外部DevIL库,因此加载的图像最终会在外部内存中--这就是Array F DIM3 Word8中的F索引的原因。DevIL库本身不知道如何在Haskell堆中构建未打包的U数组。

这些示例仅为示例,我并不打算使repa-examples成为一个完整的图像处理库。一些数组使用外部F表示,而一些使用未打包的U表示只反映了包装外部代码的标准问题。如果您想要统一的图像处理API,则需要在边界处更改图像表示(这可能会引入冗余的复制),使函数更具多态性(这会使其类型变得复杂),或者以某种方式隐藏问题(这使成本模型不明显)。无论选择哪个选项,都会有人对此提出抱怨。


2
例如,为什么模糊类型不是这样的:blur :: Monad m => Int -> Array U DIM2 (Word8, Word8, Word8) -> m (Array U DIM2 (Word8, Word8, Word8))
  1. 始终使用元组而不是简单数字是样板代码,除非您使用fixed-vector
  2. 结果代码不可重用。
  3. 您无法通过颜色通道并行计算。
请看yarr,专门设计用于RGB图像处理。例如,您可以定义blur :: (Num v) => Array Dim2 v -> Array Dim2 v(近似签名),然后将其应用于灰度图像或彩色图像。
let blurred = fromSlices $ map blur $ slices image

请参见https://github.com/leventov/yarr/blob/master/tests/blur.hs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接