2010-12-06 22 views
5

私は、「写真」を撮るプログラムを作成しました。それは、すべてのピクセルについて、他のさまざまな写真から画像を挿入することを選択しました。選択された画像は、平均色が写真の元のピクセルに最も近い写真です。イメージファイルへの追加

私はまず、 'ストック'画像のすべてのピクセルのrgb値を平均し、それをCIE LABに変換することで、これを行っています。これは、人間の知覚の観点から、色の

元の「写真」画像の各ピクセルが「最も近い」ストック画像に置き換えられた画像をコンパイルしました。

これはうまく動作しますが、在庫イメージのサイズは300 x 300ピクセルで、「-Xms2048m -Xmx2048m」という仮想マシンのフラグを使用しても、555pxで540pxの画像I私はメモリ不足のエラーを取得する前に、50ピクセルに縮小されたストック画像を置き換えることができます。

私は基本的に解決策を考えようとしています。まず、元の画像の4ピクセル(2x2平方)ごとに平均して1つのピクセルに変換し、次にこのピクセルを画像に置き換えることで、画像の効果そのものを改善することができると思います。このように、小さな写真は個々のプリント。これにより、ストック画像をより大きなサイズで描画することもできます。誰かがこのような画像操作の経験がありますか?もしそうなら、あなたは素敵なイメージを作り出すためにどんなトリックを発見しましたか?

最終的に私は、メモリーエラーを減らす方法は、ディスクにイメージを繰り返し保存し、メモリから古いイメージセットを絶えず削除しながらイメージの次の行をファイルに追加することだと思います。これはどうすればできますか?通常のファイルを追加するのと似ていますか?

この最後の問題のお手伝いをさせていただきます。

おかげで、

アレックス

答えて

3

Java Advanced Imaging(JAI)APIを調べることをお勧めします。あなたはたぶんBufferedImageを使用しています。これはメモリ内のすべてを保持します。ソース画像と出力画像です。これは「即時モード」処理として知られています。イメージのサイズを変更するメソッドを呼び出すと、すぐにイメージが生成されます。その結果、在庫イメージはまだメモリに残っています。

JAIには、2つの利点があります。

  1. 遅延モード処理。
  2. タイル計算。

遅延モードとは、画像上のメソッドを呼び出すと出力画像が正しく計算されないことを意味します。代わりに、画像のサイズを変更する呼び出しは、後でサイズ変更を行うことができる小さな「演算子」オブジェクトを作成します。これにより、操作のチェーン、ツリー、パイプラインを構築できます。だから、あなたの仕事は、それぞれのストックイメージに対して、 "作物、サイズ変更、合成"のような操作のツリーを構築するでしょう。便利な点は、操作がコマンドオブジェクトであるため、コマンドを作成する間にすべてのメモリを消費していないことです。

このAPIはプルベースです。出力アクションがオペレータからピクセルを引き出すまで計算を延期します。これにより、不必要なピクセル操作を避けることによって、時間とメモリの節約に迅速に役立ちます。

たとえば、2048×2048ピクセルの出力イメージが必要で、1600×512ピクセルのソースイメージから512×512のクロップをスケールアップしたとします。明らかに、ピクセルの2/3を捨てるだけで、1600x512ソースイメージ全体を拡大することは意味がありません。代わりに、スケーリング演算子は、出力ディメンションに基づいて "関心領域"(ROI)を持ちます。スケーリング演算子は、ROIをソースイメージに投影し、それらのピクセルのみを計算します。

コマンドは最終的に評価される必要があります。これは、ほとんどの場合、最終画像の出力に関係するいくつかの状況で発生します。そのため、出力を画面に表示するようにBufferedImageを要求すると、すべてのコマンドが強制的に評価されます。同様に、出力イメージをディスクに書き込むと、評価が強制されます。

場合によっては、タイルベースのレンダリングであるJAIの2つ目の利点を維持できます。 BufferedImageはすべてのピクセルで直ちにそのすべての作業を行いますが、タイルレンダリングは一度に画像の長方形のセクションで動作します。

前の例を使用すると、2048x2048の出力イメージがタイルに分割されます。これらが256x256であるとすると、画像全体が64タイルに分割されます。 JAI演算子オブジェクトは、タイルでタイルを操作する方法を知っています。したがって、ソースイメージの512x512セクションの拡大縮小は、一度に64x64ソースピクセルで64回発生します。

タイルを一度に計算することは、タイル全体をループすることを意味し、時間がかかるようです。しかし、タイル計算を実行するときは、2つのことがうまく機能します。まず、複数のスレッドでタイルを同時に評価することができます。第2に、過渡的メモリ使用量は、即時モード計算よりもずっと低くなります。

このタイプの画像処理にJAIを使用する理由については、すべて説明があります。


ノートや警告のカップル:

  1. あなたはそれを実現することなく、タイルベースのレンダリングを倒すことができます。ワークストリームにBufferedImageがある場合は、タイルソースまたはシンクとして機能することはできません。
  2. JPEG用のJAIまたはJAIイメージI/O演算子を使用してディスクにレンダリングすると、良好な状態になります。 JDKのビルトインイメージクラスを使用しようとすると、すべてのメモリが必要になります。 (基本的には、2つのタイプのイメージ操作を混ぜないでください。イミディエイトモードと遅延モードはうまく混ざりません)
  3. ROI、タイル、および遅延モードを含むすべてのものは、プログラムにとって透過的です。 JAIクラスでAPI呼び出しを行うだけです。タイルサイズ、キャッシング、同時実行性などをより詳細に制御する必要がある場合にのみ、機械を扱うことができます。
0

あなたは「APPEND」たびに、あなたはおそらく暗黙的に古いもの(すなわち、繰り返し追加の古典的な問題と平行に置き換えるために1つの以上の画素に新しいオブジェクトを作成していますStringBuilderを使用する代わりにStringに変換する)

保存して追加するコードの部分を投稿すると、誰かがコードを効率的に記録するのに役立つでしょう。

2

ここには便利な候補があります。

2つの主要なタスクを個別のプログラムに分けることを試みてください。あなたの最初の仕事は、どこの画像が行くかを決定することであり、それは、テキストの行として表現することができますファイル名への座標から単純なマッピング、することができます。そのタスクが実行された後

0,0,image123.jpg 
0,1,image542.jpg 
..... 

(と、それはあなたのように聞こえますそれをうまく処理してください)、別のプログラムでコンパイルを処理できます。

このコンパイルはイメージに追加することで実行できますが、おそらく自分でファイルフォーマットを混乱させたくないでしょう。何らかのJava Imageオブジェクトを使用することによって、プログラミング環境で行うほうがよいでしょう。ピクセル単位でメモリに収めることができる最大のものは2GBで、sqrt(2x10^9)の最大の高さと幅になります。この数から、高さと幅のイメージ数で割ると、許されるサブイメージ全体のピクセル数が得られ、適切な場所にペイントすることができます。

関連する問題