Open greatghoul opened 10 months ago
我的姐姐是一位大学教授,她的课题研究中,需要处理一些显微镜影像图片,但是 MRXS 文件导出的 TIF 图片尺寸太大,通常能达到几万到十几万像素,文件体积也能达到六七百M甚至更大,这样巨大的文件,通常的看图软件或者图片处理软件根本无法打开。
我拿到图片后,也尝试了一些处理软件,均以失败告终,于是想到使用 Python 的图像库来进行处理,尝试了 cv2, PIL, Pillow 等一些库,都没有能够解决。
import cv2 large_image = cv2.imread("E:\\imagematch\\CMU-1-Saved-1_2.mrxs")
即使手动设置 OPENCV_IO_MAX_IMAGE_PIXELS 也无济于事。
于是我转变了想法,可不可以直接处理 MRXS 文件呢,毕竟 CaseViewer 本身就可以按照区域查看 Slide 中的图像。
网上搜索后,找到了 OpenSlide 这个库,尝试了下,发现可以解析 MRXS 文件,比如如下的脚本,可以正确的拿到各个缩放级别的图像尺寸,看样子有戏。
slide = openslide.OpenSlide("E:\\imagematch\\CMU-1-Saved-1_2.mrxs") print(slide.level_dimensions) # ((57230, 117638), (28615, 58819), (14307, 29409), (7153, 14704), (3576, 7352), (1788, 3676), (894, 1838), (447, 919), (223, 459))
OpenSlide 是有一个 read_region 方法的,可以用来读取区域的图像,从而达到裁剪的目的。
def read_region(self, location, level, size):
不过我们今天会使用另一个工具 - DeepZoomGenerator,它可以按照我们指定的尺寸来裁剪图像,例如按照 3000x3000 来裁剪的话,在不同的缩放级别下,会生成不同的“小”块, 在最高的缩放级别上面,会生成 20 列 40 行的图像。
data_gen = DeepZoomGenerator(slide, tile_size=3000, overlap=0, limit_bounds=False) print(data_gen.level_tiles) # ((1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 2), (2, 3), (3, 5), (5, 10), (10, 20), (20, 40))
遍历这些行列,保存这些图像就可以完成裁剪了。
data_gen = DeepZoomGenerator(slide, tile_size=3000, overlap=0, limit_bounds=False) level = data_gen.level_count - 1 [cols, rows] = data_gen.level_tiles[-1] for col in range(cols): for row in range(rows): im = data_gen.get_tile(level, (col, row)) im.save("E:\\imagematch\\output\\%s_%s.jpg" % (col, row))
但是这样裁剪下来有一个问题,就是很多空白图片,一张 Slide 上面,实验数据只占一点点。
我们可以简单的丢弃掉纯白的图像,只保留有内容的。
extrema = im.convert("L").getextrema() if extrema[0] != extrema[1]: im.save("E:\\imagematch\\output\\%s_%s.jpg" % (col, row))
完整的脚本
import os # 如果脚本找不到 openslide 运行库,可以这样手动指定 os.add_dll_directory("C:\\tools\\openslide-win64-20171122\\bin") import openslide from openslide.deepzoom import DeepZoomGenerator # 使用 Open Slide 打开 mrxs img_path = "E:\\imagematch\\slide-8.mrxs" slide = openslide.OpenSlide(img_path) # 按照 3000 x 3000 切割图片,如果想要更大的图,可以自己调整,overlap 是指图片边界不重叠 data_gen = DeepZoomGenerator(slide, tile_size=3000, overlap=0, limit_bounds=False) # 拿到最高像素的缩放级别 level = data_gen.level_count - 1 # 获取最高像素下分割后的列数和行数 [cols, rows] = data_gen.level_tiles[-1] print(cols, rows) # 循环读取各个行列的图像 for col in range(cols): for row in range(rows): print("Processing %s %s" % (col, row)) im = data_gen.get_tile(level, (col, row)) # 如果图像是纯白,则跳过 extrema = im.convert("L").getextrema() if extrema[0] != extrema[1]: # 保存图像到 output 文件夹(需要提前创建这个文件夹) im.save("E:\\imagematch\\output\\%s_%s.jpg" % (col, row))
用到的 Slide 文件,可以在这里下载到。
参考资料
slug: openslide-python-cut-mrxs-slide date: 2022-05-28
我的姐姐是一位大学教授,她的课题研究中,需要处理一些显微镜影像图片,但是 MRXS 文件导出的 TIF 图片尺寸太大,通常能达到几万到十几万像素,文件体积也能达到六七百M甚至更大,这样巨大的文件,通常的看图软件或者图片处理软件根本无法打开。
我拿到图片后,也尝试了一些处理软件,均以失败告终,于是想到使用 Python 的图像库来进行处理,尝试了 cv2, PIL, Pillow 等一些库,都没有能够解决。
即使手动设置 OPENCV_IO_MAX_IMAGE_PIXELS 也无济于事。
于是我转变了想法,可不可以直接处理 MRXS 文件呢,毕竟 CaseViewer 本身就可以按照区域查看 Slide 中的图像。
网上搜索后,找到了 OpenSlide 这个库,尝试了下,发现可以解析 MRXS 文件,比如如下的脚本,可以正确的拿到各个缩放级别的图像尺寸,看样子有戏。
OpenSlide 是有一个 read_region 方法的,可以用来读取区域的图像,从而达到裁剪的目的。
不过我们今天会使用另一个工具 - DeepZoomGenerator,它可以按照我们指定的尺寸来裁剪图像,例如按照 3000x3000 来裁剪的话,在不同的缩放级别下,会生成不同的“小”块, 在最高的缩放级别上面,会生成 20 列 40 行的图像。
遍历这些行列,保存这些图像就可以完成裁剪了。
但是这样裁剪下来有一个问题,就是很多空白图片,一张 Slide 上面,实验数据只占一点点。
我们可以简单的丢弃掉纯白的图像,只保留有内容的。
完整的脚本
参考资料