- 20191013
0.博客背景
- 病理切片常见的染色方式有 H&E(苏木精和伊红) 和 IHC(免疫组化),用于检测病理组织的癌变情况。大体情况可以参考此处链接。
- 由于cycle GAN能够转换图像模态的特性,由此产生了很多基于改进cycle GAN进行染色模态转换(用H&E染色切片生成虚拟IHC染色切片)的论文。
- 而使用cycle GAN进行模态转换对数据集的基本要求是同类别同组织结构图像之间的转换,所以对H&E和IHC切图生成的patch需要分类对应。众所周知一张WSI的按照256*256切图一般都会有几千上万张patches,手动分类肯定是个大工程,所以在此产生了一种切图思路。
- 利用传统图像算法对H&E和IHC的WSI进行配准,然后按照配准变换在两张WSI上对应切图,这样能够保证大部分patches两两之间的组织形态是一致的,由此着手研究了传统的图像配准算法。
- PS :如果有现成分类好的公开数据集就完全没必要这么折腾。
1.基于ORB的图像配准
-
配准图像
由于病理图像结构复杂性,就直接选取对应组织部分的mask进行配准。
- H&E缩略图tissue部分mask
- IHC缩略图tissue部分mask
- H&E缩略图tissue部分mask
-
代码实现
参考 https://blog.csdn.net/lyxleft/article/details/89476175
from skimage import io import cv2 as cv import numpy as np import matplotlib.pyplot as plt img_path1 = '2_HE_maxarea.png' img_path2 = '2_IHC_maxarea.png' img1 = io.imread(img_path1) img2 = io.imread(img_path2) img1 = np.uint8(img1) img2 = np.uint8(img2) # find the keypoints and descriptors with ORB orb = cv.ORB_create() kp1, des1 = orb.detectAndCompute(img1,None) kp2, des2 = orb.detectAndCompute(img2,None) # def get_good_match(des1,des2): # bf = cv.BFMatcher() # matches = bf.knnMatch(des1, des2, k=2) # good = [] # for m, n in matches: # if m.distance < 0.75 * n.distance: # good.append(m) # return good,matches # goodMatch,matches = get_good_match(des1,des2) # img3 = cv.drawMatchesKnn(img1,kp1,img2,kp2,matches[:20],None,flags=2) # create BFMatcher object bf = cv.BFMatcher(cv.NORM_HAMMING, crossCheck=True) # Match descriptors. matches = bf.match(des1,des2) # Sort them in the order of their distance. matches = sorted(matches, key = lambda x:x.distance) # Draw first 20 matches. img3 = cv.drawMatches(img1,kp1,img2,kp2,matches[:20],None, flags=2) goodMatch = matches[:20] if len(goodMatch) > 4: ptsA= np.float32([kp1[m.queryIdx].pt for m in goodMatch]).reshape(-1, 1, 2) ptsB = np.float32([kp2[m.trainIdx].pt for m in goodMatch]).reshape(-1, 1, 2) ransacReprojThreshold = 4 H, status =cv.findHomography(ptsA,ptsB,cv.RANSAC,ransacReprojThreshold); #其中H为求得的单应性矩阵矩阵 #status则返回一个列表来表征匹配成功的特征点。 #ptsA,ptsB为关键点 #cv2.RANSAC, ransacReprojThreshold这两个参数与RANSAC有关 imgOut = cv.warpPerspective(img2, H, (img1.shape[1],img1.shape[0]),flags=cv.INTER_LINEAR + cv.WARP_INVERSE_MAP) # 叠加配准变换图与基准图 overlapping = cv.addWeighted(img1, 0.6, imgOut, 0.4, 0) io.imsave('HE_2_IHC.png', overlapping) # 显示对比 plt.subplot(221) plt.title('orb') plt.imshow(img3) plt.subplot(222) plt.title('imgOut') plt.imshow(imgOut) plt.subplot(223) plt.title('overlapping') plt.imshow(overlapping) plt.show()
-
结果展示
此处结果使用H&E为基准图像,将IHC配准到H&E图像。能够看到效果其实还可以,如果后续切图可以选择mask重叠区域保证两者都能切到有效图像。