使用Python自动比对免疫荧光图像的相对强度(一)

Yinski 4,405 2022-06-13

起因

使用ImageJ手动选定测定相对强度值操作繁琐、系统误差大,遂考虑用Python自动化的手段达到目的。

需求

首先检测荧光图像中参照通道的高亮点,并根据高亮点位置画设定大小的选择圈,然后在目的通道与参照通道的中测定选定圈内的中间密度值(int-density),最后计算两个通道的比值。

核心代码

import os
from skimage import io,data,filters
from PIL import Image, ImageDraw,ImageFont
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

def mat2gray(image):
	"""
	归一化函数(线性归一化)
	:param image: ndarray
	:return:
	"""
	# as dtype = np.float32
	image = image.astype(np.float32)
	image = (image - np.min(image)) / (np.max(image)-np.min(image)+ 1e-14)
	return image

def show2D(img2D):
	plt.imshow(img2D,cmap=plt.cm.gray)
	plt.show()

#分离通道并优化处理
def channel(pic):
    #分离通道
    pic_1_raw = pic[:,:,1] #参考通道-根据具体情况设定
    pic_0 = pic[:,:,0] #目的通道
    #高斯模糊gamma通道-可选,在需要将两个位置极近的点算作单个目标的时候使用
    pic_1 = filters.gaussian(pic_1_raw,sigma=3)
    pic_1 = pic_1 * 255
    show2D(pic_0)
    show2D(pic_1)
    return pic_0,pic_1

# 检测gamma的高亮点并且计算两个通道的比值
#bright_threshold亮度阈值,根据需求调整0-1。pixel_range画圈范围,根据需要调整单位为像素
def highlight(pic_1,pic_0,bright_threshold,pixel_range,name): 
    # 检测gamma的高亮点
    pic_1_mask = (mat2gray(pic_1)>=bright_threshold).astype(float)
    from skimage import measure, color
    pic_1_mask_point = measure.label(pic_1_mask, connectivity=pixel_range)
    final_list = []
    radius = 5
    index_mask = np.zeros(pic_1_mask_point.shape) # 写上数字
    index_mask = Image.fromarray(index_mask)
    d = ImageDraw.Draw(index_mask)
    fnt = ImageFont.truetype(r"/System/Library/Fonts/AppleSDGothicNeo.ttc", 30)
    for point_index in range(1, np.max(pic_1_mask_point)+1):
	    # 记录坐标
        dim = np.where(pic_1_mask_point ==point_index)
        dim0,dim1 = [dim[0][0], dim[1][0]]

	    # 读取point所在范围
        bbox = [np.min(dim[0]), np.max(dim[0]), np.min(dim[1]), np.max(dim[1])]
        bbox[0] -= radius
        bbox[1] += radius
        bbox[2] -= radius
        bbox[3] += radius

	    # 计算强度比
        intens = (np.sum(pic_0[bbox[0]:bbox[1], bbox[2]:bbox[3]])) / (np.sum(pic_1[bbox[0]:bbox[1], bbox[2]:bbox[3]])+1e-12)

	    # 记录
        final_list.append([point_index, intens])

	    # 在mask写上数字
        d.text((dim1,dim0), str(point_index), font=fnt)

    index_mask = np.array(index_mask)
    show2D(index_mask)
    results=pd.DataFrame(columns=name,data=final_list)#数据有三列,列名分别为one,two,three
    return results,index_mask #results 为pd数据,index_mask为图像数据
    
if __name__ == '__main__':
    pic = io.imread(file) #file为文件路径
    pic_b,pic_a = channel(pic)  
    results,index_mask = highlight(pic_1=pic_a,
        pic_0 = pic_b,
        bright_threshold = 0.38, #定义筛选阈值
        pixel_range = 2,#定义画圈范围
        name = ['No','b/a']#定义文件名
        )
    print(results)
    savepath,rawfile = os.path.split(file) #分出原路径为保存路径
    results.to_csv(savepath+'/results.csv',encoding='gbk') #保存为csv
    io.imsave(savepath+'/conuts-mask.tif', index_mask) #mask文件保存为tif

到这里荧光图片就能够按照我的需求处理了,下一次将测试批量自动测定并合并整理CSV数据


# Python # 免疫荧光 # 图像处理