2016-05-01 34 views
2

同じ解像度の2つの画像の対応するピクセルにどのように関数を適用するのですか? Photoshopのように、あるレイヤーを別のレイヤーで覆う場合はそうです。 2つ以上の画像はどうですか?vips(ruby-vips8)を使用して複数の画像を結合する

もし私がWolfram Mathematicaだったら、それらの画像のリストを取り上げ、それぞれの "画素"がN個の画素の配列になる単一の "画像"を得るためにそれらを転置します - そこにMean[]関数を適用します。

しかし、私はどのようにそれをvipで行いますか?非常に多くの方法がありますが、hereしかありません。何を意味するのか、いくつかの最小限の説明があります。したがって、たとえば:

images = Dir["shots/*"].map{ |i| Vips::Image.new_from_file(i) } 
ims = images.map(&:bandmean) 
(ims.inject(:+)/ims.size).write_to_file "temp.png" 

私は「平均画像を計算する」ことを意味したかったが、ここで何をしたのか分からなかった。

+0

達成しようとしていることを説明できますか?一連の画像を読み込み、各ピクセルの平均値を見つけようとしていますか? – user894763

+0

@ user894763特にあります。それらを同じ物体の騒々しい写真として想像し、それをきれいにしたい。しかし、一般的には、my_custom_function(pixel1、pixel2、...、pixelN)を適用する方法を知りたいと思います。 – Nakilon

答えて

1

ruby​​-vips8にはcomplete set of operator overloadsが付いているので、画像で算術演算を行うことができます。自動共通部分式の消去も行いますので、順序やグループ分けについてあまり気を付けすぎる必要はありません。方程式を書くだけで十分です。あなたの例では

require 'vips8' 

images = Dir["shots/*"].map{ |i| Vips::Image.new_from_file(i) } 
sum = images.reduce (:+) 
avg = sum/images.length 
avg.write_to_file "out.tif" 

+ - * /定数とは、常にフロート画像を作るので、あなたが保存する前UCHARするには、下の結果をキャストすることがありますか」(または多分USHORT?)巨大な出力tiffを持つでしょう。

avg = sum/images.length 
avg.cast("uchar").write_to_file "out.tif" 

デフォルトでは、new_from_fileは画像をランダムアクセス用に開きます。ソースイメージがJPGまたはPNGの場合、処理が開始される前に、それらを完全にメモリ(または非常に大きい場合はディスクtemp)に圧縮解除する必要があります。

この場合、入力画像を上から下にスキャンするだけで、結果を書き込むことができるので、システムから画像をストリーミングすることができます。

images = Dir["shots/*"].map { |i| Vips::Image.new_from_file(i, :access => "sequential") } 

だけ画像ピクセルを順番に使用され、そしてあなたは、メモリとCPUの使用での素敵な低下を見る必要があることをほのめかしする:ことnew_from_fileを変更します。

PNGはひどく遅いフォーマットです。できるだけtiffを使用します。

bandrankこれは一連の画像に対してメジアンフィルタのようなものです。画像の配列を与え、各ピクセル位置で画像をピクセル値でソートし、N番目の画像を選択します。これは一時的なアーティファクトを除去する非常に効果的な方法です。

さらに複雑な関数を計算するには、condition.ifthenelse(then, else)を使用できます。たとえば、ローカルの平均に等しい彼らの局所平均を上回るすべてのピクセルを設定するには、あなたが書くことができる:

(image > image.gaussblur(1)).ifthenelse(image.gaussblur(1), image) 

あなたはVIPは上記のプログラムを実行する方法好奇心かもしれません。コード:バックUCHARにそれをノックする分割を行うために、配列を合計するvips_add()一連のvips_linear()、最後にvips_cast()

(images.reduce(:+)/images.length).cast("uchar") 

は、画像処理動作のパイプラインを構築します。

write_to_fileに電話すると、マシンの各コアにパイプラインのコピーが与えられ、デコンプレッサーから到着するとソースイメージからタイルを処理するようにキューに入れられます。出力タイルの行が完成するたびに、バックグラウンドスレッドは、選択されたイメージ書き込みライブラリ(私の例ではlibtiff)を使用して、それらのスキャンラインをディスクに戻します。

メモリ使用量が少なく、CPU使用率が高いことがわかります。

+0

既存の '+ - * /'演算子についてのヒントはとても役に立ちます。ありがとうございます。しかし、もし私の関数が '.reduce(:+)/ .size'のように単純ではなく、if-branchesなどを持っていればどうでしょうか?それはRubyで実装するのに十分なのでしょうか、Cにジャンプする必要がありますか? – Nakilon

+1

'.ifthenelse'を使って枝を追加することができ、さまざまなローカルフィルタを構築する一連の演算子があります。ほとんどのものは簡単でなければならないかもしれません。 vips trackerもあります。それはかなりアクティブです:https://github.com/jcupitt/libvips/issues – user894763

+1

私は愚かなifthenelseの例を追加しました。 – user894763

関連する問題