什么Haskell表示推荐用于二维,无盒子像素arrays与数百万像素?
我想在Haskell中解决一些image processing问题。 我正在处理具有数百万像素的双色调(位图)和彩色图像。 我有很多问题:
-
我应该在
Vector.Unboxed
和UArray
之间select什么? 它们都是非装箱的数组,但是Vector
抽象似乎被广泛宣传,特别是在循环融合。Vector
总是更好吗? 如果不是, 我应该什么时候使用哪种表示? -
对于彩色图像,我将希望存储16位整数的三元组或单精度浮点数的三元组。 为此,
Vector
或UArray
更易于使用? 更高性能? -
对于双色调图像,我将只需要存储每像素1位。 是否有一个预定义的数据types,可以通过将多个像素打包成单词来帮助我,还是我自己?
-
最后,我的数组是二维的。 我想我可以处理由一个表示法所强加的额外间接方式为“数组数组”(或vector向量),但我更喜欢一个具有索引映射支持的抽象。 任何人都可以从标准库或Hackage推荐任何东西?
我是一个function程序员,并没有需要突变:-)
对于multidimensional array,在我看来,Haskell中当前的最佳选项已被修复 。
Repa提供高性能,规则,多维,形状多态平行arrays。 所有的数字数据都被解除存储。 使用Repa组合器编写的函数是自动并行的,只要您提供+ RTS – 运行程序时无论在命令行上如何。
最近,它已被用于一些image processing问题:
- 实时边缘检测
- 有效的并行模板卷积在Haskell中
我已经开始编写关于使用repa的教程,如果您已经知道Haskell数组或vector库,那么这是一个很好的开始。 关键的垫脚石是使用形状types而不是简单的索引types来解决多维索引(甚至模板)。
repa-io软件包包括对读写.bmp图像文件的支持,但需要支持更多的格式。
解决您的具体问题,这里是一个graphics,讨论:
我应该在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
像素(Double
,Float
,Word16
等) - 所有必要的function,如
map
,fold
,zipWith
,traverse
… - 支持各种色彩空间:RGB,HSI,灰度,双色,复合等
- 常见的image processingfunction:
- 二元形态
- 卷积
- 插值
- 傅里叶变换
- 直方图绘图
- 等等
- 能够将像素和图像视为常规数字。
- 通过JuicyPixels库读取和写入常见的图像格式
最重要的是,它是一个纯粹的Haskell库,所以它不依赖于任何外部程序。 它也是高度可扩展的,可以引入新的色彩空间和图像表示。
有一件事情,它不能做的是在一个Word
打包多个二进制像素,而不是每个二进制像素使用一个Word
,也许在未来…