2011-07-18 10 views
2

私は、画像内のすべてのピクセルにわたって反復するアルゴリズムを実装しています(各OpenCVでは、近傍のピクセルとのブロックマッチングを計算して隣接ピクセルの類似性を評価しています)。非常に深いループを持つ「素朴な」実装は非常に遅いので、パフォーマンスをどのように改善しようとしているのだろうかと思っていました。以下は私の現在のコードの抜粋です。ピクセル処理のためのループの最適化

for(nCh=1;nCh<=channels;nCh++) { // Loop over three channels 

    for(i=0;i<h;i++) { // "vertical" loop 

    for(j=0;j<w;j++) { // "horizontal" loop 

     for (si=-sw_height; si<sw_height; si++){ // vertical search window loop 

     for (sj=-sw_width; sj<sw_width; sj++){ // horizontal search window loop 

      dist = 0; 

      for (blki=0; blki<blk_height; blki++){ // block match loop 

       for (blkj=0; blkj<blk_width; blkj++){ // block match loop 

       current_pxl = data[(i+blki)*step+(j+blkj)*channels+nCh]; 

       search_pxl = data[(i+blki+si)*step+(j+blkj+sj)*channels+nCh]; 

       dist += pow((current_pxl - search_pxl),2); 

       } 

      } 

      // ... further processing 

     } 

     } 

    } 

    } 

} 
+1

は、非局所的な手段のノイズ除去や自己相似性の特徴をやってyour'reように見える:-)もう少し空白が役立つかもしれませんか?そうであれば、最良の最適化を行っても、小さな画像、ブロックサイズ、および検索ウィンドウであっても、リアルタイムでは十分ではありません。 NVidia CUDA SDKには、カードで100 fps以上のNLMノイズ除去のサンプルアプリケーションが付属しています。 – jeff7

+0

ありがとうJeff、これは実際に私が実装しているアルゴリズムのタイプです。私はGPUに関するあなたの提案が好きです。実際には汎用GPUプログラミングを手に入れたいと思っていますが、私の現在のグラフィックスカードは、「ちょうど」の16ストリームプロセッサを搭載したNVIDIA Quadro fx570はGPUのように比較的遅いです。私は大規模な画像(6メガピクセルの画像)のための合理的な処理時間(<2分)で非リアルタイムソリューションに満足しています。 GPU処理に関するコメントがありましたら、お聞きしたいと思います。 – trican

+0

私が現在目指しているもう1つの選択肢は、最も内側の2つのループを避けるためにブロックの類似性を事前計算することです(差の平方和の代わりに絶対差メトリックの合計に対して)。顔検出アルゴリズムで積分画像を使用するのとほぼ同じです。 – trican

答えて

5

あなたは最も内側のループにpowと呼んでいます。しないでください。

また、そこでは多くのインデックス計算が行われています。 私はあなたが内側のループからそれを抜け出すことができると確信しています。

あなたはそれはので、あなたの内側のループがより次のようになり得ることができる必要があります:

  for (blkj = 0; blkj < blk_width; blkj++, pc += channels, ps += channels){ 
      int diff = (*pc - *ps); 
      dist += (diff * diff); 
      } 

そして、あなたもそれを少しアンロールしたい場合があります。ところで

+0

特に、pow(x、2)を(x * x)に置き換えてください。コンパイラがあなたのためにこの置き換えを行うと思うでしょうが、私がここに入らない理由はしばしばありません。 –

+0

提案のおかげでマイク、私はそれらを試してみましょう。 @Mark thats非常に興味深い、私は交換も起こると仮定していただろう。私はgccを使用しています4.5.2 – trican

+0

@trican:これは 'pow'が完全に異なるものに置き換えられていないことを知る方法がありません。私はコンパイラがレジスタなどをうまく利用しているのが好きですが、自分でできることをするために決して依存しません。 –

関連する問題