栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Deeplung复现 数据切割部分(测试)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Deeplung复现 数据切割部分(测试)

Deeplung复现 (二)、数据切割部分(测试)

deeplung中这部分的实现代码同样都是参照的DSB2017的第一名团队的代码,主要的思路就是一个完整的CT由于GPU内存的限制很难全部直接送入网络进行计算,所以需要进行切分,切分成更小的尺寸,这样才能送入网络进行计算。这部分的代码主要在data.py中的DataBowl3Detector类中的__getitem__函数。

imgs = np.load(self.filenames[idx])
            # print('imgs.shape',imgs.shape)
            bboxes = self.sample_bboxes[idx] # 为啥还要有标签
            nz, nh, nw = imgs.shape[1:]#(197, 181, 224)
            pz = int(np.ceil(float(nz) / self.stride)) * self.stride # 补成stride的倍数
            ph = int(np.ceil(float(nh) / self.stride)) * self.stride
            pw = int(np.ceil(float(nw) / self.stride)) * self.stride
            imgs = np.pad(imgs, [[0,0],[0, pz - nz], [0, ph - nh], [0, pw - nw]], 'constant',constant_values = self.pad_value)  # 用170将长宽高填充成stride的整数倍,为了方便下面计算coord
            # print('1------pad',self.stride, pz,ph,pw)
            xx,yy,zz = np.meshgrid(np.linspace(-0.5,0.5,imgs.shape[1]/self.stride),
                                   np.linspace(-0.5,0.5,imgs.shape[2]/self.stride),
                                   np.linspace(-0.5,0.5,imgs.shape[3]/self.stride),indexing ='ij')
            coord = np.concatenate([xx[np.newaxis,...], yy[np.newaxis,...],zz[np.newaxis,:]],0).astype('float32') # np.newaxis用来增加一个维度,使x,y,z坐标可以堆叠起来,
            # print('------1',imgs.shape)
            imgs, nzhw = self.split_comber.split(imgs)  # 获得分割好的patch
            # print('------2',imgs.shape)
            # print('------',self.split_comber.max_stride,self.stride)
            
            coord2, nzhw2 = self.split_comber.split(coord,
                                                   side_len = self.split_comber.side_len//self.stride,
                                                   max_stride = self.split_comber.max_stride//self.stride,
                                                   margin = self.split_comber.margin//self.stride) # 相应的coord也要进行分割
            assert np.all(nzhw==nzhw2)  # 如果没有问题,nzhw和nzhw2肯定是一样的
            imgs = (imgs.astype(np.float32)-128)/128
            # print('sample.shape',imgs.shape,coord2.shape)
            return torch.from_numpy(imgs), bboxes, torch.from_numpy(coord2), np.array(nzhw)

这部分的代码都做了详细的注释,其中最主要的就是利用了split_comber类中的split函数对一整张CT图像进行划分(在deeplung中作者将一整张CT在测试的时候划分成了(160x160x160)的patch,并且patch之间有32像素的重叠区域,防止边缘效应)。并对每个patch相应的coord进行了计算。

一开始我在看这部分的代码时产生了一个疑问,就是以上的代码虽然将一张CT分割成了很多patch,但是最终返回的结果是将所有的patch堆叠在一起,这样不是和将一整张CT送入网络没啥区别吗?
这个疑问在我看main.py的test函数得到了解答,在这个函数中会将所有的patch再进行拆分,即保证每次只将一个patch送入网络。


下面贴出split函数,关键部分都有详细的注释

    def split(self, data, side_len = None, max_stride = None, margin = None):
        if side_len==None:
            side_len = self.side_len
        if max_stride == None:
            max_stride = self.max_stride
        if margin == None:
            margin = self.margin
        
        assert(side_len > margin)
        assert(side_len % max_stride == 0)
        # print('margin, max_stride',margin, max_stride)
        assert(margin % max_stride == 0)

        splits = []
        _, z, h, w = data.shape
        # print('READdata',data.shape)
        nz = int(np.ceil(float(z) / side_len))  # 补成side_len的倍数
        nh = int(np.ceil(float(h) / side_len))
        nw = int(np.ceil(float(w) / side_len))
        
        nzhw = [nz,nh,nw]  # 里面存的是z,y,x三个轴可以划分的patch个数,一个CT的总的patch个数就是nz*nh*nw
        # print('nzhw',nzhw)
        # print('nzhw',nz * side_len - z + margin)
        self.nzhw = nzhw
        
        pad = [ [0, 0],
                [margin, nz * side_len - z + margin],  # 算出在z轴前后应该padding的大小
                [margin, nh * side_len - h + margin],  # 算出在y轴前后应该padding的大小
                [margin, nw * side_len - w + margin]]  # 算出在x轴前后应该padding的大小
        data = np.pad(data, pad, 'edge')  # 将原来的CT padding成nz * side_len+2*margin大小,但是为啥要padding成这样呢?看到下面的划分patch的过程就悟了(这样做是为了保证一个CT可以恰好划分出整数个patch并且每两个patch之间具有32像素的重叠区域)
        # print('PADdata',data.shape)
        # print('PADdata',stop)
        for iz in range(nz):
            for ih in range(nh):
                for iw in range(nw):
                    sz = iz * side_len  # 切分的每个patch的z轴起始位置
                    ez = (iz + 1) * side_len + 2 * margin  # 切分的每个patch的z轴终止位置,加上2*margin是为了保证下一个patch的起始位置与上一个patch的终止位置有32个像素的重叠
                    sh = ih * side_len  # 切分的每个patch的y轴起始位置
                    eh = (ih + 1) * side_len + 2 * margin  # 切分的每个patch的y轴终止位置,加上2*margin是为了保证下一个patch的起始位置与上一个patch的终止位置有32个像素的重叠
                    sw = iw * side_len  # 切分的每个patch的x轴起始位置
                    ew = (iw + 1) * side_len + 2 * margin  # 切分的每个patch的x轴终止位置,加上2*margin是为了保证下一个patch的起始位置与上一个patch的终止位置有32个像素的重叠

                    split = data[np.newaxis, :, sz:ez, sh:eh, sw:ew]  # 取出patch的数据(160*160*160),并增加一个batch_size维度
                    splits.append(split)  # 将所有的patch放到一个列表里
        # splits.append(split)
        
        splits = np.concatenate(splits, 0)  # 将所有的patch在batch_size维度进行拼接,最后得到的是(patch个数,1,160,160,160)
        return splits,nzhw
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/948143.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号