这里介绍使用 AICSImage 和 roifile 来读取从 ImageJ 中保存的 TIFF 高维图像和 ROI 记录。
读取TIFF图像文件,之前我常用的是 scikit-image 中提供的方法:
from skimage import io
img = io.imread('something.tif', plugin='pil')读取的数据其实就是一个 np.array,可以使用 numpy 这个强大的库进行各种矩阵计算,这样就很方便。但最近不知道是什么原因,读取的矩阵的 shape 会变化。比如有些数据是 (1000, 1000,3),有些就成了 (3,1000,1000),这会给我批量处理图像带来错误。所以我后来更换为了 AICSImage 这个模块来作为读取各种科研方面成像数据的主要工具。另外 imageio 也是不错的选择,支持的数据格式也相当丰富。
使用AICSImage读取图像的方法,官方文档给了很好的说明。摘抄如下:
from aicsimageio import AICSImage
# Get an AICSImage objectimg = AICSImage("my_file.tiff") # selects the first scene foundimg.data # returns 5D TCZYX numpy arrayimg.xarray_data # returns 5D TCZYX xarray data array backed by numpyimg.dims # returns a Dimensions objectimg.dims.order # returns string "TCZYX"img.dims.X # returns size of X dimensionimg.shape # returns tuple of dimension sizes in TCZYX orderimg.get_image_data("CZYX", T=0) # returns 4D CZYX numpy array最常用的就是 get_mage_data 方法,第一个参数是指定返回的数值矩阵的 dimension。以上示例代码为例,注意CZYX分别代表通道,Z轴,Y轴(对应row)和X轴(对应 col)。这个参数可以修改为 YX,那么就是返回一张二维的矩阵了。
读取 ImageJ 中保存的 ROI 记录,我选择使用的 roifile 这个模块,也是非常简单好用。
from roifile import roiread
rois = roiread(item['roi_fp'])注意这里的 roiread 方法,既可以读取单个 roi 文件,也可以读取多个 roi 的 zip 文件。如果是读取 zip 文件,返回的是一个列表。
我这里主要是针对 xyc 类型的成像数据,想提取其中 FAM 荧光通道和 BF 明场通道的数据。代码如下所示:
for idx, item in enumerate(box): item['img'] = AICSImage(item['img_fp']) if item['group']=='ctrl': item['FAM'] = item['img'].get_image_data("YX", C=1) item['BF'] = item['img'].get_image_data("YX", C=0) else: item['FAM'] = item['img'].get_image_data("YX", C=0) item['BF'] = item['img'].get_image_data("YX", C=1) item['rois'] = roiread(item['roi_fp'])之前我们已经使用 box 这个列表变量,收集好了各个数据。每个数据 item 是一个字典,记录了相关的信息。然后就可以对 box 进行遍历。
这里有个特殊情况,由于 ctrl 这个组的数据中,明场通道在第一个,FAM在第二个;而其它组的数据,FAM是第一个通道。所以循环过程中,可以根据组别,调整需要提取的通道数据。
提取的指定通道的图像,我们可以直接在这个 item 字典中新增键值对,和之前保留的信息放到一起。这就是字典的妙用之一。
最后,可以查看下图像和ROI,由于我ROI是矩形,所以遍历得到ROI的所有锚点xy坐标后,可以选择 matplotlib 中的 polygon 来绘制。代码如下:
import matplotlib.pyplot as pltfrom matplotlib.patches import Polygon
fig, ax = plt.subplots(figsize=(8,8))ax.imshow(item['BF'], vmin=0, vmax=255, cmap="Grays")for roi in item['rois']: coords = roi.coordinates() # 获取roi的坐标,注意返回的是一个array, [[x0, y0], [x1, y1],...] # 等同于 [[c0, r0], [c1, r1],...],按矩阵处理时要格外注意这点 contour = Polygon(coords, edgecolor='yellow', facecolor='yellow', linewidth=2, alpha=0.2, ) ax.add_patch(contour)plt.show()效果如下: