web-dev-qa-db-ja.com

数百万ピクセルの2次元のボックス化されていないピクセル配列に推奨されるHaskell表現は何ですか?

Haskellの画像処理の問題に取り組みたい。私は、数百万ピクセルのモノクロ(ビットマップ)画像とカラー画像の両方を扱っています。私にはいくつかの質問があります:

  1. どのベースでVector.UnboxedおよびUArray?どちらもボックス化されていない配列ですが、Vector抽象化は、特にループフュージョンを中心に、広く宣伝されているようです。 Vectorは常に良いですか?そうでない場合、どの表現をいつ使用する必要がありますか?

  2. カラー画像の場合、16ビット整数のトリプルまたは単精度浮動小数点数のトリプルを保存したいと思います。この目的のために、VectorまたはUArrayのどちらが使いやすいですか?よりパフォーマンスが高い?

  3. モノクロ画像の場合、ピクセルごとに1ビットのみを保存する必要があります。 Wordに複数のピクセルをパックすることでここで役立つ定義済みのデータ型はありますか、それとも私自身ですか?

  4. 最後に、私の配列は2次元です。 「配列の配列」(またはベクトルのベクトル)として表現によって課せられた余分な間接性に対処できると思いますが、インデックスマッピングをサポートする抽象化を好むでしょう。誰でも標準ライブラリまたはHackageから何かを推薦できますか?

私は機能的なプログラマーであり、突然変異の必要はありません:-)

118
Norman Ramsey

多次元配列の場合、私の見解では、Haskellの現在の最適なオプションは- repa

Repaは、高性能で、通常の、多次元の、形状多相並列配列を提供します。すべての数値データはボックス化されずに保存されます。 Repaコンビネーターで記述された関数は、プログラムの実行時にコマンドラインで+ RTS -Nwhateverを指定すると、自動的に並列されます。

最近、いくつかの画像処理の問題に使用されています。

私は書き始めましたrepaの使用に関するチュートリアルは、Haskellを既に知っている場合に始めるのに適した場所です配列、またはベクトルライブラリ。重要な足掛かりは、多次元インデックス(さらにはステンシル)に対処するために、単純なインデックスタイプの代わりに形状タイプを使用することです。

repa-io パッケージには、.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.


Vector.UnboxedとUArrayのどちらを選択すればよいですか?

基本的な表現はほぼ同じですが、主な違いはベクターを操作するためのAPIの幅です。通常はリストに関連付けられるほぼすべての操作(融合駆動型最適化フレームワークを使用)を持ち、UArrayにはAPIがほとんどありません。

カラー画像の場合、16ビット整数のトリプルまたは単精度浮動小数点数のトリプルを保存したいと思います。

UArrayは、インデックス作成に任意のデータ型を使用できるため、多次元データのサポートが向上しています。これはVectorで可能ですが(要素タイプにUAのインスタンスを記述することにより)、Vectorの主な目標ではありません。代わりに、 Repaがステップインし、shapeインデックスのおかげで、効率的な方法で保存されたカスタムデータ型を非常に使いやすくします。

Repaでは、トリプルのショートは次のタイプになります。

Array DIM3 Word16

つまり、Word16の3D配列です。

モノクロ画像の場合、ピクセルごとに1ビットのみを保存する必要があります。

UArrayはBoolをビットとしてパックし、VectorはWord8に基づく表現を使用する代わりに、ビットパッキングを行うBoolのインスタンスを使用します。ただし、ベクトルのビットパッキング実装を書くのは簡単です 旧式の)uvectorライブラリから---(こちらは1つ です。内部では、RepaVectorsを使用するため、そのライブラリ表現の選択肢を継承すると思います。

複数のピクセルをWordにパックすることでここで私を助けることができる事前定義されたデータ型があります

既存のインスタンスを任意のライブラリ、さまざまなWordタイプに使用できますが、Data.Bitsを使用してパックデータをロールおよびアンロールするためのヘルパーをいくつか作成する必要がある場合があります。

最後に、私の配列は二次元です

UArrayとRepaは、効率的な多次元配列をサポートしています。 Repaには、そのための豊富なインターフェイスもあります。ベクター自体にはありません。


注目すべき言及:

  • hmatrix 、線形代数パッケージへの広範なバインディングを持つカスタム配列タイプ。 vectorまたはrepaタイプを使用するようにバインドする必要があります。
  • ix-shapeable 、通常の配列からより柔軟なインデックス付けを取得
  • 黒板 、2D画像を操作するためのAndy Gillのライブラリ
  • codec-image-devil 、さまざまな画像形式の読み取りとUArrayへの書き込み
89
Don Stewart

私にとって重要なHaskell配列ライブラリの機能を確認し、 比較表 (スプレッドシートのみ: 直接リンク )をコンパイルしました。だから私は答えようとします。

Vector.UnboxedとUArrayのどちらを選択すればよいですか?どちらもボックス化されていない配列ですが、ベクターの抽象化は、特にループ融合を中心に、広く宣伝されているようです。 Vectorは常に優れていますか?そうでない場合、どの表現をいつ使用する必要がありますか?

UArrayは、2次元配列または多次元配列が必要な場合、Vectorよりも優先される場合があります。しかし、Vectorには、ベクターを操作するためのより良いAPIがあります。一般に、Vectorは多次元配列のシミュレーションにはあまり適していません。

Vector.Unboxedは、並列戦略では使用できません。 UArrayも使用できないと思いますが、少なくともUArrayからボックス化されたアレイに切り替えるのは非常に簡単で、並列化がボックス化コストを上回るかどうかを確認するのは簡単です。

カラー画像の場合、16ビット整数のトリプルまたは単精度浮動小数点数のトリプルを保存したいと思います。この目的のために、VectorまたはUArrayは使いやすいですか?よりパフォーマンスが高い?

画像を表現するために配列を使用してみました(グレースケール画像のみが必要でしたが)。カラーイメージの場合、Codec-Image-DevILライブラリを使用してイメージの読み取り/書き込み(DevILライブラリへのバインド)を行い、グレースケールイメージの場合はpgmライブラリ(純粋なHaskell)を使用しました。

配列に関する私の主な問題は、ランダムアクセスストレージのみを提供することでしたが、配列アルゴリズムを構築する多くの手段を提供せず、配列ルーチンのライブラリを使用する準備ができていません(線形代数ライブラリとインターフェイスしません、畳み込み、fft、その他の変換を表現することはできません)。

既存の配列から新しい配列を作成する必要がある場合は常に、値の中間listを作成する必要があります( matrixのように)乗算 穏やかな紹介から)。多くの場合、配列構築のコストは、ランダムアクセスの高速化の利点を上回っており、一部のユースケースではリストベースの表現が高速になります。

STUArrayは私を助けてくれたかもしれませんが、 STUArrayを使用した多態性コード を書くために必要な不可解な型エラーと努力との戦いが好きではありませんでした。

したがって、配列の問題は、配列が数値計算にあまり適していないことです。 HmatrixのData.Packed.VectorとData.Packed.Matrixは、この点で優れています。これらは、ソリッドマトリックスライブラリに付属しているためです(注意:GPLライセンス)。パフォーマンス面では、行列の乗算では、hmatrixは十分に高速でした( Octaveよりもわずかに遅い )が、非常にメモリを消費します(Python/SciPyの数倍消費しました)。

マトリックス用のblasライブラリもありますが、GHC7には基づいていません。

私はまだRepaの経験があまりなく、repaコードをよく理解していません。私が見るところ、その上に書かれた行列と配列アルゴリズムを使用する準備が非常に限られていますが、少なくともライブラリを使って重要なアルゴリズムを表現することは可能です。たとえば、repa-algorithmsには 行列乗算と畳み込み のルーチンが既にあります。残念ながら、コンボリューションは現在 7×7カーネルに制限 (私には十分ではありませんが、多くの用途には十分です)。

Haskell OpenCVバインディングは試しませんでした。 OpenCVは非常に高速であるため、高速である必要がありますが、バインディングが完全で使用可能かどうかはわかりません。また、OpenCVはその性質上、非常に必須であり、破壊的な更新に満ちています。その上にニースで効率的な機能インターフェースを設計するのは難しいと思います。 OpenCVを使用する場合は、どこでもOpenCVイメージ表現を使用し、OpenCVルーチンを使用してそれらを操作する可能性があります。

モノクロ画像の場合、ピクセルごとに1ビットのみを保存する必要があります。 Wordに複数のピクセルをパックすることでここで役立つ定義済みのデータ型はありますか、それとも私自身ですか?

私の知る限り、 Boolsの非ボックス化配列 ビットベクトルのパックとアンパックを処理します。他のライブラリでのBoolsの配列の実装を見たのを覚えていますが、他では見ませんでした。

最後に、私の配列は2次元です。 「配列の配列」(またはベクトルのベクトル)として表現によって課せられた余分な間接性に対処できると思いますが、インデックスマッピングをサポートする抽象化を好むでしょう。誰でも標準ライブラリまたはHackageから何かを推薦できますか?

ベクター(および単純なリスト)を除き、他のすべての配列ライブラリーは2次元配列または行列を表すことができます。彼らは不必要な間接化を避けていると思います。

17
sastanin

しかし、これはあなたの質問に正確に答えているわけではなく、実際にはそのようなものでさえありませんが、 [〜#〜] cv [〜#〜] または CV-combinators ハッキングされたライブラリ。それらは、opencv-libraryの多くのかなり有用な画像処理およびビジョンオペレーターをバインドし、マシンビジョンの問題をより速く処理します。

誰かがrepaまたはそのような配列ライブラリをopencvで直接使用できる方法を見つけたら、かなり素晴らしいでしょう。

5
aleator

ここに、新しい Haskell Image Processing library があります。これは、問題のすべてのタスクなどを処理できます。現在、基礎となる表現に Repa および Vector パッケージを使用しており、その結果、融合、並列計算、突然変異、およびこれらのライブラリに付属する他のほとんどの利点を継承します。画像操作に自然な使いやすいインターフェイスを提供します。

  • 任意の精度(DoubleFloatWord16など。)
  • mapfoldzipWithtraverseなどのすべての必須関数...
  • さまざまな色空間のサポート:RGB、HSI、グレースケール、複調、複合など.
  • 一般的な画像処理機能:
    • バイナリ形態
    • 畳み込み
    • 補間
    • フーリエ変換
    • ヒストグラムプロット
    • 等.
  • ピクセルと画像を通常の数字として扱う機能。
  • JuicyPixels ライブラリを使用した一般的な画像形式の読み取りと書き込み

最も重要なことは、純粋なHaskellライブラリであるため、外部プログラムに依存しないことです。また、高度に拡張可能であり、新しい色空間と画像表現を導入できます。

しないことの1つは、Wordに複数のバイナリピクセルをパックすることです。代わりに、将来的にはバイナリピクセルごとにWordを使用します。

0
lehins