2011-09-05 11 views
4

のための私のソフトウェアの一部として、私はプロジェクターがスクリーンに対して垂直でない角度で表示されている場合、あなたが得ることができる墓石/キーストーン効果を避けるために、台形補正フィルタを書くことを探しています。アルゴリズムは、ソフトウェアキーストーン補正

現在のところ、私は何かが働いていますが、それは信じられないほど遅いです(画像全体で100ms)、理想的にはもっと速く(できれば10msの範囲で)したいと思っています。ピクセルし、この新しい配列に新しい画像のRGBの内容を設定し、新しい配列に私が欲しいのピクセルをコピーすることで、画像全体のピクセル:

public BufferedImage getCorrectedImage() { 
    double width = originalImage.getWidth(null) * 0.5; 
    double increment = (originalImage.getWidth(null) - width)/originalImage.getHeight(); 

    BufferedImage ret = new BufferedImage(originalImage.getWidth(null), originalImage.getHeight(null), BufferedImage.TYPE_INT_ARGB); 

    for (int h = 0; h < originalImage.getHeight(); h++) { 
     int[] arr = new int[originalImage.getWidth()]; 
     for (int w = 0; w < originalImage.getWidth(); w++) { 
      arr[w] = originalImage.getRGB(w, h); 
     } 
     int[] newPixels = getShortLine(arr, (int) (width + 0.5)); 

     for (int w = 0; w < originalImage.getWidth(); w++) { 
      ret.setRGB(w, h, newPixels[w]); 
     } 
     width += increment; 
    } 

    return ret; 
} 

private int[] getShortLine(int[] original, int newSize) { 
    int[] newArr = new int[original.length]; 
    double scale = original.length/newSize; 
    int start = (original.length - newSize)/2; 
    int end = original.length - ((original.length - newSize)/2); 
    for (int i = start; i < end-1; i++) { 
     newArr[i] = original[(int) ((i - start) * scale)]; 
    } 
    return newArr; 
} 

は何これを行うについての最良の方法だろうか?カスタムアフィン変換は最初は私が見ようとしていましたが、私は正しい方向に私を向けるためのコード/例を見つけることができませんでした。私は上記よりも良い結果を達成する良い方法がありますか?

+4

OpenCVをご覧ください。それは*本当に*高速であり、事実上あらゆるレンズ歪みを補正する機能を持っています。ここに有望なJavaラッパーがあります:http://code.google.com/p/javacv/ – Blender

+0

@Blenderはそれに感謝します、私はそれを調べます。 JNAの魔法はありますが、可能ならばそれを避けたいと思います。その場合は – berry120

+0

、気にしないでください。私はそれをどのように手助けするのかがはっきりと分かっていませんが、OpenCVや他のライブラリのソースコードを見れば、そういったことをすばやく確認できます。 – Blender

答えて

1

既存のコードをスピードアップするためにできることがいくつかあります。注意してください、これらはあなたのコードを読みにくく、難しくします...そしてデバッグします。しかし、アルゴリズムが動作している場合、パフォーマンス向上のためにリファクタリングすることはそれほど難しくないかもしれない場合:

  • ことはあなたのアルゴリズムのいずれかのより少なくより明らかにボトルネックがあるかどうかを確認するためにprofilerを使用してみてください。
  • getCorrectedImage関数のループを使用するたびに、新しい配列を再配置します。これは時間の経過とともに増えるメモリ割り当てです。高速化するには、配列の1つ(ピクセル幅/高さをターゲットとする)を作成し、関数の存続期間全体にわたって再利用します。実際に使用されている内容を追跡するために、いくつかの変数を追加する必要があるかもしれません。
  • getShortLineメソッドをインライン展開してみてください。 JVMが実行時にインライン展開するのか、それとも実行するのかをチェックする方法があるのか​​どうかはわかりません。いずれにしても、配列の再利用がパフォーマンスを引き上げない場合は、インラインで「手動で」実行する価値があります。
  • この機能を静的にすることもできます。 originalImageメンバを変数として渡すだけです。これは、特にクラスローディングのパフォーマンスに軽微な影響を与える可能性があります。唯一の変数がイメージであり、簡単に渡すことができるので、静的変数として定義することも意味があります。他のクラスメンバーの依存関係はありません。それはユーティリティクラスのユーティリティメソッドでなければならないようです。

ImageJは完全にJavaで書かれています。

+0

提案していただきありがとうございます - 私は実際に上記の両方を試してみましたが、読みやすくするために上記のコードから除外しました。どちらも、測定可能な小さな増加をもたらしました。他のものと同じように、個々のピクセルではなく配列としてラインごとにイメージのRGBコンテンツを取得するようにしました。彼らはそれを少し速くしますが、私が探しているものの桁違いの増加のオーダーではありません。可能であればビデオフレームのようなリアルタイム処理でこれを動作させたいのが理想です。 – berry120

+0

ボトルネックを見つけるためにプロファイラを試しましたか? (私の答えにオプションとして追加) –

+0

残念ながら、明らかなボトルネックはなく、処理に費やされた時間はアルゴリズム全体に均等に分散されていました。間違いなく、単一のステートメント/ループは、処理時間の90%を取っているか、そのようなものです。 – berry120

関連する問題