什么Haskell表示推荐用于二维,无盒子像素arrays与数百万像素?

我想在Haskell中解决一些image processing问题。 我正在处理具有数百万像素的双色调(位图)和彩色图像。 我有很多问题:

  1. 我应该在Vector.UnboxedUArray之间select什么? 它们都是非装箱的数组,但是Vector抽象似乎被广泛宣传,特别是在循环融合。 Vector总是更好吗? 如果不是, 我应该什么时候使用哪种表示?

  2. 对于彩色图像,我将希望存储16位整数的三元组或单精度浮点数的三元组。 为此, VectorUArray更易于使用? 更高性能?

  3. 对于双色调图像,我将只需要存储每像素1位。 是否有一个预定义的数据types,可以通过将多个像素打包成单词来帮助我,还是我自己?

  4. 最后,我的数组是二维的。 我想我可以处理由一个表示法所强加的额外间接方式为“数组数组”(或vector向量),但我更喜欢一个具有索引映射支持的抽象。 任何人都可以从标准库或Hackage推荐任何东西?

我是一个function程序员,并没有需要突变:-)

对于multidimensional array,在我看来,Haskell中当前的最佳选项已被修复

Repa提供高性能,规则,多维,形状多态平行arrays。 所有的数字数据都被解除存储。 使用Repa组合器编写的函数是自动并行的,只要您提供+ RTS – 运行程序时无论在命令行上如何。

最近,它已被用于一些image processing问题:

  • 实时边缘检测
  • 有效的并行模板卷积在Haskell中

我已经开始编写关于使用repa的教程,如果您已经知道Haskell数组或vector库,那么这是一个很好的开始。 关键的垫脚石是使用形状types而不是简单的索引types来解决多维索引(甚至模板)。

repa-io软件包包括对读写.bmp图像文件的支持,但需要支持更多的格式。

解决您的具体问题,这里是一个graphics,讨论:


所有UArray,Vector和Repa三个都支持拆箱。 Vector和Repa有一个丰富,灵活的API,但UArray不。 UArray和Repa有多维索引,但Vector不。他们都支持比特包装,虽然Vector和Repa在这方面有一些警告。 Vector和Repa与C数据和代码交互操作,但是UArray不能。只有维修支持模具。


我应该在Vector.Unboxed和UArray之间select什么?

它们具有大致相同的底层表示,但是,主要区别在于处理vector的API的广度:几乎所有通常与列表关联的操作(使用融合驱动的优化框架),而UArray具有几乎没有API。

对于彩色图像,我将希望存储16位整数的三元组或单精度浮点数的三元组。

UArray对多维数据有更好的支持,因为它可以使用任意数据types进行索引。 尽pipe在Vector这是可能的(通过为您的元素types编写UA实例),但这不是Vector的主要目标 – 相反,这是Repa步骤的地方,使得使用存储在一个有效的方式,归功于形状索引。

Repa ,你的三倍的短裤将有这样的types:

 Array DIM3 Word16 

那就是一个Word16的3D数组。

对于双色调图像,我将只需要存储每像素1位。

UArrays将Bools作为位,Vector使用Bool实例进行位打包,而不是使用基于Word8的表示。 无论如何,很容易为vector写一个比特封装的实现 – 这是一个来自(过时的)uvector库。 在引擎盖下, Repa使用Vectors ,所以我认为它inheritance了库表示的select。

有没有一个预定义的数据types,可以通过将多个像素打包成单词来帮助我

您可以将任何库的现有实例用于不同的单词types,但是您可能需要使用Data.Bits编写一些帮助程序来滚动和展开打包的数据。

最后,我的数组是二维的

UArray和Repa支持高效的multidimensional array。 维也有一个丰富的接口这样做。 vector本身不。


值得注意的是:

  • hmatrix ,一种自定义数组types,具有对线性代数包的广泛绑定。 应该绑定使用vector或重新types。
  • ix-shapeable ,从常规数组中获得更灵活的索引
  • 黑板 ,安迪·吉尔的图书馆操纵二维图像
  • 编解码器图像魔鬼 ,读取和写入各种图像格式到UArray

一旦我回顾了Haskellarrays库对我很重要的function,并编译了一个比较表 (仅电子表格: 直接链接 )。 所以我会试着回答。

我应该在Vector.Unboxed和UArray之间select什么? 它们都是非装箱的数组,但是Vector抽象似乎被大量宣传,特别是在循环融合方面。 Vector总是更好吗? 如果不是,我应该什么时候使用哪种表示?

如果需要二维或multidimensional array,则UArray可能优于Vector。 但是Vector有更好的API来操纵vector。 一般来说,Vector不适合模拟multidimensional array。

Vector.Unboxed不能用于并行策略。 我怀疑,UArray不能使用,但至less是从UArray切换到盒装arrays是非常容易的,看看并行化是否有利于超出拳击成本。

对于彩色图像,我将希望存储16位整数的三元组或单精度浮点数的三元组。 为此,Vector或UArray更易于使用? 更高性能?

我尝试使用数组来表示图像(尽pipe我只需要灰度图像)。 对于彩色图像,我使用Codec-Image-DevIL库读取/写入图像(绑定到DevIL库),对于灰度图像我使用pgm库(纯Haskell)。

我对Array的主要问题是它只提供随机存取存储,但是它不提供构buildArrayalgorithm的许多方法,也没有准备好使用数组例程库(不与线性代数库交互,不允许expression卷积,fft和其他变换)。

几乎每一次都要从现有的数组中创build一个新的数组,必须构造一个中间数值列表 (就像从柔和介绍中的matrix乘法一样)。 数组构造的成本往往超过了更快速的随机访问的好处,在某些用例中基于列表的表示速度更快。

STUArray本可以帮助我,但我不喜欢与隐藏types的错误和努力编写STUArray编写多态代码的努力 。

所以数组的问题在于它们不适合数值计算。 Hmatrix的Data.Packed.Vector和Data.Packed.Matrix在这方面比较好,因为它们带有一个坚实的matrix库(注意:GPL许可证)。 在matrix乘法的性能方面,hmatrix速度足够快( 只比Octave慢一点 ),但是非常消耗内存(比Python / SciPy多耗费几倍)。

还有用于matrix的blas库,但不是基于GHC7。

我还没有很多的经验,我不明白代码。 从我所看到的,已经准备好使用的matrix和数组algorithm的范围非常有限,但是至less可以通过库的方式expression重要的algorithm。 例如,已经有matrix乘法和重新algorithm中的卷积的例程。 不幸的是,似乎卷积现在仅限于7×7内核 (这对我来说是不够的,但应该足够用于很多用途)。

我没有尝试Haskell OpenCV绑定。 他们应该是快速的,因为OpenCV真的很快,但我不确定绑定是否完整,足够好用。 另外,OpenCV本质上是非常迫切的,充满了破坏性的更新。 我想很难devise一个很好的高效的function界面。 如果采用OpenCV的方式,他可能会在任何地方使用OpenCV图像表示,并使用OpenCV例程来操作它们。

对于双色调图像,我将只需要存储每像素1位。 是否有一个预定义的数据types,可以通过将多个像素打包成单词来帮助我,还是我自己?

据我所知, Bbox的Unboxed数组负责打包和解包位向量。 我记得在其他库中查看Bools数组的实现,并没有在其他地方看到这个。

最后,我的数组是二维的。 我想我可以处理由一个表示法所强加的额外间接方式为“数组数组”(或vector向量),但我更喜欢一个具有索引映射支持的抽象。 任何人都可以从标准库或Hackage推荐任何东西?

除Vector(和简单列表)之外,所有其他数组库都能够表示二维数组或matrix。 我想他们避免不必要的间接。

虽然,这并不能完全回答你的问题,甚至不是真正的Haskell,我build议看看简历或简历组合库的黑客行为。 他们绑定了许多来自opencv库的相当有用的image processing和视觉操作者,并使得机器视觉问题的工作速度更快。

如果有人指出如何直接使用opencv来修复或某些这样的数组库,那将是相当不错的。

这是一个新的Haskellimage processing库 ,可以处理所有有问题的任务等等。 目前,它使用Repa和Vector软件包进行底层表示,从而inheritance了这些库所带来的融合,并行计算,变异以及大多数其他好东西。 它提供了一个易于使用的image processing自然界面:

  • 2D索引和任意精度的无Word16像素( DoubleFloatWord16等)
  • 所有必要的function,如mapfoldzipWithtraverse
  • 支持各种色彩空间:RGB,HSI,灰度,双色,复合等
  • 常见的image processingfunction:
    • 二元形态
    • 卷积
    • 插值
    • 傅里叶变换
    • 直方图绘图
    • 等等
  • 能够将像素和图像视为常规数字。
  • 通过JuicyPixels库读取和写入常见的图像格式

最重要的是,它是一个纯粹的Haskell库,所以它不依赖于任何外部程序。 它也是高度可扩展的,可以引入新的色彩空间和图像表示。

有一件事情,它不能做的是在一个Word打包多个二进制像素,而不是每个二进制像素使用一个Word ,也许在未来…