def convert_seg_to_bounding_box_coordinates(data_dict, dim, get_rois_from_seg=False): bb_target = [] roi_masks = [] roi_labels = [] for b in range(data_dict['seg'].shape[0]): p_coords_list = [] p_roi_masks_list = [] p_roi_labels_list = [] if np.sum(data_dict['seg'][b]!=0) > 0: if get_rois_from_seg: clusters, n_cands = lb(data_dict['seg'][b]) data_dict['class_target'][b] = [data_dict['class_target'][b]] * n_cands else: n_cands = int(np.max(data_dict['seg'][b])) rois = np.array([(data_dict['seg'][b] == ii) * 1 for ii in range(1, n_cands + 1)]) # separate clusters and concat # rois = rois[:n_max_gt] #cut clutter out to save memory # print("Rois in transformer", rois.shape, pid[b]) for rix, r in enumerate(rois): if np.sum(r !=0) > 0: #check if the lesion survived data augmentation seg_ixs = np.argwhere(r != 0) coord_list = [np.min(seg_ixs[:, 1])-1, np.min(seg_ixs[:, 2])-1, np.max(seg_ixs[:, 1])+1, np.max(seg_ixs[:, 2])+1] if dim == 3: coord_list.extend([np.min(seg_ixs[:, 3])-1, np.max(seg_ixs[:, 3])+1]) p_coords_list.append(coord_list) p_roi_masks_list.append(r) p_roi_labels_list.append(data_dict['class_target'][b][rix] + 1) #add background class = 0. bb_target.append(np.array(p_coords_list)) roi_masks.append(np.array(p_roi_masks_list)) roi_labels.append(np.array(p_roi_labels_list)) else: bb_target.append([]) roi_masks.append(np.zeros_like(data_dict['seg'][b])[None]) roi_labels.append(np.array([-1])) if get_rois_from_seg: data_dict.pop('class_target', None) return np.array(bb_target), np.array(roi_masks), np.array(roi_labels)
def get_coords(binary_mask, n_components, dim): """ loops over batch to perform connected component analysis on binary input mask. computes box coordiantes around n_components - biggest components (rois). :param binary_mask: (b, y, x, (z)). binary mask for one specific foreground class. :param n_components: int. number of components to extract per batch element and class. :return: coords (b, n, (y1, x1, y2, x2, (z1), (z2)) :return: batch_components (b, n, (y1, x1, y2, x2, (z1), (z2)) """ binary_mask = binary_mask.astype('uint8') batch_coords = [] batch_components = [] for ix, b in enumerate(binary_mask): clusters, n_cands = lb(b) # peforms connected component analysis. uniques, counts = np.unique(clusters, return_counts=True) # only keep n_components largest components. keep_uniques = uniques[1:][np.argsort(counts[1:])[::-1]][:n_components] # separate clusters and concat. p_components = np.array([(clusters == ii) * 1 for ii in keep_uniques]) p_coords = [] if p_components.shape[0] > 0: for roi in p_components: mask_ixs = np.argwhere(roi != 0) # get coordinates around component. roi_coords = [ np.min(mask_ixs[:, 0]) - 1, np.min(mask_ixs[:, 1]) - 1, np.max(mask_ixs[:, 0]) + 1, np.max(mask_ixs[:, 1]) + 1 ] if dim == 3: roi_coords += [ np.min(mask_ixs[:, 2]), np.max(mask_ixs[:, 2]) + 1 ] p_coords.append(roi_coords) p_coords = np.array(p_coords) # clip coords. p_coords[p_coords < 0] = 0 p_coords[:, :4][p_coords[:, :4] > binary_mask.shape[-2]] = binary_mask.shape[-2] if dim == 3: p_coords[:, 4:][p_coords[:, 4:] > binary_mask.shape[-1]] = binary_mask.shape[-1] batch_coords.append(p_coords) batch_components.append(p_components) return batch_coords, batch_components
def get_z_crops(x, ix, min_pix=1500, n_comps=2, rad_crit=20000): final_slices = [] for six in range(x.shape[0]): tx = np.copy(x[six]) < -600 img_center = np.array(tx.shape) / 2 tx = clear_border(tx) clusters, n_cands = lb(tx) count = np.unique(clusters, return_counts=True) keep_comps = np.array([ ii for ii in np.argwhere((count[1] > min_pix)) if ii > 0 ]).astype(int) if len(keep_comps) > n_comps - 1: coms = com(tx, clusters, index=keep_comps) keep_com = [ ix for ix, ii in enumerate(coms[0]) if ((ii[0] - img_center[0])**2 + (ii[1] - img_center[1])**2 < rad_crit) ] keep_comps = keep_comps[keep_com] if len(keep_comps) > n_comps - 1: final_slices.append(six) # print('appending', six) z_min = np.min(final_slices) - 7 z_max = np.max(final_slices) + 7 dist = z_max - z_min if dist >= 151: print('trying again with min pix', min_pix + 500, rad_crit - 500, ix, dist) z_min, z_max = get_z_crops(x, ix, min_pix=min_pix + 500, rad_crit=rad_crit - 500) if dist <= 43: print('trying again with one component', min_pix - 100, rad_crit + 100, ix, dist) z_min, z_max = get_z_crops(x, ix, n_comps=1, min_pix=min_pix - 100, rad_crit=rad_crit + 100) print(z_min, z_max, z_max - z_min, ix) return z_min, z_max
def convert_seg_to_bounding_box_coordinates(seg, class_target, pid, dim, n_max_gt=3): bb_target = np.zeros( (seg.shape[0], n_max_gt, dim * 2)) #for whole batch or single patient? roi_shape = [seg.shape[0], n_max_gt, seg.shape[2], seg.shape[3]] if dim == 3: roi_shape.append(seg.shape[4]) roi_masks = np.zeros(roi_shape) roi_class_ids = np.zeros((seg.shape[0], n_max_gt, 1)) for b in range(seg.shape[0]): if np.sum(seg != 0) > 0: clusters, n_cands = lb(seg[b]) rois = np.array([ (clusters == ii) * 1 for ii in range(1, n_cands + 1) ]) # separate clusters and concat rois = rois[:n_max_gt] #cut clutter out to save memory # print("Rois in transformer", rois.shape, pid[b]) for rix, r in enumerate(rois): seg_ixs = np.argwhere(r != 0) coord_list = [ np.min(seg_ixs[:, 2]) - 1, np.min(seg_ixs[:, 1]) - 1, np.max(seg_ixs[:, 2]) + 1, np.max(seg_ixs[:, 1]) + 1 ] if dim == 3: coord_list.extend( [np.min(seg_ixs[:, 3]) - 1, np.max(seg_ixs[:, 3]) + 1]) bb_target[b, rix] = coord_list roi_masks[b, rix] = r roi_class_ids[ b, rix] = class_target[b] + 1 # add background class # print("CHECK BBTARGET", bb_target[b], roi_masks[b].shape, roi_class_ids[b], pid[b]) else: print("fail: bb kicked out of image by data augmentation", np.sum(seg != 0), pid[b], class_target) return bb_target, roi_masks, roi_class_ids
def convert_seg_to_bounding_box_coordinates(seg, class_target, pid, dim): bb_target = [] roi_masks = [] roi_class_ids = [] for b in range(seg.shape[0]): p_coords_list = [] p_roi_masks_list = [] p_roi_class_ids_list = [] if np.sum(seg != 0) > 0: clusters, n_cands = lb(seg[b]) rois = np.array([ (clusters == ii) * 1 for ii in range(1, n_cands + 1) ]) # separate clusters and concat # rois = rois[:n_max_gt] #cut clutter out to save memory # print("Rois in transformer", rois.shape, pid[b]) for rix, r in enumerate(rois): seg_ixs = np.argwhere(r != 0) coord_list = [ np.min(seg_ixs[:, 1]) - 1, np.min(seg_ixs[:, 2]) - 1, np.max(seg_ixs[:, 1]) + 1, np.max(seg_ixs[:, 2]) + 1 ] if dim == 3: coord_list.extend( [np.min(seg_ixs[:, 3]) - 1, np.max(seg_ixs[:, 3]) + 1]) p_coords_list.append(coord_list) p_roi_masks_list.append(r) p_roi_class_ids_list.append(class_target[b] + 1) bb_target.append(np.array(p_coords_list)) roi_masks.append(np.array(p_roi_masks_list)) roi_class_ids.append(np.array(p_roi_class_ids_list)) # print("CHECK BBTARGET", bb_target[b], roi_masks[b].shape, roi_class_ids[b], pid[b]) elif class_target[b] > -1: print("fail: bb kicked out of image by data augmentation", np.sum(seg != 0), pid[b], class_target) return bb_target, roi_masks, roi_class_ids
def convert_seg_to_bounding_box_coordinates(data_dict, dim, get_rois_from_seg_flag=False, class_specific_seg_flag=False): ''' :param data_dict: :param dim: :param get_rois_from_seg: :return: coords (y1, x1, y2, x2) ''' bb_target = [] roi_masks = [] roi_labels = [] out_seg = np.copy(data_dict['seg']) for b in range(data_dict['seg'].shape[0]): p_coords_list = [] p_roi_masks_list = [] p_roi_labels_list = [] if np.sum(data_dict['seg'][b] != 0) > 0: if get_rois_from_seg_flag: clusters, n_cands = lb(data_dict['seg'][b]) data_dict['class_target'][b] = [data_dict['class_target'][b] ] * n_cands else: n_cands = int(np.max(data_dict['seg'][b])) clusters = data_dict['seg'][b] rois = np.array([ (clusters == ii) * 1 for ii in range(1, n_cands + 1) ]) # separate clusters and concat for rix, r in enumerate(rois): if np.sum( r != 0 ) > 0: #check if the lesion survived data augmentation seg_ixs = np.argwhere(r != 0) coord_list = [ np.min(seg_ixs[:, 1]) - 1, np.min(seg_ixs[:, 2]) - 1, np.max(seg_ixs[:, 1]) + 1, np.max(seg_ixs[:, 2]) + 1 ] if dim == 3: coord_list.extend([ np.min(seg_ixs[:, 3]) - 1, np.max(seg_ixs[:, 3]) + 1 ]) p_coords_list.append(coord_list) p_roi_masks_list.append(r) # add background class = 0. rix is a patient wide index of lesions. since 'class_target' is # also patient wide, this assignment is not dependent on patch occurrances. p_roi_labels_list.append( data_dict['class_target'][b][rix] + 1) if class_specific_seg_flag: out_seg[b][data_dict['seg'][b] == rix + 1] = data_dict['class_target'][b][rix] + 1 if not class_specific_seg_flag: out_seg[b][data_dict['seg'][b] > 0] = 1 bb_target.append(np.array(p_coords_list)) roi_masks.append(np.array(p_roi_masks_list)) roi_labels.append(np.array(p_roi_labels_list)) else: bb_target.append([]) roi_masks.append(np.zeros_like(data_dict['seg'][b])[None]) roi_labels.append(np.array([-1])) if get_rois_from_seg_flag: data_dict.pop('class_target', None) data_dict['bb_target'] = np.array(bb_target) data_dict['roi_masks'] = np.array(roi_masks) data_dict['roi_labels'] = np.array(roi_labels) data_dict['seg'] = out_seg return data_dict
def convert_seg_to_bounding_box_coordinates(data_dict, dim, roi_item_keys, get_rois_from_seg=False, class_specific_seg=False): '''adapted from batchgenerators :param data_dict: seg: segmentation with labels indicating roi_count (get_rois_from_seg=False) or classes (get_rois_from_seg=True), class_targets: list where list index corresponds to roi id (roi_count) :param dim: :param roi_item_keys: keys of the roi-wise items in data_dict to process :param n_rg_feats: nr of regression vector features :param get_rois_from_seg: :return: coords (y1,x1,y2,x2 (,z1,z2)) where the segmentation GT is framed by +1 voxel, i.e., for an object with z-extensions z1=0 through z2=5, bbox target coords will be z1=-1, z2=6. (analogically for x,y). data_dict['roi_masks']: (b, n(b), c, h(n), w(n) (z(n))) list like roi_labels but with arrays (masks) inplace of integers. c==1 if segmentation not one-hot encoded. ''' bb_target = [] roi_masks = [] roi_items = {name: [] for name in roi_item_keys} out_seg = np.copy(data_dict['seg']) for b in range(data_dict['seg'].shape[0]): p_coords_list = [] #p for patient? p_roi_masks_list = [] p_roi_items_lists = {name: [] for name in roi_item_keys} if np.sum(data_dict['seg'][b] != 0) > 0: if get_rois_from_seg: clusters, n_cands = lb(data_dict['seg'][b]) data_dict['class_targets'][b] = [ data_dict['class_targets'][b] ] * n_cands else: n_cands = int(np.max(data_dict['seg'][b])) rois = np.array([(data_dict['seg'][b] == ii) * 1 for ii in range(1, n_cands + 1)], dtype='uint8') # separate clusters for rix, r in enumerate(rois): if np.sum( r != 0 ) > 0: # check if the roi survived slicing (3D->2D) and data augmentation (cropping etc.) seg_ixs = np.argwhere(r != 0) coord_list = [ np.min(seg_ixs[:, 1]) - 1, np.min(seg_ixs[:, 2]) - 1, np.max(seg_ixs[:, 1]) + 1, np.max(seg_ixs[:, 2]) + 1 ] if dim == 3: coord_list.extend([ np.min(seg_ixs[:, 3]) - 1, np.max(seg_ixs[:, 3]) + 1 ]) p_coords_list.append(coord_list) p_roi_masks_list.append(r) # add background class = 0. rix is a patient wide index of lesions. since 'class_targets' is # also patient wide, this assignment is not dependent on patch occurrences. for name in roi_item_keys: p_roi_items_lists[name].append(data_dict[name][b][rix]) assert data_dict["class_targets"][b][ rix] >= 1, "convertsegtobbox produced bg roi w cl targ {} and unique roi seg {}".format( data_dict["class_targets"][b][rix], np.unique(r)) if class_specific_seg: out_seg[b][data_dict['seg'][b] == rix + 1] = data_dict['class_targets'][b][rix] if not class_specific_seg: out_seg[b][data_dict['seg'][b] > 0] = 1 bb_target.append(np.array(p_coords_list)) roi_masks.append(np.array(p_roi_masks_list)) for name in roi_item_keys: roi_items[name].append(np.array(p_roi_items_lists[name])) else: bb_target.append([]) roi_masks.append( np.zeros_like(data_dict['seg'][b], dtype='uint8')[None]) for name in roi_item_keys: roi_items[name].append(np.array([])) if get_rois_from_seg: data_dict.pop('class_targets', None) data_dict['bb_target'] = np.array(bb_target) data_dict['roi_masks'] = np.array(roi_masks) data_dict['seg'] = out_seg for name in roi_item_keys: data_dict[name] = np.array(roi_items[name]) return data_dict
def convert_seg_to_bounding_box_coordinates(data_dict, dim, get_rois_from_seg_flag=False, class_specific_seg_flag=False): ''' This function generates bounding box annotations from given pixel-wise annotations. :param data_dict: Input data dictionary as returned by the batch generator. :param dim: Dimension in which the model operates (2 or 3). :param get_rois_from_seg: Flag specifying one of the following scenarios: 1. A label map with individual ROIs identified by increasing label values, accompanied by a vector containing in each position the class target for the lesion with the corresponding label (set flag to False) 2. A binary label map. There is only one foreground class and single lesions are not identified. All lesions have the same class target (foreground). In this case the Dataloader runs a Connected Component Labelling algorithm to create processable lesion - class target pairs on the fly (set flag to True). :param class_specific_seg_flag: if True, returns the pixelwise-annotations in class specific manner, e.g. a multi-class label map. If False, returns a binary annotation map (only foreground vs. background). :return: data_dict: same as input, with additional keys: - 'bb_target': bounding box coordinates (b, n_boxes, (y1, x1, y2, x2, (z1), (z2))) - 'roi_labels': corresponding class labels for each box (b, n_boxes, class_label) - 'roi_masks': corresponding binary segmentation mask for each lesion (box). Only used in Mask RCNN. (b, n_boxes, y, x, (z)) - 'seg': now label map (see class_specific_seg_flag) ''' bb_target = [] roi_masks = [] roi_labels = [] out_seg = np.copy(data_dict['seg']) for b in range(data_dict['seg'].shape[0]): p_coords_list = [] p_roi_masks_list = [] p_roi_labels_list = [] if np.sum(data_dict['seg'][b]!=0) > 0: if get_rois_from_seg_flag: clusters, n_cands = lb(data_dict['seg'][b]) data_dict['class_target'][b] = [data_dict['class_target'][b]] * n_cands else: n_cands = int(np.max(data_dict['seg'][b])) clusters = data_dict['seg'][b] rois = np.array([(clusters == ii) * 1 for ii in range(1, n_cands + 1)]) # separate clusters and concat for rix, r in enumerate(rois): if np.sum(r !=0) > 0: #check if the lesion survived data augmentation seg_ixs = np.argwhere(r != 0) coord_list = [np.min(seg_ixs[:, 1])-1, np.min(seg_ixs[:, 2])-1, np.max(seg_ixs[:, 1])+1, np.max(seg_ixs[:, 2])+1] if dim == 3: coord_list.extend([np.min(seg_ixs[:, 3])-1, np.max(seg_ixs[:, 3])+1]) p_coords_list.append(coord_list) p_roi_masks_list.append(r) # add background class = 0. rix is a patient wide index of lesions. since 'class_target' is # also patient wide, this assignment is not dependent on patch occurrances. p_roi_labels_list.append(data_dict['class_target'][b][rix] + 1) if class_specific_seg_flag: out_seg[b][data_dict['seg'][b] == rix + 1] = data_dict['class_target'][b][rix] + 1 if not class_specific_seg_flag: out_seg[b][data_dict['seg'][b] > 0] = 1 bb_target.append(np.array(p_coords_list)) roi_masks.append(np.array(p_roi_masks_list).astype('uint8')) roi_labels.append(np.array(p_roi_labels_list)) else: bb_target.append([]) roi_masks.append(np.zeros_like(data_dict['seg'][b])[None]) roi_labels.append(np.array([-1])) if get_rois_from_seg_flag: data_dict.pop('class_target', None) data_dict['bb_target'] = np.array(bb_target) data_dict['roi_masks'] = np.array(roi_masks) data_dict['class_target'] = np.array(roi_labels) data_dict['seg'] = out_seg return data_dict
def _convert_seg_to_bounding_box_coordinates( self, data_dict, dim, margin=None, get_rois_from_seg_flag=True, class_specific_seg_flag=False): ''' :param data_dict: :param dim: :param get_rois_from_seg: :return: coords (x_center, y_center, width, height) ''' bb_target = [] roi_masks = [] roi_labels = [] out_seg = np.copy(data_dict['seg']) for b in range(data_dict['seg'].shape[0]): p_coords_list = [] p_roi_masks_list = [] p_roi_labels_list = [] if np.sum(data_dict['seg'][b] != 0) > 0: if get_rois_from_seg_flag: clusters, n_cands = lb(data_dict['seg'][b]) #data_dict['label'][b] = [data_dict['label'][b]] * n_cands else: n_cands = int(np.max(data_dict['seg'][b])) clusters = data_dict['seg'][b] rois = np.array([ (clusters == ii) * 1 for ii in range(1, n_cands + 1) ]) # separate clusters and concat for rix, r in enumerate(rois): if np.sum( r != 0 ) > 0: # check if the lesion survived data augmentation seg_ixs = np.argwhere(r != 0) coord_list = [ np.min(seg_ixs[:, 1]) - 1, np.min(seg_ixs[:, 2]) - 1, np.max(seg_ixs[:, 1]) + 1, np.max(seg_ixs[:, 2]) + 1 ] if dim == 3: coord_list.extend([ np.min(seg_ixs[:, 3]) - 1, np.max(seg_ixs[:, 3]) + 1 ]) p_coords_list.append(coord_list) p_roi_masks_list.append(r) # add background class = 0. rix is a patient wide index of lesions. since 'class_target' is # also patient wide, this assignment is not dependent on patch occurrances. #p_roi_labels_list.append(data_dict['label'][b][rix] + 1) p_roi_labels_list.append(data_dict['label'][b]) if class_specific_seg_flag: out_seg[b][data_dict['seg'][b] == rix + 1] = \ data_dict['label'][b][rix] + 1 if not class_specific_seg_flag: out_seg[b][data_dict['seg'][b] > 0] = 1 bb_target.append(np.array(p_coords_list)) roi_masks.append(np.array(p_roi_masks_list).astype('uint8')) roi_labels.append(np.array(p_roi_labels_list)) else: bb_target.append(np.array([[0, 0, 1, 1]])) roi_masks.append(np.zeros_like(data_dict['seg'][b])[None]) roi_labels.append(np.array([0])) # if get_rois_from_seg_flag: # data_dict.pop('label', None) # add margin if desired if margin is not None: if margin < 0 or margin > 1: ValueError("Margin must be a value in [0,1]!") for i in range(len(bb_target)): #bb_target = np.asarray(bb_target) height = bb_target[i][:, 2] - bb_target[i][:, 0] width = bb_target[i][:, 3] - bb_target[i][:, 1] offset = np.asarray( [np.floor(height * margin), np.floor(width * margin)]) # make sure bounds are valid bb_target[i][:, 0] = np.clip( np.floor(bb_target[i][:, 0] - height * margin * 0.5), 0, data_dict["seg"].shape[2] - 1) bb_target[i][:, 1] = np.clip( np.floor(bb_target[i][:, 1] - width * margin * 0.5), 0, data_dict["seg"].shape[3] - 1) bb_target[i][:, 2] = np.clip( np.floor(bb_target[i][:, 2] + height * margin * 0.5), 0, data_dict["seg"].shape[2] - 1) bb_target[i][:, 3] = np.clip( np.floor(bb_target[i][:, 3] + width * margin * 0.5), 0, data_dict["seg"].shape[3] - 1) # if used on cropped masks, small overlapping bbox might appear # that should be removed # reference = bb_target[0] # num_bbox_params = len(bb_target) # for i in range(num_bbox_params): # area = (bb_target[i][3] -bb_target[i][1]) * \ # (bb_target[i][2] - bb_target[i][0]) # if area > (reference[3] - reference[1]) * \ # (reference[2] - reference[0]): # reference = bb_target[i] # # i = 0 # while i < num_bbox_params: # if (bb_target[i][0] > reference[0] and \ # bb_target[i][1] > reference[1]) or \ # (bb_target[i][2] < reference[2] and \ # bb_target[i][3] < reference[3]): # bb_target.pop(i) # num_bbox_params -= 1 # i = 0 # continue # i += 1 # # convert into numpy and save in [x_center, y_center, width ,hight] format #bb_target = np.asarray(bb_target) #print(bb_target) #tmp = np.copy(bb_target).astype(np.float32) for i in range(len(bb_target)): size = bb_target[i][:, 2:] - bb_target[i][:, 0:2] center = np.floor(bb_target[i][:, 0:2] + size / 2) bb_target[i][:, 0] = center[:, 1] bb_target[i][:, 1] = center[:, 0] bb_target[i][:, 2] = size[:, 1] bb_target[i][:, 3] = size[:, 0] bb_target[i] = bb_target[i].astype(np.float32) data_dict['bboxes'] = np.array(bb_target) data_dict['roi_masks'] = np.array(roi_masks) data_dict['roi_labels'] = np.array(roi_labels) data_dict['seg'] = out_seg return data_dict
def report(self, volume=None, threshold=None, out_file='ClusterReport.csv'): # To take care if user has given a 4D contrast if volume != None: self.volume = volume if len(self.brain.shape) > 3: brain = np.array(self.brain[:, :, :, self.volume]) else: brain = np.array(self.brain) if threshold != None: self.thresh = threshold # Total number of brain voxels num_brain_voxels = len(np.where(brain != 0)[0]) """ Brain_zero is used later to calculate the center of gravity of the cluster voxels overlapping with atlas voxels """ brain_zero = np.zeros(brain.shape) # Apply thresholding brain[(brain < self.thresh) & (brain > -self.thresh)] = 0 # Find clusters clusters, num_clusters = lb(brain) df_report = pd.DataFrame() # List to store cluster size information full_cluster_voxels_percentage_list = [] atlas_path = self.atlas_dict['atlas_path'] atlas_labels_path = self.atlas_dict['atlas_labels_path'] atlas_xml_zero_start_index = \ self.atlas_dict['atlas_xml_zero_start_index'] atlas_obj = au.queryAtlas( atlas_path, atlas_labels_path, atlas_xml_zero_start_index=atlas_xml_zero_start_index) for cluster_number in range(1, num_clusters + 1): # Coordinates that are present in cluster given by cluster_number cluster_indices = np.where(clusters == cluster_number) # Number of voxels belonging to the cluster -> cluster_number num_cluster_voxels = len(cluster_indices[0]) # Percentage of total brain voxels in a cluster full_cluster_voxels_percentage = \ num_cluster_voxels * 100 / num_brain_voxels # To create a list to be added to dataframe full_cluster_voxels_percentage_list.append( full_cluster_voxels_percentage) # Find the atlas labels/regions that the cluster spans atlas_regions_labels = np.unique(self.atlas[cluster_indices]) # print(atlas_regions_labels) # iterate over all the labes/regions for label in atlas_regions_labels: # Lists to be used for dataFrame creation cog_value_list = [] number_overlapping_cluster_voxels_list = [] overlapping_cluster_voxels_percentage_list = [] MNI_cog_list = [] cog_region_name_list = [] cog_unweighted_value_list = [] cog_weighted_value_list = [] cog_weighted_value_list = [] MNI_cog_unweighted_list = [] MNI_cog_weighted_list = [] cog_region_name_weighted_list = [] cog_region_name_unweighted_list = [] # Find all the coordinates of the labels # Skipping the Label 0 if label == 0: continue atlas_label_indices = np.where(self.atlas == label) """ Find the cluster coordinates overlapping the label/region under consideration """ # Changing the form of cluster indices to (x,y,z) tuple cluster_indices_zip = zip(cluster_indices[0], cluster_indices[1], cluster_indices[2]) cluster_indices_tuple_list = list(cluster_indices_zip) # Changing the form of atlas indices to (x,y,z) tuple atlas_label_indices_zip = \ zip(atlas_label_indices[0], atlas_label_indices[1], atlas_label_indices[2]) atlas_label_indices_tuple_list = list(atlas_label_indices_zip) # Number of voxels belonging to the atlas region num_atlas_region_voxels = len(atlas_label_indices_tuple_list) # 1. Find intersecion of the above two lists overlapping_coordinates = \ list(set(cluster_indices_tuple_list).intersection( set(atlas_label_indices_tuple_list))) """ 2. Make an brain array and initialize the overlapping coordinates with the values from brain # Transform coordinates list to list of indices as returned by np.where() # Ref: https://stackoverflow.com/questions/12974474/ how-to-unzip-a-list-of-tuples-into-individual-lists """ overlapping_indices_zip = zip(*overlapping_coordinates) overlapping_indices_tuple_list = list(overlapping_indices_zip) # Number of voxels in the overlap of cluster and atlas region number_overlapping_cluster_voxels = \ len(overlapping_coordinates) # Creating list to be added to dataframe number_overlapping_cluster_voxels_list.append( number_overlapping_cluster_voxels) #Percentage of voxels in the overlap of cluster and atlas region overlapping_cluster_voxels_percentage = \ number_overlapping_cluster_voxels*100 / num_atlas_region_voxels # Creating list to be added to dataframe overlapping_cluster_voxels_percentage_list.append( overlapping_cluster_voxels_percentage) # Assigning the overlap to the empty brain to find COG later brain_zero[overlapping_indices_tuple_list] = \ brain[overlapping_indices_tuple_list] """ 3. Then use the already created functions to do the following: a. Find the representative coordinate of the intersection Create a dummy atlas (roi_mask) with just one region and label that as 1 Ref: https://stackoverflow.com/questions/32322281/ numpy-matrix-binarization-using-only-one-expression """ roi_mask_for_unweighted_cog = np.where(brain_zero != 0, 1, 0) roi_mask_for_weighted_cog = brain_zero cog_unweighted = com(roi_mask_for_unweighted_cog) cog_weighted = com(roi_mask_for_weighted_cog) # convert the coordinates to int (math.floor) cog_unweighted = tuple(map(int, cog_unweighted)) cog_weighted = tuple(map(int, cog_weighted)) """ If the COG lies outside the overlapping coordinates then find the coordinate that lies on the overlapping region and is closest to the COG. """ if not roi_mask_for_unweighted_cog[cog_unweighted]: cog_unweighted = \ tuple(self.getNearestVoxel(roi_mask_for_unweighted_cog, cog_unweighted)) if not roi_mask_for_weighted_cog[cog_weighted]: cog_weighted= \ tuple(self.getNearestVoxel(roi_mask_for_weighted_cog, cog_weighted)) # print('COM Unweighted', cog_unweighted) # print('COM Weighted', cog_weighted) # Finding the values at the cluster representative coordinates cog_unweighted_value = brain[cog_unweighted] cog_weighted_value = brain[cog_weighted] # Lists to be added to dataframe cog_unweighted_value_list.append(cog_unweighted_value) cog_weighted_value_list.append(cog_weighted_value) # b. Convert the cartesian coordinates to MNI MNI_cog_unweighted = self._XYZ2MNI(cog_unweighted) MNI_cog_weighted = self._XYZ2MNI(cog_weighted) # Convert the list of coordinates to string to get rid of: # Exception: Data must be 1-dimensional str_cog_unweighted = '' for i in MNI_cog_unweighted: str_cog_unweighted = str_cog_unweighted + ' ' + str(i) str_cog_weighted = '' for i in MNI_cog_weighted: str_cog_weighted = str_cog_weighted + ' ' + str(i) # Lists to be added to dataframe MNI_cog_unweighted_list.append(str_cog_unweighted) MNI_cog_weighted_list.append(str_cog_weighted) # c. Report the name of the region # Names of the regions of COG cog_region_name_weighted = \ atlas_obj.getAtlasRegions(MNI_cog_weighted)[1] cog_region_name_unweighted = \ atlas_obj.getAtlasRegions(MNI_cog_unweighted)[1] # print('Region name weighted COG: ',cog_region_name_weighted) # # print('Region name unweighter COG: ',cog_region_name_unweighted) # List created to be added to dataframe cog_region_name_weighted_list.append(cog_region_name_weighted) cog_region_name_unweighted_list.append( cog_region_name_unweighted) # To choose from weighted and unweighted COG options WEIGHTED = True if WEIGHTED: MNI_cog_list = MNI_cog_weighted_list cog_region_name_list = cog_region_name_weighted_list cog_value_list = cog_weighted_value_list else: pass # Sort the Regions bsed on cog value # Get the indices of elements after they are sorted sorted_indices = np.argsort(cog_value_list) # Sort the lists according to the above sorted_indices cog_value_list = np.array(cog_value_list)[sorted_indices] number_overlapping_cluster_voxels_list = \ np.array(number_overlapping_cluster_voxels_list)[sorted_indices] overlapping_cluster_voxels_percentage_list = \ np.array(overlapping_cluster_voxels_percentage_list)[sorted_indices] MNI_cog_list = np.array(MNI_cog_list)[sorted_indices] cog_region_name_list = np.array( cog_region_name_list)[sorted_indices] """ TODO: Convert MNI coordinates from list to string (x,y,z) The next error that I will have to deal with is unequal length arrays. For that append each list with spaces. Then care about ordering the dictionary. """ # Creating a dictionary to create dataframe df_dict = OrderedDict() df_dict['Cluster Number'] = [cluster_number] df_dict['Max Value'] = cog_value_list df_dict['Num Voxels'] = number_overlapping_cluster_voxels_list df_dict['Percentage of Voxel' ] = \ overlapping_cluster_voxels_percentage_list df_dict['MNI Coordinates'] = MNI_cog_list df_dict['Region Name'] = cog_region_name_list df = pd.DataFrame(df_dict) df_report = df_report.append(df) # Empty the lists to be filled again cog_value_list = [] number_overlapping_cluster_voxels_list = [] overlapping_cluster_voxels_percentage_list = [] MNI_cog_list = [] cog_region_name_list = [] """ TODO: The order of the columns is not maintained Test again about the validity of results. The number of voxels is very low. Check it! DONE: Store each of the coordinates in cog_list, names in name_list, values in value_list, number of voxels etc. Find the max of the value_list and corresponding name in name_list and also calculate other details and store them in lists. Create a distionary with all the above created lists. Create a empty data frame and add the above created dictionary in it. ATLAS NAME SIZE (MM) In one For loop create the details about cluster1 and store them in lists as said above. As said above, add these lists in a dictionary. Then this dictionary is added to a dataframe. The table should look like the following: ROI1 Cluster1 MaxValue COG Region Total_#_voxels %_voxels MaxValue COG Region #_voxels %_voxles_overlap Value2 COG Region #_voxels %_voxles_overlap Value3 COG Region #_voxels %_voxles_overlap . . . . . . Cluster2 MaxValue COG Region Total_#_voxels MaxValue COG Region #_voxels %_voxles_overlap Value2 COG Region #_voxels %_voxles_overlap Value3 COG Region #_voxels %_voxles_overlap . . . . . . """ pass brain_zero.fill(0) # d. Number and Percentage of voxels overlapping the region # e. Peak coordinate of the cluster df_report.to_csv(out_file, index=False) return os.path.abspath(out_file), df_report
def process_video(arg): svc, X_scaler = load_svc_model() cap = cv2.VideoCapture(arg.input) if arg.output: output_fn = arg.output fps = 30 size = (1280, 720) # cv2.cv.CV_FOURCC('D', 'I', 'V', 'X') = 0x58564944 # cv2.cv.CV_FOURCC('X', '2', '6', '4') = 0x34363258 # cv2.cv.CV_FOURCC('H', '2', '6', '4') = 0x34363248 out = cv2.VideoWriter(output_fn, 0x34363258, fps, size, 1) else: out = None skip_index = 0 frame_index = 0 frame_bbox_list = [] while cap: ret, frame = cap.read() if not ret: break frame_index += 1 if frame_index < skip_index: continue frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # multi-scale cars detect found_win_list = [] ystart, ystop = 400, 500 win_list = find_cars(frame, ystart, ystop, 1.0, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins) found_win_list.extend(win_list) ystart, ystop = 400, 600 win_list = find_cars(frame, ystart, ystop, 1.5, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins) found_win_list.extend(win_list) ystart, ystop = 400, 600 win_list = find_cars(frame, ystart, ystop, 2.0, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins) found_win_list.extend(win_list) ystart, ystop = 400, 650 win_list = find_cars(frame, ystart, ystop, 2.5, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins) found_win_list.extend(win_list) ystart, ystop = 400, 700 win_list = find_cars(frame, ystart, ystop, 3.0, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins) found_win_list.extend(win_list) ystart, ystop = 500, 700 win_list = find_cars(frame, ystart, ystop, 4.0, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins) found_win_list.extend(win_list) ystart, ystop = 600, 700 win_list = find_cars(frame, ystart, ystop, 6.0, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins) found_win_list.extend(win_list) out_img = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) heatmap = np.zeros_like(out_img[:, :, 0], dtype=np.uint8) heatmap[heatmap < 2] = 0 # draw heatmap add_heat(heatmap, found_win_list) # Apply threshold to help remove false positives heat = apply_threshold(heatmap, 1) # Visualize the heatmap when displaying heatmap = np.clip(heat, 0, 255) # Find final boxes from heatmap using label function labels = lb(heatmap) bbox_list = draw_labeled_bboxes(out_img, labels, frame_bbox_list) frame_bbox_list.append(bbox_list) if len(frame_bbox_list) > 4: frame_bbox_list.pop(0) cv2.imshow("output", out_img) key = cv2.waitKey(10) & 0xff if key in [ord('q'), 23]: break if out: out.write(out_img)
def extract(self, volume=None, threshold=None): # To take care if user has given a 4D contrast if volume != None: self.volume = volume if len(self.brain.shape) > 3: brain = np.array(self.brain[:, :, :, self.volume]) else: brain = np.array(self.brain) if threshold != None: self.thresh = threshold # Total number of brain voxels num_brain_voxels = len(np.where(brain != 0)[0]) """ Brain_zero is used later to calculate the center of gravity of the cluster voxels overlapping with atlas voxels """ brain_zero = np.zeros(brain.shape) # Apply thresholding brain[(brain < self.thresh) & (brain > -self.thresh)] = 0 # Find clusters clusters, num_clusters = lb(brain) # print('######### Num of clusters: ',num_clusters) df_report = pd.DataFrame() # List to store cluster size information full_cluster_voxels_percentage_list = [] # c. Report the name of the region atlas_path = self.atlas_dict['atlas_path'] atlas_labels_path = self.atlas_dict['atlas_labels_path'] atlas_xml_zero_start_index = \ self.atlas_dict['atlas_xml_zero_start_index'] aal_atlas_obj = au.queryAtlas( atlas_path, atlas_labels_path, atlas_xml_zero_start_index=atlas_xml_zero_start_index) for cluster_number in range(1, num_clusters + 1): # Coordinates that are present in cluster given by cluster_number cluster_indices = np.where(clusters == cluster_number) # Number of voxels belonging to the cluster -> cluster_number num_cluster_voxels = len(cluster_indices[0]) # Percentage of total brain voxels in a cluster full_cluster_voxels_percentage = \ num_cluster_voxels * 100 / num_brain_voxels # To create a list to be added to dataframe full_cluster_voxels_percentage_list.append( full_cluster_voxels_percentage) # Find the atlas labels/regions that the cluster spans atlas_regions_labels = np.unique(self.atlas[cluster_indices]) # print(atlas_regions_labels) # iterate over all the labes/regions for label in atlas_regions_labels: # Lists to be used for dataFrame creation cog_value_list = [] number_overlapping_cluster_voxels_list = [] overlapping_cluster_voxels_percentage_list = [] MNI_cog_list = [] cog_region_name_list = [] cog_unweighted_value_list = [] cog_weighted_value_list = [] cog_weighted_value_list = [] MNI_cog_unweighted_list = [] MNI_cog_weighted_list = [] cog_region_name_weighted_list = [] cog_region_name_unweighted_list = [] # Find all the coordinates of the labels # Skipping the Label 0 if label == 0: continue atlas_label_indices = np.where(self.atlas == label) """ Find the cluster coordinates overlapping the label/region under consideration """ # Changing the form of cluster indices to (x,y,z) tuple cluster_indices_zip = zip(cluster_indices[0], cluster_indices[1], cluster_indices[2]) cluster_indices_tuple_list = list(cluster_indices_zip) # Changing the form of atlas indices to (x,y,z) tuple atlas_label_indices_zip = \ zip(atlas_label_indices[0], atlas_label_indices[1], atlas_label_indices[2]) atlas_label_indices_tuple_list = list(atlas_label_indices_zip) # Number of voxels belonging to the atlas region num_atlas_region_voxels = len(atlas_label_indices_tuple_list) # 1. Find intersecion of the above two lists overlapping_coordinates = \ list(set(cluster_indices_tuple_list).intersection( set(atlas_label_indices_tuple_list))) """ 2. Make an brain array and initialize the overlapping coordinates with the values from brain # Transform coordinates list to list of indices as returned by np.where() # Ref: https://stackoverflow.com/questions/12974474/ how-to-unzip-a-list-of-tuples-into-individual-lists """ overlapping_indices_zip = zip(*overlapping_coordinates) overlapping_indices_tuple_list = list(overlapping_indices_zip) # # # Number of voxels in the overlap of cluster and atlas region # number_overlapping_cluster_voxels = \ # len(overlapping_coordinates) # # # Creating list to be added to dataframe # number_overlapping_cluster_voxels_list.append( # number_overlapping_cluster_voxels) # # #Percentage of voxels in the overlap of cluster and atlas region # overlapping_cluster_voxels_percentage = \ # number_overlapping_cluster_voxels*100 / num_atlas_region_voxels # # # Creating list to be added to dataframe # overlapping_cluster_voxels_percentage_list.append( # overlapping_cluster_voxels_percentage) # # # Assigning the overlap to the empty brain to find COG later # brain_zero[overlapping_indices_tuple_list] = \ # brain[overlapping_indices_tuple_list] # # """ # 3. Then use the already created functions to do the following: # a. Find the representative coordinate of the intersection # # Create a dummy atlas (roi_mask) with just one region and label # that as 1 # # Ref: https://stackoverflow.com/questions/32322281/ # numpy-matrix-binarization-using-only-one-expression # """ # # roi_mask_for_unweighted_cog = np.where(brain_zero != 0, 1, 0) # roi_mask_for_weighted_cog = brain_zero # # # cog_unweighted = com(roi_mask_for_unweighted_cog) # cog_weighted = com(roi_mask_for_weighted_cog) # # # convert the coordinates to int (math.floor) # cog_unweighted = tuple(map(int, cog_unweighted)) # cog_weighted = tuple(map(int, cog_weighted)) # # """ # If the COG lies outside the overlapping coordinates then find # the coordinate that lies on the overlapping region and is # closest to the COG. # """ # # if not roi_mask_for_unweighted_cog[cog_unweighted]: # cog_unweighted = \ # tuple(self.getNearestVoxel(roi_mask_for_unweighted_cog, # cog_unweighted)) # # if not roi_mask_for_weighted_cog[cog_weighted]: # cog_weighted= \ # tuple(self.getNearestVoxel(roi_mask_for_weighted_cog, # cog_weighted)) # # print('COM Unweighted', cog_unweighted) # print('COM Weighted', cog_weighted) # # # Finding the values at the cluster representative coordinates # cog_unweighted_value = brain[cog_unweighted] # cog_weighted_value = brain[cog_weighted] # # # Lists to be added to dataframe # cog_unweighted_value_list.append(cog_unweighted_value) # cog_weighted_value_list.append(cog_weighted_value) # # # b. Convert the cartesian coordinates to MNI # MNI_cog_unweighted = self._XYZ2MNI(cog_unweighted) # MNI_cog_weighted = self._XYZ2MNI(cog_weighted) # # # Convert the list of coordinates to string to get rid of: # # Exception: Data must be 1-dimensional # # # str_cog_unweighted = '' # for i in MNI_cog_unweighted: # str_cog_unweighted = str_cog_unweighted + ' ' + str(i) # # str_cog_weighted = '' # for i in MNI_cog_weighted: # str_cog_weighted = str_cog_weighted + ' ' + str(i) # # # # # Lists to be added to dataframe # MNI_cog_unweighted_list.append(str_cog_unweighted) # MNI_cog_weighted_list.append(str_cog_weighted) # # # # c. Report the name of the region # # # # # Names of the regions of COG # cog_region_name_weighted = \ # aal_atlas_obj.getAtlasRegions(MNI_cog_weighted)[1] # cog_region_name_unweighted = \ # aal_atlas_obj.getAtlasRegions(MNI_cog_unweighted)[1] # # print('Region name weighted COG: ',cog_region_name_weighted) # # print('Region name unweighter COG: ',cog_region_name_unweighted) # # # List created to be added to dataframe # cog_region_name_weighted_list.append(cog_region_name_weighted) # cog_region_name_unweighted_list.append(cog_region_name_unweighted) # # # To choose from weighted and unweighted COG options # WEIGHTED = True # # if WEIGHTED: # MNI_cog_list = MNI_cog_weighted_list # cog_region_name_list = cog_region_name_weighted_list # cog_value_list = cog_weighted_value_list # else: # pass # # # Sort the Regions bsed on cog value # # # Get the indices of elements after they are sorted # sorted_indices = np.argsort(cog_value_list) # # # Sort the lists according to the above sorted_indices # cog_value_list = np.array(cog_value_list)[sorted_indices] # number_overlapping_cluster_voxels_list = \ # np.array(number_overlapping_cluster_voxels_list)[sorted_indices] # # overlapping_cluster_voxels_percentage_list = \ # np.array(overlapping_cluster_voxels_percentage_list)[sorted_indices] # # MNI_cog_list = np.array(MNI_cog_list)[sorted_indices] # cog_region_name_list = np.array(cog_region_name_list)[sorted_indices] """ TODO: Convert MNI coordinates from list to string (x,y,z) The next error that I will have to deal with is unequal length arrays. For that append each list with spaces. Then care about ordering the dictionary. """ # Creating a dictionary to create dataframe df_dict = OrderedDict() df_dict['ROI Index'] = [self.volume] df_dict['Cluster Number'] = [cluster_number] df_dict['Cluster Label'] = [label] # # df_dict['Max Value'] = cog_value_list # df_dict['Num Voxels'] = number_overlapping_cluster_voxels_list # df_dict['Percentage of Voxel' ] = \ # overlapping_cluster_voxels_percentage_list # df_dict['MNI Coordinates'] = MNI_cog_list # df_dict['Region Name'] = cog_region_name_list df_dict[ 'overlapping_indices_tuple_list'] = overlapping_indices_tuple_list self.feature_dict_list.append(df_dict) # df = pd.DataFrame(df_dict) # # df_report = df_report.append(df) # Empty the lists to be filled again cog_value_list = [] number_overlapping_cluster_voxels_list = [] overlapping_cluster_voxels_percentage_list = [] MNI_cog_list = [] cog_region_name_list = []
def convert_seg_to_bbox_coords(data_dict, dim, get_rois_from_seg_flag=False, class_specific_seg_flag=False): """Converts a mask into a bounding box format. data: format (n_patches, c, x, y, z) mask: format (n_patches, 1, x, y, z) """ bb_target = [] roi_masks = [] roi_labels = [] out_seg = np.copy(data_dict['seg']) for bix in range(data_dict['seg'].shape[0]): p_coords_list = [] p_roi_masks_list = [] p_roi_labels_list = [] if np.sum(data_dict['seg'][bix] != 0) > 0: if get_rois_from_seg_flag: clusters, n_cands = lb(data_dict['seg'][bix]) #s = generate_binary_structure(2,2) #(1,1); (3,3) #clusters, n_cands = lb(data_dict['seg'][bix], structure=s) #data_dict['class_target'][bix] = [data_dict['class_target'][bix]] * n_cands else: n_cands = int(np.max(data_dict['seg'][bix])) clusters = data_dict['seg'][bix] rois = np.array([ (clusters == ii) * 1 for ii in range(1, n_cands + 1) ]) # separate clusters and concat for rix, r in enumerate(rois): if np.sum( r != 0 ) > 0: #check if the lesion survived data augmentation seg_ixs = np.argwhere(r != 0) coord_list = [ np.min(seg_ixs[:, 1]) - 1, np.min(seg_ixs[:, 2]) - 1, np.max(seg_ixs[:, 1]) + 1, np.max(seg_ixs[:, 2]) + 1 ] if dim == 3: coord_list.extend([ np.min(seg_ixs[:, 3]) - 1, np.max(seg_ixs[:, 3]) + 1 ]) p_coords_list.append(coord_list) p_roi_masks_list.append(r) # add background class = 0. rix is a patient wide index of lesions. since 'class_target' is # also patient wide, this assignment is not dependent on patch occurrances. p_roi_labels_list.append( data_dict['class_target'][bix]) #[rix] + 1) if class_specific_seg_flag: out_seg[bix][data_dict['seg'][bix] == rix + 1] = data_dict['class_target'][bix][rix] + 1 if not class_specific_seg_flag: out_seg[bix][data_dict['seg'][bix] > 0] = 1 bb_target.append(np.array(p_coords_list)) roi_masks.append(np.array(p_roi_masks_list).astype('uint8')) roi_labels.append(np.array(p_roi_labels_list)) else: bb_target.append([]) roi_masks.append(np.zeros_like(data_dict['seg'][bix])[None]) roi_labels.append(np.array([-1])) if get_rois_from_seg_flag: data_dict.pop('class_target', None) data_dict['bb_target'] = np.array(bb_target) #box['box_coords'] data_dict['roi_masks'] = np.array(roi_masks) data_dict['roi_labels'] = np.array(roi_labels) data_dict['seg'] = out_seg return data_dict