对于具有数百万像素的2D 非盒装像素数组,推荐使用什么 Haskell 表示?

我想解决一些哈斯克尔的图像处理问题。我正在处理双位(位图)和彩色图像与数百万像素。我有几个问题:

  1. 我应该在 Vector.UnboxedUArray之间选择什么基础?它们都是未装箱的数组,但是 Vector抽象似乎被大肆宣传,特别是在循环融合方面。Vector总是更好吗?如果没有,我应该在什么时候使用哪种表示法?

  2. 对于彩色图像,我希望存储16位整数的三元组或单精度浮点数的三元组。为此,VectorUArray是否更容易使用?更有表现力?

  3. For bitonal images I will need to store only 1 bit per pixel. Is there a predefined datatype that can help me here by packing multiple pixels into a word, or am I on my own?

  4. 最后,我的数组是二维的。我认为我可以处理“数组的数组”(或向量的向量)这种表示所带来的额外的间接性,但是我更喜欢具有索引映射支持的抽象。有人能从标准库或 Hackage 中推荐任何东西吗?

我是一个函数式程序员,不需要变异: -)

11091 次浏览

对于多维数组,在我看来,目前哈斯克尔最好的选择是 Ref = “ http://hackage.haskell.org/package/repa”rel = “ noReferrer”> repa

Repa provides high performance, regular, multi-dimensional, shape polymorphic parallel arrays. All numeric data is stored unboxed. Functions written with the Repa combinators are automatically parallel provided you supply +RTS -Nwhatever on the command line when running the program.

最近,它被用于解决一些图像处理问题:

我已经开始编写 a tutorial on the use of repa了,如果您已经知道 Haskell 数组或者向量库,那么从 a tutorial on the use of repa开始是个不错的选择。关键的步骤是使用形状类型而不是简单的索引类型来处理多维索引(甚至模板)。

吃吧包包含对读写.bmp 图像文件的支持,但是还需要更多格式的支持。

针对你的具体问题,这里有一个图表,带有讨论:


All three of UArray, Vector, and Repa support unboxing. Vector and Repa have a rich, flexible API, but UArray does not. UArray and Repa have multi-dimensional indexing, but Vector does not. They all have support for bit-packing, although Vector and Repa have some caveats in that regard. Vector and Repa interoperate with C data and code, but UArray does not. Only Repa supports stencils.


我应该根据什么来选择向量。取消装箱和 UArray?

它们具有大致相同的基底形式,然而,主要的区别在于用于向量处理的 API 的宽度: 它们几乎拥有你通常与列表关联的所有操作(使用融合驱动的优化框架) ,而 UArray几乎没有 API。

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

UArray has better support for multi-dimensional data, as it can use arbitrary data types for indexing. While this is possible in Vector (by writing an instance of UA for your element type), it isn't the primary goal of Vector -- instead, this is where Repa steps in, making it very easy to use custom data types stored in an efficient manner, thanks to the shape indexing.

Repa中,你的三条短裤应该是这样的:

Array DIM3 Word16

也就是说,一个由 Word16组成的3D 数组。

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

UArray 将 Bool 打包为位,Vector 使用 Bool 的实例进行位打包,而不是使用基于 Word8的表示。然而,很容易从(过时的) uVector 库编写矢量的位打包实现—— 这里有一个。在底层,Repa使用 Vectors,所以我认为它继承了库表示选择。

Is there a predefined datatype that can help me here by packing multiple pixels into a word

对于不同的单词类型,可以使用任何库的现有实例,但是可能需要使用 Data 编写一些助手。滚动和展开打包数据的位。

Finally, my arrays are two-dimensional

UArray 和 Repa 支持高效的多维数组。Repa 还提供了丰富的用户界面。而 Vector 本身却没有。


值得注意的是:

  • HMatrix ,这是一个定制的数组类型,具有到线性代数包的广泛绑定。应该绑定到使用 vectorrepa类型。
  • Ix-shapeable ,从常规数组获得更灵活的索引
  • 黑板 ,Andy Gill 的图书馆,用于处理2D 图像
  • codec-image-devil, read and write various image formats to UArray

Although, this doesn't exactly answer your question and isn't really even haskell as such, I would recommend taking a look at 简历 or 简历编码器 libraries at hackage. They bind the many rather useful image processing and vision operators from the opencv-library and make working with machine vision problems much faster.

It would be rather great if someone figures out how repa or some such array library could be directly used with opencv.

有一次,我回顾了 Haskell 数组库的特性,并编译了 比较表(只有电子表格: 直接联系)。所以我会尽量回答。

我应该根据什么来选择 Vector。未装箱和 UArray? ?它们都是未装箱的数组,但 Vector 抽象似乎被大肆宣传,特别是在循环融合方面。Vector 总是更好吗?如果没有,我应该在什么时候使用哪种表示法?

如果需要二维或多维数组,UArray 可能优于 Vector。但 Vector 有更好的操作矢量的 API。一般来说,Vector 不太适合模拟多维数组。

Vector.Unboxed cannot be used with parallel strategies. I suspect that UArray cannot be used neither, but at least it is very easy to switch from UArray to boxed Array and see if parallelization benefits outweight the boxing costs.

对于彩色图像,我希望存储16位整数的三元组或单精度浮点数的三元组。为此,Vector 或 UArray 是否更容易使用?更有表现力?

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

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

几乎每次必须从现有的数组构建一个新的 Array 时,都必须构建一个值的中间 名单(类似于 Gentle Guide 中的 矩阵乘法)。数组构造的成本往往超过了更快的随机访问的好处,以至于在我的一些用例中,基于列表的表示更快。

STUArray 本来可以帮助我,但我不喜欢与神秘的类型错误作斗争,也不喜欢为编写 使用 STUArray 的多态代码而付出必要的努力。

因此,Array 的问题在于它们不太适合进行数值计算。黑客帝国的数据。打包好了。矢量与数据。打包好了。矩阵在这方面更好,因为它们附带了一个坚实的矩阵库(注意: GPL 许可证)。就性能而言,从矩阵乘法来看,hMatrix 足够快(只比八度慢一点) ,但非常占用内存(消耗的内存是 Python/SciPy 的数倍)。

还有一个用于矩阵的 blas 库,但是它不建立在 GHC7之上。

我对 Repa 还没有太多的经验,而且我也不是很了解 Repa 代码。在我看来,它只能在非常有限的范围内使用写在它上面的矩阵和数组算法,但是至少它可以通过库的方式来表示重要的算法。例如,repa 算法中已经有了 矩阵乘法和卷积的例程。不幸的是,卷积现在似乎是 最多7 × 7粒(这对我来说还不够,但应该足够用于许多用途)。

我没有试过 Haskell OpenCV 绑定。它们应该很快,因为 OpenCV 确实很快,但我不确定绑定是否完整,是否足够好以便使用。此外,OpenCV 本质上是非常必要的,充满了破坏性的更新。我想在它的基础上设计一个漂亮而高效的功能界面是很困难的。如果一个人采用 OpenCV 的方式,他可能会在任何地方使用 OpenCV 图像表示,并使用 OpenCV 例程来操纵它们。

对于位图像,我将只需要存储每像素1位。有没有一个预定义的数据类型,可以帮助我在这里打包多个像素到一个字,或我自己吗?

据我所知,未装箱的 Bools 数组负责打包和解包位向量。我记得曾在其他库中研究过 Bools 数组的实现,但在其他库中没有看到这种情况。

最后,我的数组是二维的。我认为我可以处理“数组的数组”(或向量的向量)这种表示所带来的额外的间接性,但是我更喜欢具有索引映射支持的抽象。有人能从标准库或 Hackage 中推荐任何东西吗?

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

这里是一个新的 图像处理库,可以处理所有的问题和更多的任务。目前,它使用 RepaVector包作为底层表示,因此它们继承了融合、并行计算、变异和这些库带来的大部分其他优点。它提供了一个易于使用的界面,这是自然的图像操作:

  • 具有任意精度的二维索引和未装箱像素(DoubleFloatWord16等)
  • 所有基本功能,如 mapfoldzipWithtraverse..。
  • 支持各种颜色空间: RGB,HSI,灰度,双色调,复杂等。
  • common image processing functionality:
    • 二元形态学
    • 卷积
    • 插值
    • 傅里叶变换
    • Histogram plotting
    • 等等。
  • 能够将像素和图像作为常规数字处理。
  • 通过 多汁像素库读写常用的图像格式

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

它没有做的一件事是在 Word中打包多个二进制像素,而是使用每个二进制像素的 Word,也许在将来..。