【问题标题】:Converting PIL image to VIPS image将 PIL 图像转换为 VIPS 图像
【发布时间】:2017-02-21 16:47:24
【问题描述】:

我正在使用 Vips 图像库处理一些大型组织学图像。连同图像,我有一个带有坐标的数组。我想制作一个二进制掩码,它掩盖了由坐标创建的多边形内的图像部分。我首先尝试使用 vips 绘制功能来做到这一点,但这非常低效并且需要很长时间(在我的真实代码中,图像大约为 100000 x 100000px 并且多边形数组非常大)。

然后我尝试使用 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')

【问题讨论】:

    标签: python-imaging-library bytesio vips


    【解决方案1】:

    您正在以 TIFF 格式从 PIL 保存,但随后使用 vips 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") 附加到乘法行)在保存之前,或者使用 255 而不是 1 作为您的 PIL 掩码。

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

    你说得对,vips 中的draw 操作不适用于 Python 中非常大的图像。在 vips 中编写一个东西来从一组点制作任何大小的蒙版图像并不难(只需将大量 &&< 与通常的缠绕规则结合起来),但使用 PIL 肯定更简单。

    您还可以考虑将多边形蒙版设为 SVG 图像。 libvips 可以有效地加载非常大的 SVG 图像(它按需渲染部分),因此您只需将其放大到光栅图像所需的任何大小。

    【讨论】:

    • 感谢您的回答,改成new_from_buffer 为我解决了这个问题。还要感谢您提供有关将强制转换附加到乘法函数的其他信息。我会先尝试这个解决方案,然后在必要时考虑您的其他建议。
    猜你喜欢
    • 2015-12-31
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 2016-12-04
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 2018-08-15
    相关资源
    最近更新 更多