2017-02-21 20 views
0

私は、Vips画像ライブラリを使用して、いくつかの大きな組織画像に取り組んでいます。画像とともに私は座標を持つ配列を持っています。私は、座標によって作成されたポリゴン内の画像の部分をマスクするバイナリマスクを作成します。私はまずvips draw関数を使ってこれをやろうとしましたが、これは非常に非効率的で、永遠に(実際のコードでは約100000×100000px、ポリゴンの配列は非常に大きい)です。PIL画像をVIPS画像に変換する

次に、PILを使用してバイナリマスクを作成しようとしましたが、これは素晴らしいです。私の問題は、PILイメージをvipsイメージに変換することです。 multiply-commandを使用できるようにするには、両方ともvipsイメージでなければなりません。私はまた、ディスクに書き込むよりも速いと思うので、メモリから書き込みして読み込みたいと思っています。

im_PIL.save(memory_area,'TIFF')コマンドでは、イメージ形式を指定する必要がありますが、新しいイメージを作成しているので、ここに何を入れるべきか分かりません。

Vips.Image.new_from_memory(..)コマンドの戻り値:TypeError: constructor returned NULL

from gi.overrides import Vips 
from PIL import Image, ImageDraw 
import io 

# Load the image into a Vips-image 
im_vips = Vips.Image.new_from_file('images/image.tif') 

# Coordinates for my mask 
polygon_array = [(368, 116), (247, 174), (329, 222), (475, 129), (368, 116)] 

# Making a new PIL image of only 1's 
im_PIL = Image.new('L', (im_vips.width, im_vips.height), 1) 

# Draw polygon to the PIL image filling the polygon area with 0's 
ImageDraw.Draw(im_PIL).polygon(polygon_array, outline=1, fill=0) 

# Write the PIL image to memory ?? 
memory_area = io.BytesIO() 
im_PIL.save(memory_area,'TIFF') 
memory_area.seek(0) 

# Read the PIL image from memory into a Vips-image 
im_mask_from_memory = Vips.Image.new_from_memory(memory_area.getvalue(), im_vips.width, im_vips.height, im_vips.bands, im_vips.format) 

# Close the memory buffer ? 
memory_area.close() 

# Apply the mask with the image 
im_finished = im_vips.multiply(im_mask_from_memory) 

# Save image 
im_finished.tiffsave('mask.tif') 

答えて

1

あなたがTIFF形式でPILから保存、その後の画素値の単純なC配列を期待してのVIP new_from_memoryコンストラクタを使用しています。

最も簡単な修正は、new_from_bufferを代わりに使用することです。これは、画像をある形式で読み込み、文字列から形式をスニッフィングします。プログラムの中央部分を次のように変更してください。

# Write the PIL image to memory in TIFF format 
memory_area = io.BytesIO() 
im_PIL.save(memory_area,'TIFF') 
image_str = memory_area.getvalue() 

# Read the PIL image from memory into a Vips-image 
im_mask_from_memory = Vips.Image.new_from_buffer(image_str, "") 

これはうまくいくはずです。

2つの8ビットucharイメージ上のvip multiplyは、16ビットucharイメージを作成します。数値範囲は0〜255であるため、非常に暗く見えます。保存する前に.cast("uchar")を乗算行に追加するか、PILマスクに1の代わりに255を使用します。

イメージを単純なバイト配列としてPILからVIPSに移動することもできます。少し速いかもしれません。

あなたが正しいです、drawの操作は、Pythonの非常に大きな画像でうまく動作しません。 1セットのポイントから任意のサイズのマスク画像を作成するためのものを書くことは難しいことではありません(普通の巻き取りルールで&&<のロットを組み合わせるだけです)が、PILを使うのは確かに簡単です。

ポリマスクをSVGイメージとして使用することもできます。 libvipsは非常に大きなSVG画像を効率的に読み込むことができます(必要に応じてセクションをレンダリングする)ので、ラスタ画像に必要なサイズまで拡大するだけです。

+0

答えてくれてありがとう、 'new_from_buffer'に変更してくれました。また、multiply関数へのキャストの追加に関する追加情報もありがとう。まずこのソリューションを試し、必要に応じて他の提案を検討します。 – Rune

関連する問題