背景
本文参照github上面的文档,对WSI进行处理,目的在根据WSI原图和对应的标注文件提取小块的补丁(patch),作为训练集和测试集。
需要对如何打开和处理WSI切片有一定的了解,如不了解,可以先去了解一下Openslide和ASAP,这些网上资料都较多,可以自行查阅。
问题
根据文档中的代码,在生成不包括癌变区域的掩码(mask)时,会遇到无法从组织区域掩码中减去癌变区域的情况,下面是原github文档中的代码:
def generator_non_tumor_mask_level(tumor_mask_level, tussion_mask_level):
# 现将tumor_mask_level变成灰度图
tumor_mask_grayscale = cv2.cvtColor(tumor_mask_level, cv2.COLOR_BGR2GRAY)
# 非运算
tumor_mask_grayscale_inv = cv2.bitwise_not(tumor_mask_grayscale)
# 为了位运算,将两个掩码尺寸同一
tumor_mask_grayscale_inv_resized = cv2.resize(tumor_mask_grayscale_inv, (tussion_mask_level.shape[1], tussion_mask_level.shape[0]))
# 交运算
tumor_wsi_excluding_tumor_area = cv2.bitwise_and(tumor_mask_grayscale_inv_resized, tussion_mask_level)
tumor_wsi_excluding_tumor_area_mask = cv2.cvtColor(tumor_wsi_excluding_tumor_area, cv2.COLOR_BGR2GRAY)
return tumor_wsi_excluding_tumor_area
输入这个函数中的tussion_mask_level是已经处理得到的组织区域的灰度图(背景区域像素值为0,组织区域像素值为1,像素值范围是0-255,这里是关键,之后会说明),而tumor_mask_level经过代码中第一句的转化也是同样形式的灰度图。
这个函数的思路就将组织区域的mask减去癌变区域的mask就可以得到不含癌变区域的正常组织,这个思路是没错的,但是出来的结果缺不是我们想要的。
以下三张图,从上到下分别是组织区域的mask,癌变区域的mask,和利用上面代码生成的不包含癌变区域的正常组织mask,可以看到,组织区域的mask和生成的不包含癌变区域的正常组织mask并没有什么区别。
之所以会出现这样的情况,和前面提到的 “ 背景区域像素值为0,组织(或癌变)区域像素值为1,像素值范围是0-255 ” 有关系,因为图像的相减并不是直接的相减,而是要被其中一个图像取反之后相加(或者位图像相与)来完成。(至于为什么生成的mask组织区域的像素值为1,可能与通过openslide打开与保存这些mask有关,我是通过将读取之后的mask保存在csv文件中才知道组织区域的像素值是1的)
所以在原代码中,通过对tumor_mask_grayscale进行取反操作,得到的mask的背景区域像素值变为255,癌变区域像素值变为254,再与组织区域的mask进行位的与操作,自然不能得到去除了癌变区域的组织区域。
既然知道了问题所在,那么我们就可以在取反操作之前将癌变区域的像素值映射为1,可以通过opencv中的convertScaleAbs()函数实现。
convertScaleAbs()函数
convertScaleAbs()函数有3个主要参数:src,alpha,beta
设返回值为Result,那么简单的说就是
R
e
s
u
l
t
=
s
r
c
∗
a
l
p
h
a
+
b
e
t
a
Result = src*alpha+beta
Result=src∗alpha+beta
所以我们只需要将alpha设为255,即可实现映射。
修改后的代码
def generator_non_tumor_mask_level(tumor_mask_level, tussion_mask_level): #tumor_mask_level应该是BGR格式的
# 现将tumor_mask_level变成灰度图
tumor_mask_grayscale = cv2.cvtColor(tumor_mask_level, cv2.COLOR_BGR2GRAY)
# tumor_mask_level转化为GRAY之后,数据类型是uint8,但是labeled区域值为1,取非之后为254,并不能在之后的and操作中起到作用
tumor_mask_grayscale = cv2.convertScaleAbs(tumor_mask_grayscale, alpha=255) #a*src+b
# 非运算
tumor_mask_grayscale_inv = cv2.bitwise_not(tumor_mask_grayscale)
# 为了位运算,将两个掩码尺寸同一
tumor_mask_grayscale_inv_resized = cv2.resize(tumor_mask_grayscale_inv,
(tussion_mask_level.shape[1], tussion_mask_level.shape[0]))
tumor_wsi_excluding_tumor_area = cv2.bitwise_and(tussion_mask_level,tumor_mask_grayscale_inv_resized) #tussion_mask_level
tumor_wsi_excluding_tumor_area_mask = cv2.cvtColor(tumor_wsi_excluding_tumor_area, cv2.COLOR_GRAY2BGR)
return tumor_wsi_excluding_tumor_area_mask