实战:使用Pytorch搭建分类网络(肺结节假阳性剔除)
阅前可看:
实战:使用yolov3完成肺结节检测(Luna16数据集)及肺实质分割
其中的脚本资源getMat.py文件是对肺结节进行切割。
注意:
本博客内容没有上述博客内容完美衔接,这里只是提供思路(在完成肺结节检测之后进行假阳性剔除)以及练习使用pytorch搭建深度学习网络。
- 样本生成
- Pytorch分类网络搭建
- 训练+测试
注意:原始脚本有误,因为进行重采样之后,尺寸就不再是512*512的。!!!
修改如下:
ImageW = int(512 * real_resize_factor[0])
ImageH = int(512 * real_resize_factor[1])
#如果图像进行旋转了,那么坐标也要旋转
if isflip :
x = ImageW - x
y = ImageH - y
2019.11.27发现新的两个bug。
1.注意:原始脚本(getMat.py)有误,修改如下!!!
mat = pix_resampled[y - 20: y + 20,
x - 20: x + 20,
z - 12: z + 12]
原因:
这是因为PIL/opencv图片坐标和数组坐标问题。
- 图像和数组的坐标均是左上角(0,0)
- 图像的第一维度是横着的(从做到右),第二维度是竖着的(从上到下)。
- 数组的第一维度是竖着的(从上到下),第二维度是横着的(从做到右)。
- x 和 y 均是
worldToVoxelCoord
函数从世界坐标换算到图像坐标的值。 这个因为其中一个转置imgMat = image_array.transpose(1,2,0) #transpose是将(z,x,y)的三维矩阵转为(x,y,z)的矩阵
,是把x轴放在了数组的第一个维度。
一张图来说明这个问题: 这个图有误,详见下一个图。
这个bug是在可视化.mat文件的时候发现的。
出错图下图所示:
2.注意:原始脚本(traindataset.py)有误,修改如下!!!**
这个是在dataAugmentation
函数中
修改部分:
......
dataMat = dataMat.transpose(2,1,0)#转置 从x,y,z到z,y,x
......
dataMat = dataMat[randZ : randZ + cropD, randY : randY + cropH, randX : randX + cropW]
......
这个原因是使用了pytorch的torch.nn.Conv3D
3D的卷积,输入的shape是 ( N , C i n , D , H , W ) \left(N, C_{i n}, D, H, W\right) (N,Cin,D,H,W),输出shape 是 ( N , C o u t , D o u t , H o u t , W o u t ) \left(N, C_{o u t}, D_{o u t}, H_{o u t}, W_{o u t}\right) (N,Cout,Dout,Hout,Wout),z轴对应的是深度,y轴对应的H,x轴对应的是W,为了保证一致性,转置的地方需要修改
2019.12.5
1.2019.11.27发现的bug确实是bug,但解释的原因有误。
是在这里:imgMat = image_array.transpose(1,2,0) #transpose是将(z,x,y)的三维矩阵转为(x,y,z)的矩阵
,正确的理解是#transpose是将(z,y,x)的三维矩阵转为(y,x,z)的矩阵
重新修改图示为:
2. 所以在traindataset.py
中上述修改的这个 误。正确的是:dataMat = dataMat.transpose(2,1,0)#转置 从x,y,z到z,y,x
有dataMat = dataMat.transpose(2,0,1)#转置 从y,x,z到z,y,x
1.样本生成
肺结节样本来自Luna16数据集,这里主要使用pytorch进行搭建分类网络,对疑似肺结节进行分类,进行假阳性剔除。在进行深度学习训练之前,需要完成样本集的生成。getMat.py脚本已上传到上述博客的资源中,这里对核心代码进行分析。
1.1尺度归一化
因为CT影像的采样间隔是不一致的,这里进行尺度归一化成1mm * 1mm * 1mm。也许在图像检测的时候这个尺度是否归一化可能影像不大,但是如果对单个肺结节进行分类的话,放缩到统一尺度下,是有利于分类的。
def resample(image, spacing, new_spacing=[1,1,1]):
# Determine current pixel spacing
#print("spacing:",spacing)
#spacing = np.array(list(spacing))
resize_factor = spacing / new_spacing
new_real_shape = image.shape * resize_factor
new_shape = np.round