2017-02-21 179 views
0

我正在使用Vips图像库处理一些大的组织学图像。与图像一起,我有一个坐标数组。我想制作一个二进制掩码,用于掩盖由坐标创建的多边形内的图像部分。我首先尝试使用vips绘制函数来做到这一点,但这样做效率非常低,需要花费很长时间(在我的真实代码中,图像大约是100000 x 100000像素,并且多边形数组非常大)。将PIL图像转换为VIPS图像

然后我尝试使用PIL创建二进制掩码,并且这很有效。我的问题是将PIL图像转换为vips图像。它们都必须是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

您正在从PIL保存在TIFF格式,但然后使用专署new_from_memory构造函数,它期待的像素值的一个简单的C数组。

最简单的修复方法是使用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, "") 

它应该工作。

vips multiply对两个8位uchar映像的操作将生成一个16位uchar映像,它看起来很暗,因为数字范围将为0 - 255.您可以将其重新转换为uchar(在保存之前将.cast("uchar")附加到乘法线),或者对PIL掩码使用255而不是1。

您还可以将图像从PIL移动到VIPS作为一个简单的字节数组。它可能稍微快一点。

你说得对,在vips中的draw操作不适用于Python中非常大的图像。用vips编写任何大小的面具图像并不困难(只需将大量&&<与通常的缠绕规则结合在一起),但使用PIL确实更简单。

你也可以考虑把你的poly mask作为SVG图像。 libvips可以高效地载入非常大的SVG图像(它根据需要呈现部分),所以您只需将它放大到任何需要的光栅图像大小即可。

+0

谢谢你的回答,改成'new_from_buffer'为我修好了。并且还要感谢您提供有关将转换附加到乘法函数的附加信息。我会先尝试这个解决方案,然后在必要时考虑其他建议。 – Rune