这里介绍如何使用python中的scikit-image包提供的工具模块实现类似ImageJ中划线测量的功能。
在前面我们已经导出了绿色通道的图像,接下来可以使用 ImageJ 对其中感兴趣的区域进行划线,并保存为ROI记录,然后再回到 python 中直接读取 ROI ,批量提取所有数据的 profile 并与下游的统计分析整合到一起。
ImageJ中划线保存ROI
由于保存的tif图像并没有写多余的meta信息指定LUT和Scale,所以我们使用 ImageJ 打开后通常还需要自己设置伪彩,调整对比和设定 Scale(已经统一pixelsize为 =0.1微米)。为了方便, 这里可以使用一小段 ImageJ Macro:
run("Green");
run("Enhance Contrast", "saturated=0.35");
run("Set Scale...", "distance=1 known=0.1 unit=microns");然后完成所有selection 并保存到 ROI 管理器之后,可以执行以下一段 ImageJ Macro 快速保存并按照规则命名 ROI 记录文件:
img = getTitle();wks = getDirectory("image");fname = img+"_RoiSet.zip";fpath = wks + "/" +fname;roiManager("deselect");roiManager("save",fpath);roiManager("delete");save(wks+"/"+img);close();python中提取profile
借鉴我之前的文章读取ImageJ保存的ROI记录和TIFF图像,然后profiling 可以使用 scikit-image 中的 profile_line 函数。这里需要 import 的模块如下:
from aicsimageio import AICSImagefrom roifile import roireadimport matplotlib.pyplot as pltfrom skimage.measure import profile_linefrom glob import globimport pickle由于要同时读取图像和ROI记录,所以我们可以通过这样的方式把文件路径弄好:
fps = glob("*.tif")
rps = [fp+"_RoiSet.zip" for fp in fps]图像文件和ROI文件分别存放在 fps 和 rps 两个 list,而且rps是通过列表推导式基于fps生成的,所以每一个图像与其ROI是一一对应的。后面就可以用 zip 函数来遍历。
读取TIFF图像文件使用 AICSImage,由于我们之前已经设定好了,只是 xy 二维图像,而且 pixelsize 统一为 0.1,所以这里读取数据的代码就只有两行:
img = AICSImage(fp)
ch = img.get_image_data("YX")读取ROI文件使用 roifile 的 roiread 函数,返回的是一个 list,然后结合后面 profile_line 的input 要求,我们需要知道这个 line type 的 roi 的起点和终点。这里可以通过 dir 函数来查看 roi 对象有哪些 attribute,然后发现有一个 .coordinates() 的方法会回传一个坐标列表,但是仍然是 [x, y] 的顺序,如果要用到矩阵中,得自己换成 [y, x] 再输入。而对于 line type roi,还有一些 x1,x2,y1,y2 等更加直观的属性,我们很容易就知道(x1, y1) 应该对应的就是起点。所以这个部分就是:
prof = profile_line(ch, src=[roi.y1, roi.x1], dst=[roi.y2, roi.x2], linewidth=1)然后遍历收集数据到字典中,并且保存到临时文件,休息一下,方便之后接着处理。
with open("line_profiles.tmp", 'wb') as f:
pickle.dump(data, f)完整代码如下:
from aicsimageio import AICSImagefrom roifile import roireadimport matplotlib.pyplot as pltfrom skimage.measure import profile_linefrom glob import globimport pickle
# 批量获取文件路径fps = glob("*.tif")rps = [fp+"_RoiSet.zip" for fp in fps]
# 遍历文件处理并使用字典收集整理data = {}for fp, rp in zip(fps, rps): parts = fp.split("_") group = parts[1] cell = parts[2].split(".")[0] if group not in data: data[group] = {} if cell not in data[group]: data[group][cell] = [] img = AICSImage(fp) ch = img.get_image_data("YX") rois = roiread(rp) for idx, roi in enumerate(rois): prof = profile_line(ch, src=[roi.y1, roi.x1], dst=[roi.y2, roi.x2], linewidth=1) data[group][cell].append(prof)
#保存整理好的数据到临时文件with open("line_profiles.tmp", 'wb') as f: pickle.dump(data, f)