Пример #1
0
 def fileopen():
     filename = filedialog.askopenfilename(
         filetypes=[('mhd files',
                     '*.mhd'), ('dicom files',
                                '*.dcm'), ('numpy files',
                                           '*.npy'), ('all', '*')])
     #filename = "E:/tianchi_project/TIANCHI_examples/train_1/LKDS-00001.mhd"
     if filename == '':
         return
     print(repr(filename))
     prename, extname = os.path.splitext(filename)
     if extname == '.mhd':
         full_image_info = sitk.ReadImage(filename)
         full_scan = sitk.GetArrayFromImage(full_image_info)
         old_spacing = np.array(full_image_info.GetSpacing())[::-1]
         volimg, new_spacing = mt.resample(full_scan, old_spacing)
     elif extname == '.dcm':
         pathname = os.path.split(filename)[0]
         full_scan, full_image_info, patientid = mt.read_dicom_scan(
             pathname)
         cvm.view_CT(full_scan)
         old_spacing = np.array(full_image_info.GetSpacing())[::-1]
         volimg, new_spacing = mt.resample(full_scan, old_spacing)
     elif extname == '.npy':
         volimg = np.load(filename)
     else:
         print('unknown data type')
         return
     label = tk.Label(tool_view, image=cvm.view_CT(volimg))
     label.pack()
     tool_view.quit()
Пример #2
0
    def annotations_crop(
        self,
        randsample=True,
        candsample=False,
        overbound=False,
        augment=False
    ):  #the term 'augment' is invalid when 'overbound' is True
        if os.access(self.output_path, os.F_OK):
            shutil.rmtree(self.output_path)
        os.makedirs(self.output_path)
        os.mkdir(self.nodules_npy_path)  #训练用正样本路径
        os.mkdir(self.all_annotations_mhd_path)  #检查用正样本路径
        os.mkdir(self.nonnodule_npy_path)  #训练用负样本路径
        os.mkdir(self.no_annotation_mhd_path)  #检查用负样本路径

        if not os.access(self.vision_path, os.F_OK):
            os.makedirs(self.vision_path)

        for patient in enumerate(tqdm(self.ls_all_patients)):
            patient = patient[1]
            #patient = './LUNA16/subset9\\1.3.6.1.4.1.14519.5.2.1.6279.6001.114914167428485563471327801935.mhd'
            print(patient)
            # 检查这个病人有没有大于3mm的结节标注
            if patient not in self.df_annotations.file.values:
                print('Patient ' + patient + 'Not exist!')
                continue
            patient_uid = mt.get_serie_uid(patient)
            patient_nodules = self.df_annotations[self.df_annotations.file ==
                                                  patient]
            full_image_info = sitk.ReadImage(patient)
            full_scan = sitk.GetArrayFromImage(full_image_info)
            origin = np.array(
                full_image_info.GetOrigin())[::-1]  #---获取“体素空间”中结节中心的坐标
            old_spacing = np.array(full_image_info.GetSpacing()
                                   )[::-1]  #---该CT在“世界空间”中各个方向上相邻单位的体素的间距
            image, new_spacing = mt.resample(full_scan, old_spacing)  #---重采样
            print('resample done')
            v_centers = []
            center_coords = []
            for index, nodule in patient_nodules.iterrows():
                nodule_diameter = nodule.diameter_mm
                nodule_center = np.array(
                    [nodule.coordZ, nodule.coordY,
                     nodule.coordX])  #---获取“世界空间”中结节中心的坐标
                v_center = np.rint(
                    (nodule_center - origin) / new_spacing)  #映射到“体素空间”中的坐标
                v_center = np.array(v_center, dtype=int)
                v_centers.append([index, nodule_diameter, v_center])
                center_coords.append(v_center)
            #volume_regioned = cvm.view_coordinations(image, center_coords, window_size=int(math.ceil(1.5*nodule_diameter)), reverse=False, slicewise=False, show=False)
            #np.save(self.vision_path+"/"+patient_uid+"_annotated.npy", volume_regioned)
            #---这一系列的if语句是根据“判断一个结节的癌性与否需要结合该结节周边位置的阴影和位置信息”而来,故每个结节都获取了比该结节尺寸略大的3D体素

            #get annotations nodule
            window_half = int(BOX_SIZE / 2)
            if overbound:
                num_translations = 1
                for index, nodule_diameter, v_center in v_centers:
                    zyx_1 = v_center - BOX_SIZE  # 注意是: Z, Y, X
                    zyx_2 = v_center + BOX_SIZE
                    if mt.coord_overflow(zyx_1,
                                         image.shape) or mt.coord_overflow(
                                             zyx_2, image.shape):
                        continue
                    nodule_box = np.zeros(
                        [2 * BOX_SIZE, 2 * BOX_SIZE, 2 * BOX_SIZE],
                        np.int16)  # ---nodule_box_size = 45
                    img_crop = image[zyx_1[0]:zyx_2[0], zyx_1[1]:zyx_2[1],
                                     zyx_1[2]:zyx_2[2]]  # ---截取立方体
                    img_crop[img_crop <
                             -1024] = -1024  # ---设置窗宽,小于-1024的体素值设置为-1024
                    try:
                        nodule_box = img_crop[
                            0:2 * BOX_SIZE, 0:2 * BOX_SIZE,
                            0:2 * BOX_SIZE]  # ---将截取的立方体置于nodule_box
                    except:
                        print("annotation error")
                        continue
                    #nodule_box[nodule_box == 0] = -1024  # ---将填充的0设置为-1000,可能有极少数的体素由0=>-1000,不过可以忽略不计
                    self.save_annotations_nodule(
                        nodule_box, patient_uid + "_" + str(index) + "_ob")
            else:
                if not augment:
                    scales = [1.0]
                    translations = np.array([0, 0, 0])
                else:
                    scales = [0.8, 1.0, 1.25]
                    #translations = np.array([[0,0,0],[0,0,1],[0,0,-1],[0,1,0],[0,-1,0],[1,0,0],[-1,0,0]], dtype=float)
                    translations = np.array(
                        [[0, 0, 0], [0, 0, 1], [0, 0, -1], [0, 1, 0],
                         [0, math.sqrt(0.5), math.sqrt(0.5)],
                         [0, math.sqrt(0.5), -math.sqrt(0.5)], [0, -1, 0],
                         [0, -math.sqrt(0.5),
                          math.sqrt(0.5)],
                         [0, -math.sqrt(0.5), -math.sqrt(0.5)], [1, 0, 0],
                         [math.sqrt(0.5), 0, math.sqrt(0.5)],
                         [math.sqrt(0.5), 0, -math.sqrt(0.5)],
                         [math.sqrt(0.5), math.sqrt(0.5), 0],
                         [
                             math.sqrt(0.3333),
                             math.sqrt(0.3333),
                             math.sqrt(0.3333)
                         ],
                         [
                             math.sqrt(0.3333),
                             math.sqrt(0.3333), -math.sqrt(0.3333)
                         ], [math.sqrt(0.5), -math.sqrt(0.5), 0],
                         [
                             math.sqrt(0.3333), -math.sqrt(0.3333),
                             math.sqrt(0.3333)
                         ],
                         [
                             math.sqrt(0.3333), -math.sqrt(0.3333),
                             -math.sqrt(0.3333)
                         ], [-1, 0, 0], [-math.sqrt(0.5), 0,
                                         math.sqrt(0.5)],
                         [-math.sqrt(0.5), 0, -math.sqrt(0.5)],
                         [-math.sqrt(0.5), math.sqrt(0.5), 0],
                         [
                             -math.sqrt(0.3333),
                             math.sqrt(0.3333),
                             math.sqrt(0.3333)
                         ],
                         [
                             -math.sqrt(0.3333),
                             math.sqrt(0.3333), -math.sqrt(0.3333)
                         ], [-math.sqrt(0.5), -math.sqrt(0.5), 0],
                         [
                             -math.sqrt(0.3333), -math.sqrt(0.3333),
                             math.sqrt(0.3333)
                         ],
                         [
                             -math.sqrt(0.3333), -math.sqrt(0.3333),
                             -math.sqrt(0.3333)
                         ]])

                num_translations = 3
                for index, nodule_diameter, v_center in v_centers:
                    for s in range(len(scales)):
                        rt = np.zeros(num_translations, dtype=int)
                        rt[1:num_translations] = np.random.choice(
                            range(1, len(translations)), num_translations - 1,
                            False)
                        rt = np.sort(rt)
                        for t in range(rt.size):
                            scale = scales[s]
                            box_size = int(np.ceil(BOX_SIZE * scale))
                            window_size = int(box_size / 2)
                            translation = np.array(nodule_diameter / 2 *
                                                   translations[rt[t]] /
                                                   new_spacing,
                                                   dtype=int)
                            tnz = translation.nonzero()
                            if tnz[0].size == 0 and t != 0:
                                continue
                            zyx_1 = v_center + translation - window_size  # 注意是: Z, Y, X
                            zyx_2 = v_center + translation + box_size - window_size
                            if mt.coord_overflow(
                                    zyx_1, image.shape) or mt.coord_overflow(
                                        zyx_2, image.shape):
                                continue
                            nodule_box = np.zeros(
                                [BOX_SIZE, BOX_SIZE, BOX_SIZE],
                                np.int16)  # ---nodule_box_size = 45
                            img_crop = image[zyx_1[0]:zyx_2[0],
                                             zyx_1[1]:zyx_2[1],
                                             zyx_1[2]:zyx_2[2]]  # ---截取立方体
                            img_crop[
                                img_crop <
                                -1024] = -1024  # ---设置窗宽,小于-1024的体素值设置为-1024
                            if not augment or scale == 1.0:
                                img_crop_rescaled = img_crop
                            else:
                                img_crop_rescaled, rescaled_spacing = mt.resample(
                                    img_crop, new_spacing, new_spacing * scale)
                            try:
                                padding_shape = (
                                    img_crop_rescaled.shape - np.array(
                                        [BOX_SIZE, BOX_SIZE, BOX_SIZE])) / 2
                                nodule_box = img_crop_rescaled[
                                    padding_shape[0]:padding_shape[0] +
                                    BOX_SIZE,
                                    padding_shape[1]:padding_shape[1] +
                                    BOX_SIZE,
                                    padding_shape[2]:padding_shape[2] +
                                    BOX_SIZE]  # ---将截取的立方体置于nodule_box
                            except:
                                # f = open("log.txt", 'a')
                                # traceback.print_exc(file=f)
                                # f.flush()
                                # f.close()
                                print("annotation error")
                                continue
                            #nodule_box[nodule_box == 0] = -1024  # ---将填充的0设置为-1000,可能有极少数的体素由0=>-1000,不过可以忽略不计
                            self.save_annotations_nodule(
                                nodule_box, patient_uid + "_" + str(index) +
                                "_" + str(s * rt.size + t))
            print("annotation sampling done")

            #get candidate annotation nodule
            candidate_coords = []
            if candsample:
                segimage, segmask, flag = cd.segment_lung_mask(image)
                if segimage is not None:
                    #nodule_matrix, index = cd.candidate_detection(segimage,flag)
                    #cluster_labels = lc.seed_mask_cluster(nodule_matrix, cluster_size=1000)
                    cluster_labels = lc.seed_volume_cluster(
                        image, segmask, eliminate_lower_size=-1)
                    segresult = lc.segment_color_vision(image, cluster_labels)
                    cvm.view_CT(segresult)
                    #lc.cluster_size_vision(cluster_labels)
                    exit()
                    candidate_coords, _ = lc.cluster_centers(cluster_labels)
                    #candidate_coords = lc.cluster_center_filter(image, candidate_coords)
                #the coordination order is [z,y,x]
                print("candidate number:%d" % (len(candidate_coords)))
                #volume_regioned = cv.view_coordinations(image, candidate_coords, window_size=10, reverse=False, slicewise=True, show=False)
                #mt.write_mhd_file(self.vision_path+"/"+patient_uid+"_candidate.mhd", volume_regioned, volume_regioned.shape[::-1])
                for cc in range(len(candidate_coords)):
                    candidate_center = candidate_coords[cc]
                    invalid_loc = False
                    if mt.coord_overflow(candidate_center - window_half,
                                         image.shape) or mt.coord_overflow(
                                             candidate_center + BOX_SIZE -
                                             window_half, image.shape):
                        invalid_loc = True
                        continue
                    for index_search, nodule_diameter_search, v_center_search in v_centers:
                        rpos = v_center_search - candidate_center
                        if abs(rpos[0]) < window_half and abs(
                                rpos[1]
                        ) < window_half and abs(
                                rpos[2]
                        ) < window_half:  #the negative sample is located in the positive location
                            invalid_loc = True
                            break
                    if not invalid_loc:
                        zyx_1 = candidate_center - window_half
                        zyx_2 = candidate_center + BOX_SIZE - window_half
                        nodule_box = np.zeros(
                            [BOX_SIZE, BOX_SIZE, BOX_SIZE],
                            np.int16)  #---nodule_box_size = 45
                        img_crop = image[zyx_1[0]:zyx_2[0], zyx_1[1]:zyx_2[1],
                                         zyx_1[2]:zyx_2[2]]  #---截取立方体
                        img_crop[img_crop <
                                 -1024] = -1024  #---设置窗宽,小于-1000的体素值设置为-1000
                        if img_crop.shape[0] != BOX_SIZE | img_crop.shape[
                                1] != BOX_SIZE | img_crop.shape[2] != BOX_SIZE:
                            print("error in resmapleing shape")
                        try:
                            nodule_box[
                                0:BOX_SIZE, 0:BOX_SIZE, 0:
                                BOX_SIZE] = img_crop  # ---将截取的立方体置于nodule_box
                        except:
                            print("random error")
                            continue
                        #nodule_box[nodule_box == 0] = -1024#---将填充的0设置为-1000,可能有极少数的体素由0=>-1000,不过可以忽略不计
                        self.save_nonnodule(nodule_box,
                                            patient_uid + "_cc_" + str(cc))
                print("candidate sampling done")

            #get random annotation nodule
            if randsample:
                if overbound:
                    augnum = 100
                elif augment:
                    augnum = len(scales) * num_translations
                else:
                    augnum = 1
                if augnum * len(v_centers) > len(candidate_coords):
                    randnum = augnum * len(v_centers) - len(candidate_coords)
                else:
                    randnum = len(candidate_coords)
                for rc in range(
                        randnum
                ):  #the random samples is one-to-one number of nodules
                    #index, nodule_diameter, v_center = v_centers[rc]
                    rand_center = np.array([0, 0, 0])  # 注意是: Z, Y, X
                    invalid_loc = True
                    candidate_overlap = True
                    while invalid_loc:
                        invalid_loc = False
                        candidate_overlap = False
                        for axis in range(rand_center.size):
                            rand_center[axis] = np.random.randint(
                                0, image.shape[axis])
                        if mt.coord_overflow(rand_center - window_half,
                                             image.shape) or mt.coord_overflow(
                                                 rand_center + BOX_SIZE -
                                                 window_half, image.shape):
                            invalid_loc = True
                            continue
                        if 'segmask' in dir() and not (
                                segmask is None
                        ) and not segmask[rand_center[0], rand_center[1],
                                          rand_center[2]]:
                            invalid_loc = True
                            continue
                        for index_search, nodule_diameter_search, v_center_search in v_centers:
                            rpos = v_center_search - rand_center
                            if abs(rpos[0]) < window_half and abs(
                                    rpos[1]
                            ) < window_half and abs(
                                    rpos[2]
                            ) < window_half:  #the negative sample is located in the positive location
                                invalid_loc = True
                                break
                        for candidate_coord in candidate_coords:
                            rpos = candidate_coord - rand_center
                            if abs(rpos[0]) < window_half and abs(
                                    rpos[1]
                            ) < window_half and abs(
                                    rpos[2]
                            ) < window_half:  #the negative sample is located in the pre-extracted candidate locations
                                candidate_overlap = True
                                break
                    if candidate_overlap:
                        continue

                    zyx_1 = rand_center - window_half
                    zyx_2 = rand_center + BOX_SIZE - window_half
                    nodule_box = np.zeros([BOX_SIZE, BOX_SIZE, BOX_SIZE],
                                          np.int16)  #---nodule_box_size = 45
                    img_crop = image[zyx_1[0]:zyx_2[0], zyx_1[1]:zyx_2[1],
                                     zyx_1[2]:zyx_2[2]]  #---截取立方体
                    img_crop[
                        img_crop < -1024] = -1024  #---设置窗宽,小于-1000的体素值设置为-1000
                    if img_crop.shape[0] != BOX_SIZE | img_crop.shape[
                            1] != BOX_SIZE | img_crop.shape[2] != BOX_SIZE:
                        print("error in resmapleing shape")
                    try:
                        nodule_box[
                            0:BOX_SIZE, 0:BOX_SIZE,
                            0:BOX_SIZE] = img_crop  # ---将截取的立方体置于nodule_box
                    except:
                        # f = open("log.txt", 'a')
                        # traceback.print_exc(file=f)
                        # f.flush()
                        # f.close()
                        print("candidate error")
                        continue
                    #nodule_box[nodule_box == 0] = -1024#---将填充的0设置为-1000,可能有极少数的体素由0=>-1000,不过可以忽略不计
                    self.save_nonnodule(nodule_box,
                                        patient_uid + "_rc_" + str(rc))
                print("random sampling done")

            print('Done for this patient!\n\n')
        print('Done for all!')
Пример #3
0
import numpy as np
from toolbox import CTViewer_Multiax as cvm

filename = "./detection_vision/train/LKDS-00005_detresult2.npy"
volimg = np.load(filename)
cvm.view_CT(volimg)