(实时)使用pyvips查看大图
(Live) viewing of large images using pyvips
我最近发现了很棒的 pyvips 包,并想用它来分析在自制幻灯片扫描仪(不是我制作的)上获取的数据。我沿着方形样本的边缘扫描了大约 4000 个 1024x1024 像素的图块(未记录样本的中心部分)。所有图块都保存为一个二进制文件。我写了一个 python class returns 所需的图块作为二进制文件中的 numpy 数组,它还给出了 (x, y) 特定图块的坐标。不幸的是,瓷砖没有排列在网格上。
我首先确定完整图像的总宽度和高度,并初始化正确大小的黑色图像,然后使用插入功能将图块放置在正确的位置。合成图像大约为 120k x 120k 像素,但图像的大部分是空的。最后,我使用 matplotlib 绘制生成的图像。
import pyvips
import numpy as np
import matplotlib.pyplot as plt
# class to read tiles from data file
sr = TileReader("path_to_scan_file")
# some stuff to determine the width and height of the total image...
# create empty image for inserting tiles
im = pyvips.Image.black(width, height)
# loop over all tiles and place tile at correct position
for i in range(sr.num_tiles()):
frame, coord = sr.ReadFrame(i)
tile = pyvips.Image.new_from_array(frame)
im = im.insert(tile, coord[0], coord[1])
# plot result
plt.imshow(im.numpy())
plt.show()
# save file
im.write_to_file('full_image.tiff')
在循环中生成完整图像似乎非常快。但是,绘制或保存数据不是。 (显然,)绘图仅适用于少量的图块(~10)。我还尝试将数据保存为金字塔形 tiff。但是,写入图像需要几个小时,生成的文件似乎已损坏或太大而无法打开。不幸的是,没有管理员权限我无法安装 nip2。
我希望能够手动 select 合成图像的感兴趣区域,我可以将其用于进一步处理。与生成的图像交互以启用此功能的 best/fastest 方式是什么?
您可以使用 crop
剪下一大块图像并将其传递给其他东西。它不会做全部,它只会渲染你需要的部分,所以它会很快。
类似于:
# loop over all tiles and place at correct position
# do this once on startup
for i in range(sr.num_tiles()):
frame, coord = sr.ReadFrame(i)
tile = pyvips.Image.new_from_array(frame)
im = im.insert(tile, coord[0], coord[1])
# left, top, width, height
# hook these numbers up to eg. a scrollbar
# do the crop again for each scrollbar movement
tile = im.crop(0, 0, 1000, 1000)
# plot result
plt.imshow(tile.numpy())
plt.show()
如果你想花哨,最好的解决方案可能是 vips_sink_screen()
:
https://www.libvips.org/API/current/libvips-generate.html#vips-sink-screen
这将允许您在平移和缩放时从任何管道异步生成像素,但遗憾的是它需要 C。这里有一个使用此 API 的图像查看器示例:
https://github.com/jcupitt/vipsdisp
那是 运行 vips_sink_screen()
在后台生成各种比例的 GPU 纹理,然后在平移和缩放时使用该组纹理以 60 fps (ish) 的速度绘制屏幕。它可以非常快速地显示巨大 动态计算的图像。
我最近发现了很棒的 pyvips 包,并想用它来分析在自制幻灯片扫描仪(不是我制作的)上获取的数据。我沿着方形样本的边缘扫描了大约 4000 个 1024x1024 像素的图块(未记录样本的中心部分)。所有图块都保存为一个二进制文件。我写了一个 python class returns 所需的图块作为二进制文件中的 numpy 数组,它还给出了 (x, y) 特定图块的坐标。不幸的是,瓷砖没有排列在网格上。
我首先确定完整图像的总宽度和高度,并初始化正确大小的黑色图像,然后使用插入功能将图块放置在正确的位置。合成图像大约为 120k x 120k 像素,但图像的大部分是空的。最后,我使用 matplotlib 绘制生成的图像。
import pyvips
import numpy as np
import matplotlib.pyplot as plt
# class to read tiles from data file
sr = TileReader("path_to_scan_file")
# some stuff to determine the width and height of the total image...
# create empty image for inserting tiles
im = pyvips.Image.black(width, height)
# loop over all tiles and place tile at correct position
for i in range(sr.num_tiles()):
frame, coord = sr.ReadFrame(i)
tile = pyvips.Image.new_from_array(frame)
im = im.insert(tile, coord[0], coord[1])
# plot result
plt.imshow(im.numpy())
plt.show()
# save file
im.write_to_file('full_image.tiff')
在循环中生成完整图像似乎非常快。但是,绘制或保存数据不是。 (显然,)绘图仅适用于少量的图块(~10)。我还尝试将数据保存为金字塔形 tiff。但是,写入图像需要几个小时,生成的文件似乎已损坏或太大而无法打开。不幸的是,没有管理员权限我无法安装 nip2。
我希望能够手动 select 合成图像的感兴趣区域,我可以将其用于进一步处理。与生成的图像交互以启用此功能的 best/fastest 方式是什么?
您可以使用 crop
剪下一大块图像并将其传递给其他东西。它不会做全部,它只会渲染你需要的部分,所以它会很快。
类似于:
# loop over all tiles and place at correct position
# do this once on startup
for i in range(sr.num_tiles()):
frame, coord = sr.ReadFrame(i)
tile = pyvips.Image.new_from_array(frame)
im = im.insert(tile, coord[0], coord[1])
# left, top, width, height
# hook these numbers up to eg. a scrollbar
# do the crop again for each scrollbar movement
tile = im.crop(0, 0, 1000, 1000)
# plot result
plt.imshow(tile.numpy())
plt.show()
如果你想花哨,最好的解决方案可能是 vips_sink_screen()
:
https://www.libvips.org/API/current/libvips-generate.html#vips-sink-screen
这将允许您在平移和缩放时从任何管道异步生成像素,但遗憾的是它需要 C。这里有一个使用此 API 的图像查看器示例:
https://github.com/jcupitt/vipsdisp
那是 运行 vips_sink_screen()
在后台生成各种比例的 GPU 纹理,然后在平移和缩放时使用该组纹理以 60 fps (ish) 的速度绘制屏幕。它可以非常快速地显示巨大 动态计算的图像。