def __init__(self, image_info, force_nuclei_load=False, parent=None): super(CriteriaSelection, self).__init__(parent) # nuclei selection? if not hasattr(self, 'is_nuclei_selection'): self.is_nuclei_selection = False # load image infos self.image_info = image_info # prepare criteria self.criteria = dict() # init segmentation self.segmentation = Segmentation(self.image_info) # load segmentation self.segmentation.load(force_nuclei_load=force_nuclei_load) # buttons self.btn_reset = QtGui.QPushButton(gui_labels.btn_reset) self.btn_load = QtGui.QPushButton(gui_labels.btn_load) self.btn_save = QtGui.QPushButton(gui_labels.btn_save) self.btn_close = QtGui.QPushButton(gui_labels.btn_close) # listeners self.btn_reset.clicked.connect(self.reset_criteria) self.btn_load.clicked.connect(self.load_criteria) self.btn_save.clicked.connect(self.save_criteria) self.btn_close.clicked.connect(self.close)
def create_train_target_from_ext_infos(self): """ Create training and target vectors from the given extensions :return: """ # store training and correction train_nuclei = list() corr_nuclei = list() # go through infos for info in self.ext_infos: # load segmentation seg = Segmentation(info) seg.load() # add to training nuclei train_nuclei += seg.nuclei.copy() # load correction corr = Correction(seg) corr.load_corrections() # add to correction corr_nuclei += corr.corr_nonuc.copy() # load train params train_params = cfg.clf_train_params # create data and target vectors train_data = np.zeros(shape=(len(train_nuclei), len(train_params))) train_target = np.zeros(shape=(len(train_nuclei))) # go through nuclei and build target vector for i, nucleus in enumerate(train_nuclei): # get relevant params from nucleus for j, key in enumerate(train_params): train_data[i][j] = nucleus[key] # set target nucleus_value = 0 # is it a nucleus? if Correction.is_correction_nonuc_with_list(nucleus, corr_nuclei) is False: nucleus_value = 1 # yes - it is train_target[i] = nucleus_value return train_data, train_target
def get_instance(): """ Simulate singleton-like behaviour to enable access to the segmentation system wide :return: """ global __seg_instance if __seg_instance is None: __seg_instance = Segmentation() return __seg_instance
def process_image(self): """ Segment image with the saved parameters :return: """ non_nuclei = False # is current image a revision? if Segmentation.is_revision_by_ID(self.image_info['ID']): # create a new segmentation non_nuclei = True seg = Segmentation(self.image_info, non_nuclei) # process stack seg.segment(process=True, merge=False, filter=False) # save results seg.save(force_labels_props_raw=True)
#selected_info_IDs = ['N1-19-9', 'N1-19-23'] # open window to select nuclei criteria loaded_infos = ImageHandler.load_image_infos() infos = list() # processing steps processing_steps = [['DIL', 'y', 2], ['CONV_BIT', 16]] for info in loaded_infos: info_ID = info['ID'] if info_ID in selected_info_IDs: infos.append(info) for info in infos: seg = Segmentation(info) seg.load() img_path = seg.get_results_dir().tmp + 'contact_surface.tif' print('LOAD', info['ID']) # go through nuclei and add to stack nIDs = seg.nuclei.get_nIDs(only_accepted=True) stack_contact_surface = np.zeros_like(seg.stacks.lamin) num_nIDs = len(nIDs) # go through nIDs for i, nID in enumerate(nIDs):
""" # import classes from storage.image import ImageHandler from processing.segmentation import Segmentation # load image infos image_infos = ImageHandler.load_image_infos() # to skip parent for revisions id_to_skip = None # apply defined filters to images for image_info in image_infos: # revision? then skip the initial segmentation and do the revisions if Segmentation.is_revision_by_ID(image_info['ID']): id_to_skip = Segmentation.extract_parent_from_ID(image_info['ID']) # create a new segmentation non_nuclei_seg = Segmentation(image_info, True) # segment stack non_nuclei_seg.segment() # save results non_nuclei_seg.save() else: # initial segmentation if id_to_skip != image_info['ID']: # initialise segmentation segmentation = Segmentation(image_info)
infos = list() # processing steps processing_steps = [['DIL', 'y', 2], ['CONV_BIT', 16]] # calculate compactness? calc_compactness = False for info in loaded_infos: info_ID = info['ID'] if info_ID in selected_info_IDs: infos.append(info) for info in infos: seg = Segmentation(info) seg.load() img_path = seg.get_results_dir().tmp + 'compactness_examples.tif' voxel_size = float(info['voxel_size']) voxel_volume = voxel_size ** 3 voxel_surface = voxel_size ** 2 print('LOAD', info['ID']) # go through nuclei and add to stack nIDs = seg.nuclei.get_nIDs(only_accepted=True) example_counter = np.zeros((5 * 5)).astype(np.int8) stack_examples = list()
plt.rcParams.update(params) # select a specific info selected_info_IDs = ['N1-19-9'] # open window to select nuclei criteria loaded_infos = ImageHandler.load_image_infos() infos = list() for info in loaded_infos: info_ID = info['ID'] if info_ID in selected_info_IDs: infos.append(info) for info in infos: seg = Segmentation(info) seg.load() # go through nuclei and add them to a stack with # nuclei_in_direction as value nIDs = seg.nuclei.get_nIDs(only_accepted=True) layer_stack = np.zeros_like(seg.stacks.nuclei) for nID in nIDs: # get nuclei in direction apical = seg.nuclei.get_nucleus_apical_distance(nID) if np.isnan(apical): apical = 0
plt.rcParams.update(params) selected_info_IDs = ['N1-19-9', 'N1-19-22', 'N1-19-23', 'N1-19-24'] #selected_info_IDs = ['N1-19-9'] # open window to select nuclei criteria loaded_infos = ImageHandler.load_image_infos() infos = list() for info in loaded_infos: info_ID = info['ID'] if info_ID in selected_info_IDs: infos.append(info) for info in infos: seg = Segmentation(info) seg.load() print('LOAD', info['ID']) # go through nuclei and add to stack nIDs = seg.nuclei.get_nIDs(only_accepted=True) stack_apical_dist = np.zeros_like(seg.stacks.lamin) stack_pseudo_layer = np.zeros_like(seg.stacks.lamin) # get average nuclei height all_depths = seg.nuclei.data_frames['data_params'].get_vals_from_col('depth', only_accepted=True) # get average avg_depth = np.mean(all_depths)
# lists density_list = dict() volume_list = dict() min_den = -1 max_den = -1 min_vol = -1 max_vol = -1 # resolution dim = 100 for info in infos: if info['ID'] in selected_info_IDs: selected_infos[info['ID']] = info segs[info['ID']] = Segmentation(info) segs[info['ID']].load() # prepare maps density_map[info['ID']] = np.zeros_like( segs[info['ID']].stacks.lamin[0]) volume_map[info['ID']] = np.zeros_like( segs[info['ID']].stacks.lamin[0]) # prepare lists density_list[info['ID']] = list() volume_list[info['ID']] = list() for info_ID, seg in segs.items(): # tile image for y in range(int(density_map[info_ID].shape[0] / dim)):
""" Using pandas to store nuclei in csv instead of pickling the whole list """ import numpy as np import pandas as pd import re # import classes from storage.image import ImageHandler from processing.segmentation import Segmentation from storage.struct import Struct import storage.config as cfg # open window to select nuclei criteria infos = ImageHandler.load_image_infos() # select a specific info selected_info_ID = 'N1-19-9' selected_info = None for info in infos: if info['ID'] == selected_info_ID: selected_info = info # process segmentation seg = Segmentation(selected_info) #seg.segment(process=True, merge=True, filter=False) #seg.save() seg.load()
import matplotlib.pylab as plt params = {'axes.titlesize': cfg.fontsdict_plot['fontsize'], 'xtick.labelsize': cfg.fontsdict_plot['fontsize'], 'ytick.labelsize': cfg.fontsdict_plot['fontsize']} plt.rcParams.update(params) # open window to select nuclei criteria infos = ImageHandler.load_image_infos() # select a specific info selected_info_IDs = ['N1-19-24'] for info in infos: if info['ID'] in selected_info_IDs: seg = Segmentation(info) seg.load() processing_steps = [ ['EQU'], ['THR', 'OTSU', 100, 'no3D'], ['CLS', 'bin', 2], ['FILL'], ['OPN', 'bin', 2], ['CONV_BIT', 16, '3D'] ] # apply processing steps seg.stacks.membin = ImageProcessing.apply_filters( processing_steps, seg.stacks.membrane, verbose=cfg.general_verbose)
Merge initial and revision segmentation to a final segmentation """ # import classes from storage.image import ImageHandler from processing.segmentation import Segmentation # load image infos image_infos = ImageHandler.load_image_infos() revs_to_merge = list() # apply defined filters to images for image_info in image_infos: # revision? then skip if Segmentation.is_revision_by_ID(image_info['ID']): revs_to_merge.append(Segmentation.extract_rev_from_ID(image_info['ID'])) else: # initialise segmentation segmentation = Segmentation(image_info) # load results segmentation.load() # merge for rev in revs_to_merge: segmentation.merge_parent_with_rev(rev) # save merge segmentation.save_merge_segmentation()
# import classes from storage.image import ImageHandler from processing.segmentation import Segmentation from frontend.gui.nuc_select import NucleoSelect # load image infos image_infos = ImageHandler.load_image_infos() # to skip parent for revisions id_to_skip = None # apply defined filters to images for image_info in image_infos: # revision? then skip the initial segmentation and do the revisions if Segmentation.is_revision_by_ID(image_info['ID']): id_to_skip = Segmentation.extract_parent_from_ID(image_info['ID']) if id_to_skip != image_info['ID']: # initialise segmentation segmentation = Segmentation(image_info) # load results segmentation.load() # cycle through the nuclei and correct their start and stop planes if necessary app = QtGui.QApplication(sys.argv) nuc_selector = NucleoSelect(segmentation) nuc_selector.show() nuc_selector.raise_()
class CriteriaSelection(QtGui.QDialog): def __init__(self, image_info, force_nuclei_load=False, parent=None): super(CriteriaSelection, self).__init__(parent) # nuclei selection? if not hasattr(self, 'is_nuclei_selection'): self.is_nuclei_selection = False # load image infos self.image_info = image_info # prepare criteria self.criteria = dict() # init segmentation self.segmentation = Segmentation(self.image_info) # load segmentation self.segmentation.load(force_nuclei_load=force_nuclei_load) # buttons self.btn_reset = QtGui.QPushButton(gui_labels.btn_reset) self.btn_load = QtGui.QPushButton(gui_labels.btn_load) self.btn_save = QtGui.QPushButton(gui_labels.btn_save) self.btn_close = QtGui.QPushButton(gui_labels.btn_close) # listeners self.btn_reset.clicked.connect(self.reset_criteria) self.btn_load.clicked.connect(self.load_criteria) self.btn_save.clicked.connect(self.save_criteria) self.btn_close.clicked.connect(self.close) def prep_ctn_criteria_select(self, lookup_nucleus): """ Prepare main container for criteria selection :return: """ container = QtGui.QGridLayout() # select criteria criteria = cfg.filter_criteria_labels if lookup_nucleus is True: criteria = cfg.filter_criteria_nuclei counter = 0 for param in criteria: # get container param_ctn = self.prep_criteria(param.lower(), lookup_nucleus=lookup_nucleus) # add container if param_ctn is not None: container.addLayout(param_ctn, counter, 0) counter += 1 # submit buttons container.addLayout(self.prep_ctn_submit(), counter, 0) return container def reset_criteria(self): """ Reset edit boxes :return: """ # go through edit boxes and empty for criteria_raw in self.criteria: self.criteria[criteria_raw]['edt_min'].setText('') self.criteria[criteria_raw]['edt_max'].setText('') def load_criteria(self): """ Load selection criteria :return: """ # load criteria self.loaded_criteria = self.segmentation.get_nuclei_criteria(True) # set min/max fields for critieria for criteria_raw in self.criteria: # edit boxes if self.loaded_criteria is not None and criteria_raw in self.loaded_criteria.keys(): # set value in edit box if self.loaded_criteria[criteria_raw]['MIN'] is not None: self.criteria[criteria_raw]['edt_min'].setText(str(self.loaded_criteria[criteria_raw]['MIN'])) if self.loaded_criteria[criteria_raw]['MAX'] is not None: self.criteria[criteria_raw]['edt_max'].setText(str(self.loaded_criteria[criteria_raw]['MAX'])) def save_criteria(self): """ Save selection criteria for labels :return: """ # create criteria mapping criteria = dict() # go through criteria and get the values for param in self.loaded_criteria.keys(): # is criteria on mask? if param.lower() in self.criteria.keys(): # get min and max min_input = self.criteria[param.lower()]['edt_min'].text() max_input = self.criteria[param.lower()]['edt_max'].text() min_value = None if min_input: min_value = '%.1f' % float(min_input) max_value = None if max_input: max_value = '%.1f' % float(max_input) else: min_value = self.loaded_criteria[param]['MIN'] max_value = self.loaded_criteria[param]['MAX'] # write to mapping criteria[param] = dict() criteria[param]['MIN'] = min_value criteria[param]['MAX'] = max_value # set criteria self.loaded_criteria = criteria # save to file self.segmentation.save_nuclei_criteria(criteria) def close(self): """ Close criteria selection and show the main window again :return: """ # show parent self.parent().showNormal() # close processing super(QtGui.QDialog, self).close() def prep_criteria(self, param, lookup_nucleus): """ Prepare a container with the parameter :param param: :return: """ container = None prep_ctn = True # is param part of the nuclei? if lookup_nucleus is True: if self.segmentation.nuclei.is_param_in_nuclei(param) is False: prep_ctn = False if prep_ctn is True: # prepare dictionary self.prep_criteria_dict(param) # prepare container container = self.prep_criteria_ctn(param) return container def prep_criteria_dict(self, param): """ Prepare dictionary for param :param param: :return: """ self.criteria[param] = dict() # edit boxes self.criteria[param]['edt_min'] = QtGui.QLineEdit() self.criteria[param]['edt_max'] = QtGui.QLineEdit() # figures self.criteria[param]['fig_hist'] = plt.figure(figsize=(5, 2)) self.criteria[param]['fig_example'] = plt.figure(figsize=(5, 2)) # canvases self.criteria[param]['cnv_hist'] = FigureCanvas(self.criteria[param]['fig_hist']) self.criteria[param]['cnv_example'] = FigureCanvas(self.criteria[param]['fig_example']) # misc widgets self.criteria[param]['sld_hist'] = QtGui.QSlider(QtCore.Qt.Horizontal, self) def prep_criteria_ctn(self, param): """ Container to set criteria param :return: """ container = QtGui.QGridLayout() # labels container.addWidget(QtGui.QLabel(getattr(gui_labels, 'crit_sel_label_' + param)), 0, 0) container.addWidget(QtGui.QLabel(gui_labels.crit_sel_min), 1, 0) container.addWidget(QtGui.QLabel(gui_labels.crit_sel_max), 2, 0) container.setRowStretch(3, 1) # edit boxes container.addWidget(self.criteria[param]['edt_min'], 1, 1) container.addWidget(self.criteria[param]['edt_max'], 2, 1) # sort nuclei if self.is_nuclei_selection: # sort nuclei self.segmentation.nuclei.sort_nuclei(param) # get sorted list # TODO transform the props into a dict self.criteria[param]['sorted_labels'] = self.segmentation.nuclei.get_param_list_from_nuclei(param) self.criteria[param]['sorted_props'] = self.segmentation.nuclei.get_param_list_from_nuclei(create_dict=True) else: # sort labels self.criteria[param]['sorted_labels'] = self.segmentation.get_sorted_prop_list(param) self.criteria[param]['sorted_props'] = self.segmentation.sorted_probs.copy() # show histogram Plot.view_histogram_of_value_list(self.criteria[param]['fig_hist'], self.criteria[param]['sorted_labels'], cfg.criteria_select_hist_bins) # add to container container.addWidget(self.criteria[param]['cnv_hist'], 0, 2, 3, 1) container.addWidget(self.criteria[param]['cnv_example'], 0, 3, 4, 1) # slider self.criteria[param]['sld_hist'].valueChanged[int].connect(self.make_change_criteria_example(param)) self.criteria[param]['sld_hist'].setMinimum(0) self.criteria[param]['sld_hist'].setMaximum(len(self.criteria[param]['sorted_props'])) container.addWidget(self.criteria[param]['sld_hist'], 3, 2) return container def make_change_criteria_example(self, param): """ Make function to call change criteria :param param: :return: """ def change_criteria_example_param(example_selected): self.change_criteria_example(param, example_selected) return change_criteria_example_param def change_criteria_example(self, param, example_selected): """ Change example in +/- range :param param: :param example_selected: :return: """ min_range = example_selected - cfg.criteria_select_eg_range if min_range < 0: min_range = 0 max_range = example_selected + cfg.criteria_select_eg_range if max_range > len(self.criteria[param]['sorted_props']): max_range = len(self.criteria[param]['sorted_props']) # prepare examples examples = list() # show examples from each part for i in range(min_range, max_range): example_title = '%i\n%.2f' % (self.criteria[param]['sorted_props'][i]['nID'], self.criteria[param]['sorted_props'][i][param]) # prepare image examples = Plot.prepare_output(examples, self.criteria[param]['sorted_props'][i]['img'], example_title, cfg.criteria_select_eg_colour) # clear figure if len(examples[0]) < (cfg.criteria_select_eg_range * 2): self.criteria[param]['fig_example'].clear() # show examples Plot.show_images(self.criteria[param]['fig_example'], examples, cols=cfg.criteria_select_eg_cols) # update canvas self.criteria[param]['cnv_example'].draw()
view_image(cropped, img_name="Pre-processed image") # ------ SEGMENTATION ------ # Apply the image segmentation for separating significant elements (casting surfaces) # from negligible ones (sandy background, upper metal frame, outer image background) # with respect to the casting surfaces area computation # De-noise the pre-processed image according to the config file parameters first = cv2.fastNlMeansDenoising(cropped.copy(), h=FRAME_PARAMS['h'], templateWindowSize=FRAME_PARAMS['template_window_size'], searchWindowSize=FRAME_PARAMS['search_window_size']) # Convert the de-noised image to grayscale and smooth it by blurring blurred = gray_and_blur(first, blur=True, ksize=7) # Init a Segmentation class object with the config.py segmentation parameters sgm = Segmentation(SEGMENTATION_PARAMS) # Adjust brightness/contrast and threshold the blurred image based on the configuration settings thresh = sgm.scale_abs_convert_thresh(blurred) # Apply a sequence of morphological transformations to simplify the thresholded image # in order to better detect contours transformed = sgm.transform_morphology( thresh, TRANSFORMATION_SEQ, SEGMENTATION_PARAMS['morph_ops_params']) # Show the segmentation step output image if required if args["steps"]: print(f"Sequence of transformations: {TRANSFORMATION_SEQ}") view_image( np.hstack([thresh, transformed]), img_name=f"Thresholding | {TRANSFORMATION_SEQ[0].capitalize()} and \ {TRANSFORMATION_SEQ[1].capitalize()}")
test_window = NucleoSegment(exp_id=exp_id) test_window.show() test_window.raise_() test_window.activateWindow() sys.exit(app.exec_()) # process if processing['process'] == 1: test_window = NucleoProcess(selected_info) test_window.show() test_window.raise_() test_window.activateWindow() sys.exit(app.exec_()) elif processing['process'] == 2: print('=== Process ===') seg = Segmentation(selected_info) seg.segment(process=True, merge=False, filter=False) seg.get_label_props() seg.save(force_labels_props_raw=True) del(seg) # merge if processing['merge'] == 1: test_window = MergeCriteria(selected_info) test_window.show() test_window.raise_() test_window.activateWindow() sys.exit(app.exec_()) elif processing['merge'] >= 2: force_reload = False if processing['merge'] == 3:
for info in loaded_infos: info_ID = info['ID'] if info_ID in selected_info_IDs: infos.append(info) print('TEST APPEND', info) img_maps = dict() val_maps = dict() tiling_count_map = dict() tiling_maps = dict() limits = dict() limit_lists = dict() for info in infos: seg = Segmentation(info) seg.load() # preparations for params if 'between_space' in params_to_get: # get binary stack without nuclei filled_minus_nuclei = ImageHandler.load_tiff_as_stack( seg.get_results_dir().tmp + 'filled_minus_nuclei.tif') if filled_minus_nuclei is None: filled_stack = np.full( (seg.stacks.lamin.shape[0], seg.stacks.lamin.shape[1], seg.stacks.lamin.shape[2]), 1, dtype=np.uint8)
plt.rcParams.update(params) selected_info_IDs = ['N1-19-9', 'N1-19-22', 'N1-19-23', 'N1-19-24'] #selected_info_IDs = ['N1-19-9'] # open window to select nuclei criteria loaded_infos = ImageHandler.load_image_infos() infos = list() for info in loaded_infos: info_ID = info['ID'] if info_ID in selected_info_IDs: infos.append(info) for info in infos: seg = Segmentation(info) seg.load() print('LOAD', info['ID']) # go through nuclei and add to stack nIDs = seg.nuclei.get_nIDs(only_accepted=True) stack_volume = np.zeros_like(seg.stacks.lamin).astype(np.int8) all_volumes = seg.nuclei.data_frames['data_params'].get_vals_from_col( 'volume', only_accepted=True) min_val = float(max(all_volumes)) max_val = float(min(all_volumes))