2012-11-08 8 views
8

ディスクからRGB画像をJuicyPixels-repaにロードしています。残念なことに、画像の配列表現はArray F DIM3 Word8です。ここで、内側の次元はRGBピクセルです。これは、既存のrepa画像処理アルゴリズムとは少し相容れないが、RGB画像はArray U DIM2 (Word8, Word8, Word8)である。画像ヒストグラムをrepaで計算する

私は画像のRGBヒストグラムを計算したい、私は署名して機能を探しています:

type Hist = Array U DIM1 Int 
histogram:: Array F DIM3 Word8 -> (Hist, Hist, Hist) 

どのように私は私の3Dアレイは、各colorchannelための1次元配列を取得するために折ることができますか?

編集:

主な問題は、私は(簡単にスライスで行う)各チャネルごとにDIM3からDIM2に変換することはできませんよということではありません。問題は、ソースイメージDIM2またはDIM3を繰り返し処理し、別の配列に異なるShape(Z:.256)およびエクステントに蓄積する必要があることです。 したがって、repaのfoldSを使用することはできません。ディメンションは1つ減らされますが、同じ程度です。

私もtraverseで実験しましたが、宛先イメージの範囲にわたって反復処理を行い、ソースイメージからピクセルを取得する機能を提供し、非常に非効率的なコードになり、各カラー値に対して同じピクセルをカウントします。

良い方法は、アキュムレータとしてヒストグラム型とVectorオーバーシンプルな折りたたみだろうが、残念ながら私は効率的Vectorを得ることができ、そこから何U(箱なし)またはV(ベクトル)ベースの配列を、持っていません。私はArray F(外部ポインタ)を持っています。

+3

何を試しましたか? (もし配列に 'Array U DIM2(Word8、Word8、Word8) '型があったらそれを実行できますか?もしそうなら、' Array U DIM3 Word8 - > Array U DIM2(Word8、Word8、Word8) ?) – huon

+1

明日これを見てみよう。その間に、JP-repaで役に立つと思われる画像表現の間に基本的な変換がある場合は、自由にパッチを送ってください。 –

+0

@FalcoHirschenberger大津のスレッシュホールドが完了しましたか?私はそれが欲しいですが、重複した作業を避けたいと思います。 –

答えて

7

私は数分を見つけました。以下では、4つのソリューションをカバーし、最悪のソリューション(O(n)データ変換を含む中間2つのソリューション)を簡単に作成しました。

はダムソリューション

それは明らかに開始するように合理的だと認めることができます。あなたは(未テスト/部分のコードは以下の)初期ゼロの配列から、あなたのヒストグラムを構築し、行と列を横断するData.List.foldlを使用することができます。

foldl (\(histR, histG, histB) (row,col) -> 
      let r = arr ! (Z:.row:.col:.0) 
       g = arr ! (Z:.row:.col:.1) 
       b = arr ! (Z:.row:.col:.2) 
      in (incElem r histR, incElem g histG, incElem b histB) 
     (zero,zero,zero) 
     [ (row,col) | row <- [0..nrRow-1], col <- [0..nrCol-1] ] 
... 
where (Z:.nrRow:.nrCol:._) = extent arr 

私はこれがものになるかどうか効率的にわからないんだけど、それがすることを疑いますあまりにも多くの境界チェックを行います。 unsafeIndexへの切り替えは、遅延配列hist*を仮定すると、incElemを実装することを選択するとうまくいくと思われます。

あなたはあなたが実際の要素のタプルでDIM2配列にJP-REPAのスタイルの配列を変換することができtraverseを使用

たいアレイ構築することができます:

main = do 
    let arr = R.fromFunction (Z:.a:.b:.c) (\(Z:.i:.j:.k) -> i+j-k) 
     a =4 :: Int 
     b = 4 :: Int 
     c= 4 :: Int 
     new = R.traverse arr 
         (\(Z:.r:.c:._) -> Z:.r:.c) -- the extent 
         (\l idx -> (l (idx:.0) 
            ,l (idx:.1) 
            ,l (idx :. 2))) 
    print (R.computeS new :: R.Array R.U DIM2 (Int,Int,Int)) 

あなたは身体に私を指すでしたがあなたがこのフォーマットを使用していることについて話したコードですか? JP-Repaにこのタイプの関数を含めるようにパッチするのは簡単です。あなたは箱なしのベクターを構築することができます

は、あなたが簡単な解決策は、箱なしのベクトルをオーバー折ることです言及したが、JP-REPAは、非ボックス化配列を提供していないことを嘆い

に言及しました。幸いなことに、変換は単純です:

toUnboxed :: Img a -> VU.Vector Word8 
toUnboxed = R.toUnboxed . R.computeUnboxedS . R.delay . imgData 

私たちでしたパッチREPA

REPAは、私は通常のtraverse関数を考え何を持っていないので、これは本当に唯一の問題です。 Repaのトラバースは、他の配列にインデックス関数を提供する配列構造のほうが多いです。

newTraverse :: Array r sh e -> a -> (a -> sh -> e -> a) -> a 

しかし、これは実際には不正な形式になります。だから、名前を変更し、引数の順序を変更することができます:私たちの新しい倍は2つの重要な特性を持っているか

foldAllS :: (a -> a -> a) -> a -> Array r sh a -> a 

は予告:

foldAllIdxS :: (sh -> a - > e -> a) -> a -> Array r sh e -> a 

(既存の)foldAllS操作とうまく対比されました。結果の型は要素の型と一致する必要はありませんので、ヒストグラムのタプルで始めることができます。次に、我々のバージョンのfoldはインデックスを渡します。これにより、更新するタプルのヒストグラム(もしあれば)を選択することができます。

はあなたが遅延し、ご希望のREPAアレイフォーマットを取得するには、最新のJuicyPixels-REPA

を使用することができ、またはアンボクシングベクトルを取得するために、あなただけの新たにアップロードされたJuicyPixels-REPA-0.6を使用することができます。

someImg <- readImage path :: IO (Either String (Img RGBA)) 
let img = either (error "Blah") id someImg 
    uvec = toUnboxed img 
    tupleArr = collapseColorChannel img 

ここで、最初に必要だったようにベクトルを折りたたんだり、タプル配列を直接使用することができます。

私も最初、恐ろしくナイーブ、ソリューション肉付けで醜い刺しを取った:私はこのコードのパフォーマンス指標あたり(3つのトラバーサルのあまり警戒してる

histograms :: Img a -> (Histogram, Histogram, Histogram, Histogram) 
histograms (Img arr) = 
    let (Z:.nrRow:.nrCol:._) = R.extent arr 
     zero = R.fromFunction (Z:.256) (\_ -> 0 :: Word8) 
     incElem idx x = RU.unsafeTraverse x id (\l i -> l i + if i==(Z:.fromIntegral idx) then 1 else 0) 
    in Prelude.foldl (\(hR, hG, hB, hA) (row,col) -> 
      let r = R.unsafeIndex arr (Z:.row:.col:.0) 
       g = R.unsafeIndex arr (Z:.row:.col:.1) 
       b = R.unsafeIndex arr (Z:.row:.col:.2) 
       a = R.unsafeIndex arr (Z:.row:.col:.3) 
      in (incElem r hR, incElem g hG, incElem b hB, incElem a hA)) 
      (zero,zero,zero,zero) 
      [ (row,col) | row <- [0..nrRow-1], col <- [0..nrCol-1] ] 

を...私がでなければなりません疲れている)をJP-Repaに投げ込むことができますが、それがうまくいくとわかったら私に知らせてください。

+0

あなたの素晴らしい答えに感謝します。私はあなたの提案をできるだけ早く試みます。大津自動閾値処理アルゴリズムを実装しようとしています。あなたの質問に関しては、 'repa-algorithms'のアルゴリズムは' Array U DIM2 a'の形式のマルチチャンネル画像を表し、 'rgb8OfFloat ::(Float、Float、Float) - >(Word8、Word8 、Word8) ' –

関連する問題