def train_texture_samples(subdir, samples_dict, regression_variable, endings, samples_per_image, age_ranges): ''' Read in samples for texture classification. ''' # Organize some information. total_files = os.listdir(subdir) data_points = [' '.join(a_file.split('.')[0].split(' ')[0:-1]) for a_file in total_files if a_file.split(' ')[-1] == 'hmask.png'] with open(subdir + os.path.sep + 'position_metadata_extended.json', 'r') as read_file: my_metadata = json.loads(read_file.read()) metadata_dict = {my_metadata[i]['timepoint']: my_metadata[i][regression_variable.lower()] for i in range(0, len(my_metadata))} egg_age_dict = {my_metadata[i]['timepoint']: my_metadata[i]['egg_age'] for i in range(0, len(my_metadata))} # Exclude larval animals from ghost_age computation. if regression_variable.lower() == 'ghost_age': data_points = [a_point for a_point in data_points if egg_age_dict[a_point] > 0] # Actualyl sample my images. for a_point in data_points: my_age = metadata_dict[a_point]/24 if regression_variable.lower() == 'ghost_age': my_age = abs(my_age) mask_file = freeimage.read(subdir + os.path.sep + a_point + ' ' + endings[1]) image_file = freeimage.read(subdir + os.path.sep + a_point + ' ' + endings[0]) my_samples = sample_8star(image_file, mask_file, 17, sample_number = samples_per_image) for age_range in age_ranges: if age_range[0] <= my_age < age_range[1]: samples_dict[age_range].extend(my_samples) return samples_dict
def measure(self, position_root, timepoint, annotations, before, after): derived_root = position_root.parent / DERIVED_ROOT image_file = position_root / f'{timepoint} {self.image_type}.png' if not image_file.exists(): return [numpy.nan] * len(self.feature_names) image = freeimage.read(image_file) flatfield = freeimage.read(position_root.parent / 'calibrations' / f'{timepoint} fl_flatfield.tiff') image = image.astype(numpy.float32) * flatfield mask = self.get_mask(position_root, derived_root, timepoint, annotations, image.shape) if mask is None: return [numpy.nan] * len(self.feature_names) if mask.sum() == 0: print( f'No worm region defined for {position_root.name} at {timepoint}' ) data, region_masks = measure_fluor.subregion_measures(image, mask) if self.write_masks: color_mask = measure_fluor.colorize_masks(mask, region_masks) out_dir = derived_root / 'fluor_region_masks' / position_root.name out_dir.mkdir(parents=True, exist_ok=True) freeimage.write(color_mask, out_dir / f'{timepoint} {self.image_type}.png') return data
def read_corrected_gfp_fluorescence(gfp_img, calibration_directory, super_vignette, hot_threshold=10000): ''' Correct fluorescence images for flatfield, and re-normalize to make the images more nicely viewable. ''' # Read in image and apply vignetting. gfp_img = pathlib.Path(gfp_img) timepoint = gfp_img.name.split(' ')[0] super_vignette = pickle.load(open(super_vignette, 'rb')) raw_image = freeimage.read(gfp_img) raw_image[np.invert(super_vignette)] = 0 calibration_directory = pathlib.Path(calibration_directory) # Correct for flatfield. flatfield_path = calibration_directory.joinpath(timepoint + ' fl_flatfield.tiff') calibration_image = freeimage.read(flatfield_path) #corrected_image = raw_image corrected_image = raw_image * calibration_image # Correct for hot pixels. median_image = ndimage.filters.median_filter(corrected_image, size=3) difference_image = np.abs( corrected_image.astype('float64') - median_image.astype('float64')).astype('uint16') hot_pixels = difference_image > hot_threshold median_image_hot_pixels = median_image[hot_pixels] corrected_image[hot_pixels] = median_image_hot_pixels # Return the actual image. return corrected_image.astype(np.uint16)
def extract_image_set(image_files, out_dir, date, age, plate_params, ignore_previous=False): """Find wells in a set of scanner images and extract each well into a separate image for further processing. Parameters: image_files: list of paths to a set of images. out_dir: path to write out the extracted images and metadata. date: date object referring to image scan date age: age in days of the worms in these images plate_params: configuration information for extracting wells from the plates. This must be a parameter dictionary suitable to pass to extract_wells.extract_wells() ignore_previous: if False, and stored results already exist, skip processing """ out_dir = pathlib.Path(out_dir) metadata = out_dir / 'metadata.pickle' if metadata.exists() and not ignore_previous: return images = [] print('extracting images for {}'.format(out_dir)) well_mask = freeimage.read(str(out_dir.parent / 'well_mask.png')) > 0 for image_file in image_files: image = freeimage.read(image_file) if image.dtype == numpy.uint16: image = (image >> 8).astype(numpy.uint8) images.append(image) well_names, well_images, well_centroids = extract_wells.extract_wells(images, well_mask, **plate_params) well_dir = util.get_dir(out_dir / 'well_images') for well_name, well_image_set in zip(well_names, well_images): for i, image in enumerate(well_image_set): freeimage.write(image, str(well_dir/well_name)+'-{}.png'.format(i)) util.dump(metadata, date=date, age=age, well_names=well_names, well_centroids=well_centroids)
def archive_human_masks(human_directory, new_directory, work_directory): ''' For a directory of hand-drawn masks, mask out everything in the accompanying bright-field file except for the worm itself and a 100-pixel surrounding area to save disk space. Also, re-compress all images to maximize compression and space efficiency. ''' for a_subdir in os.listdir(human_directory): if os.path.isdir(human_directory + os.path.sep + a_subdir): folderStuff.ensure_folder(new_directory + os.path.sep + a_subdir) for a_file in os.listdir(human_directory + os.path.sep + a_subdir): if a_file.split(' ')[-1] == 'hmask.png': if not os.path.isfile(new_directory + os.path.sep + a_subdir + os.path.sep + a_file): print('Up to ' + a_subdir + ' ' + a_file + '.') my_stem = a_file.split(' ')[0] my_mask = freeimage.read(human_directory + os.path.sep + a_subdir + os.path.sep + my_stem + ' ' + 'hmask.png') bf_path = human_directory + os.path.sep + a_subdir + os.path.sep + my_stem + ' ' + 'bf.png' if os.path.isfile(bf_path): my_image = freeimage.read(bf_path) else: my_image = freeimage.read(bf_path.replace(human_directory, work_directory)) area_mask = my_mask.copy().astype('bool') distance_from_mask = scipy.ndimage.morphology.distance_transform_edt(np.invert(area_mask)).astype('uint16') area_mask[distance_from_mask > 0] = True area_mask[distance_from_mask > 100] = False my_image[np.invert(area_mask)] = False freeimage.write(my_image, new_directory + os.path.sep + a_subdir + os.path.sep + my_stem + ' ' + 'bf.png', flags = freeimage.IO_FLAGS.PNG_Z_BEST_COMPRESSION) freeimage.write(my_mask, new_directory + os.path.sep + a_subdir + os.path.sep + my_stem + ' ' + 'hmask.png', flags = freeimage.IO_FLAGS.PNG_Z_BEST_COMPRESSION) elif a_file.split('.')[-1] == 'json': shutil.copyfile(human_directory + os.path.sep + a_subdir + os.path.sep + a_file, new_directory + os.path.sep + a_subdir + os.path.sep + a_file) return
def score_image_set(out_dir, score_params, ignore_previous=False): """Score wells for a single day's scanned images. Parameters: out_dir: directory in which well_images directory is found, and to which score data will be written. score_params: configuration information for scoring wells for movement. This must be a parameter dictionary suitable to pass to score_wells.score_wells() ignore_previous: if False, and stored results already exist, skip processing """ out_dir = pathlib.Path(out_dir) score_file = out_dir / 'scores.pickle' if score_file.exists() and not ignore_previous: return print('scoring images for {}'.format(out_dir)) well_names = util.load(out_dir / 'metadata.pickle').well_names well_mask = freeimage.read(str(out_dir.parent / 'well_mask.png')) > 0 well_dir = out_dir / 'well_images' well_images = [] for well_name in well_names: images = [freeimage.read(str(image)) for image in sorted(well_dir.glob(well_name+'-*.png'))] well_images.append(images) well_scores = score_wells.score_wells(well_images, well_mask, **score_params) util.dump(score_file, well_names=well_names, well_scores=well_scores) scores_out = [[name, str(score)] for name, score in zip(well_names, well_scores)] util.dump_csv(scores_out, out_dir / 'scores.csv')
def get_calibrated_image(self, well, timepoint, label, calibration_type, apply_vignette=True): ''' well - string for well timepoint - string for timepoint per YYYY-MM-DDtHHMM format label - string suffix coming after timepoint calibration_type - ['bf,'fl'] ''' image_fn = self.expt_path / well / (timepoint + ' ' + label + '.png') calibration_fn = self.expt_path / 'calibrations' / ( timepoint + ' ' + calibration_type + '_flatfield.tiff') img = freeimage.read(str(image_fn)) calibration_img = freeimage.read(str(calibration_fn)) ref_intensity = self.expt_mdata['brightfield metering'][timepoint][ 'ref_intensity'] if (self.expt_path / 'super_vignette.pickle').exists() and apply_vignette: with (self.expt_path / 'super_vignette.pickle').open('rb') as sv_file: sv = pickle.load(sv_file) calibrated_img = (img * calibration_img / ref_intensity * self.BF_REF_INTENSITY).astype('uint16') calibrated_img[~sv] = 0 return calibrated_img else: return (img * calibration_img / ref_intensity * self.BF_REF_INTENSITY).astype('uint16')
def make_composite_maskfile_batch(data_path, mask_path, save_path, data_str='', mask_str=''): data_fns = [ data_f for data_f in sorted(os.listdir(data_path)) if data_str in data_f ] print('importing data images') data_imgs = np.array([(freeimage.read(data_path + os.path.sep + data_f)) for data_f in data_fns]) print('importing mask images') mask_imgs = np.array([ freeimage.read(mask_path + os.path.sep + mask_f) > 0 for data_f in data_fns for mask_f in sorted(os.listdir(mask_path)) if data_f[0:15] in mask_f if mask_str in mask_f ]) try: os.stat(save_path) except: os.mkdir(save_path) print('generating and saving composites') comp = np.zeros(np.shape(data_imgs[[0]])) print('got here') for d_img, m_img, data_f in zip(data_imgs, mask_imgs, data_fns): comp = colorize.scale(np.copy(d_img), output_max=254) comp[m_img] = 255 #if data_f==data_fns[2]: return freeimage.write( comp.astype('uint8'), save_path + os.path.sep + data_f[:-4] + 'composite' + data_f[-4:])
def computeFocusMeasures(temporal_radius=11, update_db=True, write_models=False, write_deltas=False, write_masks=False): with sqlite3.connect(str(DPATH / "analysis/db.sqlite3")) as db: db.row_factory = sqlite3.Row non_vignette = freeimage.read(str(DPATH / "non-vignette.png")) != 0 vignette = non_vignette == 0 image_count = list(db.execute("select count() from images"))[0]["count()"] positions = [row["well_idx"] for row in db.execute("select well_idx from wells where did_hatch")] position_bgss = {position: WzBgs(2560, 2160, temporal_radius, non_vignette) for position in positions} time_points = [row["name"] for row in db.execute("select name from time_points")] image_idx = 0 for time_point in time_points: print(time_point) for position in positions: print("", position) acquisition_names = [ row["acquisition_name"] for row in db.execute( "select acquisition_name from images where well_idx=? and time_point=?", (position, time_point) ) ] if acquisition_names: bgs = position_bgss[position] tasks = [] for acquisition_name in acquisition_names: im_fpath = ( DPATH / "{:02}".format(position) / "{} {}_ffc.png".format(time_point, acquisition_name) ) tasks.append( pool.submit( lambda an=acquisition_name, fn=_computeFocusMeasures, args=( bgs, im_fpath, non_vignette, update_db, write_models, write_deltas, write_masks, ): (an, fn(*args)) ) ) for task in tasks: acquisition_name, focus_measures = task.result() if focus_measures is not None: measure_names = sorted(focus_measures.keys()) q = "update images set " + ", ".join( "{}=?".format(measure_name) for measure_name in measure_names ) q += " where well_idx=? and time_point=? and acquisition_name=?" v = [float(focus_measures[measure_name]) for measure_name in measure_names] v.extend((position, time_point, acquisition_name)) list(db.execute(q, v)) image_idx += 1 print(" {:<10} {:%}".format(acquisition_name, image_idx / image_count)) try: im = freeimage.read(str(DPATH / "{:02}".format(position) / "{} bf_ffc.png".format(time_point))) bgs.updateModel(im) except: pass db.commit()
def _computeSigmoidWeightedMeasures(db_lock, update_db, measure_antimask, x0, k, L): weightedMaskedHighpassBrenner = getWeightedMaskedHighpassBrennerInstance((2560, 1600)) with db_lock, sqlite3.connect(str(DPATH / "analysis/db.sqlite3")) as db: column_name = "x0:{},k:{}".format(x0, k) time_point_well_idxs = list( db.execute( "select time_point, well_idx from (" ' select time_point, well_idx, sum(is_focused) as sif from images where acquisition_name!="bf" group by time_point, well_idx' ") where sif == 1" ) ) for time_point, well_idx in time_point_well_idxs: with db_lock, sqlite3.connect(str(DPATH / "analysis/db.sqlite3")) as db: acquisition_names = [ row[0] for row in db.execute( "select acquisition_name from images where well_idx=? and time_point=?", (well_idx, time_point) ) ] results = [] for acquisition_name in acquisition_names: delta_fpath = ( DPATH / "{:02}".format(well_idx) / "{} {}_ffc wz_bgs_model_delta.tiff".format(time_point, acquisition_name) ) if not delta_fpath.exists(): continue image = freeimage.read( str(DPATH / "{:02}".format(well_idx) / "{} {}_ffc.png".format(time_point, acquisition_name)) ) delta = freeimage.read(str(delta_fpath)) weights = logistic_sigmoid(delta, x0, k, L) results.append(float(weightedMaskedHighpassBrenner.metric(image, measure_antimask, weights))) if not results or not update_db: continue with db_lock, sqlite3.connect(str(DPATH / "analysis/db.sqlite3")) as db: for result, acquisition_name in zip(results, acquisition_names): image_id = list( db.execute( "select image_id from images where time_point=? and well_idx=? and acquisition_name=?", (time_point, well_idx, acquisition_name), ) )[0][0] if list(db.execute("select count(*) from sigmoids where image_id=?", (image_id,)))[0][0] == 0: list( db.execute( 'insert into sigmoids (image_id, "{}") values (?, ?)'.format(column_name), (image_id, result), ) ) else: list( db.execute( 'update sigmoids set "{}"=? where image_id=?'.format(column_name), (result, image_id) ) ) db.commit()
def select_sample(image_point, vignette_mask, total_sample_number, SVM_external_parameters): ''' Given a mask in a_mask and an image file in image_file, sample points to use for texture classification according to selection_mode and total_sample_number. ''' def random_select_from_mask(a_mask, sample_number, my_radius): ''' Select sample_number pixels from a_mask which have a clear radius of length my_radius around themselves (i.e. they are not too close to the border of the image). ''' # Ensure that the edges of the image are not included in the mask. a_mask[:my_radius, :] = False a_mask[-my_radius:, :] = False a_mask[:, :my_radius] = False a_mask[:, -my_radius:] = False # Randomly select pixels from the mask. pixel_number = a_mask[a_mask > 0].shape[0] my_indices = np.ma.indices(my_image.shape) selected_pixels = np.zeros(pixel_number).astype('bool') selected_pixels[:int(total_sample_number/2)] = True selected_pixels = np.random.permutation(selected_pixels) selected_pixels = np.array([my_indices[0][a_mask > 0][selected_pixels], my_indices[1][a_mask > 0][selected_pixels]]).transpose() return selected_pixels # Rescale images and prepare some supporting variables. worm_mask = freeimage.read(image_point + ' ' + 'hmask.png').astype('bool') my_image = freeimage.read(image_point + ' ' + 'bf.png') (my_image, worm_mask, vignette_mask) = scaled_images(my_image, worm_mask, vignette_mask, SVM_external_parameters) my_radius = (SVM_external_parameters['square_size'] - 1)/2 # Select half pixels from the worm itself and half pixels from an area outside the worm but within 50 pixels of the worm. selection_mode = SVM_external_parameters['sampling'] if selection_mode == 'Local_Worm': distance_from_worm = scipy.ndimage.morphology.distance_transform_edt(np.invert(worm_mask)).astype('uint16') background_mask = np.zeros(worm_mask.shape).astype('bool') background_mask[distance_from_worm > 0] = True background_mask[distance_from_worm > worm_mask.shape[0]//20] = False background_mask[np.invert(vignette_mask)] = False background_selected_pixels = random_select_from_mask(background_mask, int(total_sample_number/2), my_radius) worm_selected_pixels = random_select_from_mask(worm_mask, int(total_sample_number/2), my_radius) elif selection_mode == 'Hard_Negative': crude_mask = freeimage.read(image_point + ' ' + 'mask.png').astype('bool') negatives_mask = crude_mask & np.invert(worm_mask) background_selected_pixels = random_select_from_mask(negatives_mask, int(total_sample_number/2), my_radius) worm_selected_pixels = random_select_from_mask(worm_mask, int(total_sample_number/2), my_radius) else: raise BaseException('Invalid selection_mode passed from SVM_external_parameters[\'sampling\'].') my_pixels = np.vstack([worm_selected_pixels, background_selected_pixels]) my_squares = [my_image[a_pixel[0] - my_radius: a_pixel[0] + 1 + my_radius, a_pixel[1] - my_radius: a_pixel[1] + 1 + my_radius] for a_pixel in my_pixels] my_classifications = np.hstack([np.array([1]*int(total_sample_number/2)), np.array([0]*int(total_sample_number/2))]) my_features = feature_computer(my_squares, SVM_external_parameters) my_samples = [my_features, my_classifications] return my_samples
def __init__(self, rw, image_dir, out_dir): """ Parameters rw - RisWidget object to load images into image_dir - str/pathlib.Path to directory images for loading out_dir - str/pathlib.Path to directory for saving overlays """ self.rw = rw self.image_dir = pathlib.Path(image_dir) self.out_dir = pathlib.Path(out_dir) assert self.image_dir.exists() assert self.out_dir.exists() self.editing = False # To be low-maintenance, just add everything to the flipbook layout layout = Qt.QFormLayout() widget = Qt.QWidget() widget.setLayout(layout) self.rw.flipbook.layout().addWidget(widget) self.rw.add_painter() self.rw.flipbook_pages.clear() self.image_list = sorted(list(self.image_dir.glob('*.png'))) for image_path in self.image_list: image = freeimage.read(image_path) image_list = flipbook.ImageList() image_list.append(rw_image.Image(data=image, name=image_path.name)) if (self.out_dir / image_path.name).exists(): image_list.append( freeimage.read((self.out_dir / image_path.name))) else: image_shape = image.shape if len(image_shape) == 3: image_list.append(numpy.zeros_like(image)) else: new_shape = list(image_shape) + [3] image_list.append( numpy.zeros(shape=new_shape).astype('uint8')) rw.flipbook_pages.append(image_list) self.rw.painter.brush_size.value = 9 self.clear = self._add_button(layout, 'Clear All', self._on_clear_clicked) self.reload = self._add_button(layout, 'Reload Overlay', self._on_reload_clicked) self.save = self._add_button(layout, 'Save Overlay', self._on_save_clicked)
def read_corrected_bf(image_file, movement_key = ''): ''' Read in an image at time_point and properly correct it for flatfield and metering. ''' time_point = image_file.split(os.path.sep)[-1].split(' ')[0] raw_image = freeimage.read(image_file) flatfield_image = freeimage.read(os.path.sep.join(image_file.split(os.path.sep)[:-2]) + os.path.sep + 'calibrations' + os.path.sep + time_point + ' ' + 'bf_flatfield.tiff') with open(os.path.sep.join(image_file.split(os.path.sep)[:-2]) + os.path.sep + 'experiment_metadata.json', 'r') as read_file: metadata = json.loads(read_file.read()) time_reference = metadata['brightfield metering'][time_point]['ref_intensity'] corrected_image = raw_image*flatfield_image corrected_image = corrected_image / time_reference * 11701.7207031 corrected_image = corrected_image.astype('uint16') return corrected_image
def _makeMeasureInputSensitivityComparisonVizWorker( measure_antimask, measure_a, measure_b, bf_im_fpath, model_im_fpath, measure_a_im_fpath, measure_a_idx_delta, measure_a_delta_im_fpath, measure_a_mask_im_fpath, measure_b_im_fpath, measure_b_idx_delta, measure_b_delta_im_fpath, measure_b_mask_im_fpath ): r = _NS() r.bf_im, r.bf_im_fpath = freeimage.read(str(bf_im_fpath)), bf_im_fpath r.model_im = freeimage.read(str(model_im_fpath)) r.measure_a_im, r.measure_a_im_fpath = freeimage.read(str(measure_a_im_fpath)), measure_a_im_fpath r.measure_a_idx_delta = measure_a_idx_delta r.measure_a_delta_im = freeimage.read(str(measure_a_delta_im_fpath)) r.measure_a_mask_im = freeimage.read(str(measure_a_mask_im_fpath)) r.measure_a_transformed_im = _apply_measure_transform(measure_a, r.measure_a_im, measure_antimask, r.measure_a_delta_im, r.measure_a_mask_im) r.measure_a_transformed_im_b = _apply_measure_transform(measure_b, r.measure_a_im, measure_antimask, r.measure_a_delta_im, r.measure_a_mask_im) r.measure_b_im, r.measure_b_im_fpath = freeimage.read(str(measure_b_im_fpath)), measure_b_im_fpath r.measure_b_idx_delta = measure_b_idx_delta r.measure_b_delta_im = freeimage.read(str(measure_b_delta_im_fpath)) r.measure_b_mask_im = freeimage.read(str(measure_b_mask_im_fpath)) r.measure_b_transformed_im = _apply_measure_transform(measure_b, r.measure_b_im, measure_antimask, r.measure_b_delta_im, r.measure_b_mask_im) r.measure_b_transformed_im_a = _apply_measure_transform(measure_a, r.measure_b_im, measure_antimask, r.measure_b_delta_im, r.measure_b_mask_im) return r
def train_texture_SVM_sample(data_points, regression_variable, samples_per_image, texture_model): ''' Get sample histograms for texture classification SVM training. ''' histogram_array = [] age_array = [] for a_point in data_points: do_point = True subdir = os.path.sep.join(a_point.split(os.path.sep)[:-1]) with open(subdir + os.path.sep + 'position_metadata_extended.json', 'r') as read_file: my_metadata = json.loads(read_file.read()) metadata_dict = { my_metadata[i]['timepoint']: my_metadata[i][regression_variable.lower()] for i in range(0, len(my_metadata)) } egg_age_dict = { my_metadata[i]['timepoint']: my_metadata[i]['egg_age'] for i in range(0, len(my_metadata)) } # Exclude larval animals from ghost_age computation. if regression_variable.lower() == 'ghost_age': time_name = a_point.split(os.path.sep)[-1].split(' ')[0] if egg_age_dict[time_name] > 0: do_point = True else: do_point = False if do_point: my_time = a_point.split(os.path.sep)[-1].split(' ')[0] my_age = metadata_dict[my_time] / 24 mask_file = freeimage.read(a_point) image_file = freeimage.read(a_point.replace('hmask.png', 'bf.png')) my_samples = sample_8star(image_file, mask_file, 17, sample_number=samples_per_image) my_codebook = np.zeros(texture_model.cluster_vectors.shape[0]) for a_sample in my_samples: my_codebook[texture_model.classify_vector(a_sample)] += 1 my_codebook = my_codebook / np.sum(my_codebook) histogram_array.append(my_codebook) age_array.append(my_age) return (histogram_array, age_array)
def preprocess_image(self, i): downscale = self.downscale lab_frame_image = freeimage.read(self.timepoint_list[i].image_path('bf')) lab_frame_image = lab_frame_image.astype(numpy.float32) height, width = lab_frame_image.shape[:2] try: metadata = self.timepoint_list[i].position.experiment.metadata optocoupler = metadata['optocoupler'] except KeyError: optocoupler = 1 mode = process_images.get_image_mode(lab_frame_image, optocoupler=optocoupler) #### DownSample the image if downscale > 0 and downscale != 1:#and set_name!='train': #t_size = (int(width / downscale), int(height / downscale)) shrink_image = pyramid.pyr_down(lab_frame_image, downscale=downscale) #shrink_image = numpy.clip(shrink_image, 0, 40000) else: shrink_image = lab_frame_image shrink_image = shrink_image.astype(numpy.float32) ## scale the image pixel value into a trainable range # map image image intensities in range (100, 2*mode) to range (0, 2) bf = colorize.scale(shrink_image, min=100, max=2*mode, output_max=2) # now shift range to (-1, 1) bf -= 1 return bf
def set_well(self, index): self.well_index = index well_name = self.well_names[index] images = [freeimage.read(str(image)) for image in sorted(self.date_dir.glob('well_images/{}-*.png'.format(well_name)))] self.animator.start(images) self.well = self.well_names[index] self.set_status(self.statuses[self.well_index])
def generate_grader(generate_specific_worm_from_parameters, mask_worm, mask_scorer, my_PCA, standard_mask_file, which_fixed = None, fixed_parameters = None): ''' Generates a function that will grade a worm generated from parameters against standard_mask. It takes as input: generate_specific_worm_from_parameters: a function which will generate a set of outline points when given the mean worm as a set of outline points, the PCA object with the linear weights for each PC, a point around which to center the worm, and a set of weights to apply to the PC object. mask_worm: a function that will take a worm from a set of points and make a rasterized mask for comparison. mask_scorer: a function that will score the "goodness" of fit when given two masks of compatible size. my_PCA: an object with results from principal component analysis of the data. standard_mask_file: the file containing the mask that we want to fit our worm to. ''' standard_mask = freeimage.read(standard_mask_file) def my_grader(my_parameters): if which_fixed == None: my_fixed_parameters = np.array([False]*my_parameters.shape[0]) my_which_fixed = np.array([False]*my_parameters.shape[0]) else: my_fixed_parameters = fixed_parameters my_which_fixed = which_fixed my_real_parameters = np.zeros(my_which_fixed.shape) my_real_parameters[my_which_fixed] = my_fixed_parameters[my_which_fixed] my_real_parameters[np.invert(my_which_fixed)] = my_parameters test_worm = generate_specific_worm_from_parameters(my_PCA, my_real_parameters) test_mask = mask_worm(test_worm, my_PCA, my_real_parameters, standard_mask.shape) my_score = mask_scorer(test_mask, standard_mask) return my_score return my_grader
def _start_autofocus(self, metric='brenner', metric_kws=None, metric_mask=None, metric_filter_period_range=None): if isinstance(metric_mask, str): metric_mask = freeimage.read(metric_mask) > 0 shape = self._camera.get_aoi_shape() if isinstance(metric, str): if metric in self._METRICS: metric = self._METRICS[metric] elif ':' in metric: path, metric = metric.split(':') metric = runpy.run_path(path)[metric] else: raise ValueError( '"metric" must be the name of a known metric or formatted as "/path/to/file.py:function"' ) if metric_kws is None: metric_kws = {} # check if metric is a class at all before asking if it's our subclass of interest: if isinstance(metric, type) and issubclass(metric, AutofocusMetricBase): return metric(shape, mask=metric_mask, fft_period_range=metric_filter_period_range, **metric_kws) else: assert callable(metric) return AutofocusMetric(metric, shape, mask=metric_mask, fft_period_range=metric_filter_period_range, **metric_kws)
def generate_images_from_files(image_files, upper_left=(0, 0), lower_right=(None, None), min=None, max=None, gamma=1, color=(255, 255, 255)): """Load images from a file, optionally cropping, scaling, and colorizing them before converting to 8 bit. Each image is yielded as it is loaded and transformed. Parameters: image_files: list of image files to read upper_left: (x, y) coordinates of upper left corner of region to include lower_right: (x, y) coordinates of lower right corner of region to include (use None to use full image extent). min, max: image intensity values to map to black and white, respectively. If None, use each image's min and max value. gamma: gamma value for intensity transformation. color: 8-bit (R,G,B) color to map "white" to. By default this is white: (255, 255, 255). To map the brightest possible color to green instead use (0, 255, 0), for example. """ x1, y1 = upper_left x2, y2 = lower_right for image_file in image_files: image = freeimage.read(image_file) cropped_image = image[x1:x2, y1:y2] scaled_image = colorize.scale(cropped_image, min, max, gamma, output_max=1) colorized_8bit_image = colorize.color_tint(scaled_image, color).astype(numpy.uint8) yield colorized_8bit_image
def process_centerline_dir(source_dir, microns_per_pixel): source_dir = pathlib.Path(source_dir) out_dir = source_dir / 'individual_centerlines' out_dir.mkdir(exist_ok=True) centerline_data = {} centerline_data_entries = ['name', 'length'] mask_data = {} [mask_data.setdefault(entry,[]) for entry in centerline_data_entries] for centerline_image_path in sorted(source_dir.iterdir()): if centerline_image_path.suffix[1:] != 'png': continue aggregate_centerline_image = freeimage.read(centerline_image_path) masks = parse_aggregate_centerlines(aggregate_centerline_image) for mask_num, mask in enumerate(masks): mask_name = centerline_image_path.stem + f'_{mask_num}' print(mask_name) freeimage.write(mask.astype('uint8')*255, out_dir / (mask_name+'.png')) center_tck, _ = worm_spline.pose_from_mask(mask) # Toss the widths try: length = spline_geometry.arc_length(center_tck) * microns_per_pixel mask_data['name'].append(mask_name) mask_data['length'].append(length) except TypeError: print(f'Warning: couldn\'t find centerline for {mask_name} (px location {list(numpy.where(mask))})') with (out_dir / 'measurements.txt').open('w+') as measurement_file: measurement_file.write('\t'.join(centerline_data_entries)+'\n') for data in zip(*[mask_data[entry] for entry in centerline_data_entries]): measurement_file.write('\t'.join([str(item) for item in data])+'\n')
def warp_image(spine_tck, width_tck, image_file, warp_file): """Warp an image of a worm to a specified place Parameters: spine_tck: parametric spline tck tuple corresponding to the centerline of the worm width_tck: non-parametric spline tck tuple corresponding to the widths of the worm image_file: path to the image to warp the worm from warp_file: path where the warped worm image should be saved to """ image = freeimage.read(image_file) warp_file = pathlib.Path(warp_file) #730 was determined for the number of image samples to take perpendicular to the spine #from average length of a worm (as determined from previous tests) warped = resample.warp_image_to_standard_width(image, spine_tck, width_tck, width_tck, int(tck[0][-1] // 5)) #warped = resample.sample_image_along_spline(image, spine_tck, 730) mask = resample.make_mask_for_sampled_spline(warped.shape[0], warped.shape[1], width_tck) warped = colorize.scale(warped).astype('uint8') warped[~mask] = 255 print("writing warped worm to :" + str(warp_file)) #return warped if not warp_file.exists(): warp_file.parent.mkdir(exist_ok=True) freeimage.write( warped, warp_file ) # freeimage convention: image.shape = (W, H). So take transpose.
def _read_page_task(self, task_page): task_page.ims = [ freeimage.read(str(image_fpath)) for image_fpath in task_page.im_fpaths ] Qt.QApplication.instance().postEvent(self, _ReadPageTaskDoneEvent(task_page))
def color_dots(image_paths, save_paths, color_dot_location_lists): ''' Draws colored dots on images from image_paths according to color_dot_location_lists, and saves them out to save_paths. ''' color_dot_location_lists = np.round(color_dot_location_lists) for i in range(0, len(image_paths)): image_array = freeimage.read(image_paths[i]) print('Drawing dots for ' + image_paths[i] + '.') if len(image_array.shape) == 2: my_width, my_height = image_array.shape color_array = np.empty((my_width, my_height, 3), dtype = image_array.dtype) color_array[:, :, 0] = image_array.copy() color_array[:, :, 1] = image_array.copy() color_array[:, :, 2] = image_array.copy() elif len(image_array.shape) == 3: color_array = image_array color_array[color_dot_location_lists[0][i][0], color_dot_location_lists[0][i][1], :] = [0, 0, 0] if len(color_dot_location_lists) > 1: color_array[color_dot_location_lists[1][i][0], color_dot_location_lists[1][i][1], :] = [0, 0, 0] if len(color_dot_location_lists) > 2: color_array[color_dot_location_lists[2][i][0], color_dot_location_lists[2][i][1], :] = [0, 0, 0] color_array[color_dot_location_lists[0][i][0], color_dot_location_lists[0][i][1], 0] = -1 if len(color_dot_location_lists) > 1: color_array[color_dot_location_lists[1][i][0], color_dot_location_lists[1][i][1], 1] = -1 if len(color_dot_location_lists) > 2: color_array[color_dot_location_lists[2][i][0], color_dot_location_lists[2][i][1], 2] = -1 freeimage.write(color_array, save_paths[i]) return
def assemble_image_sequence(out_dir, well_name, crop=True): out_dir = pathlib.Path(out_dir) well_images = collections.defaultdict(list) for img in sorted(out_dir.glob('*/well_images/{}-*.png'.format(well_name))): date = img.parent.parent.name well_images[date].append(freeimage.read(str(img))) dates, images = zip(*sorted(well_images.items())) maxlen = max(len(ims) for ims in images) shapes = numpy.array([ims[0].shape for ims in images]) if crop: shape = shapes.min(axis=0) else: shape = shapes.max(axis=0) new_images = [] for ims in images: oldshape = ims[0].shape extra = numpy.abs(shape - oldshape)/2 if numpy.any(extra): extra = list(zip(numpy.ceil(extra).astype(int), extra.astype(int))) if crop: (xl, xh), (yl, yh) = extra xh = -xh if xh else None yh = -yh if yh else None out = [i[xl:xh, yl:yh] for i in ims] else: out = [numpy.pad(i, extra, 'constant') for i in ims] else: out = ims extra_ims = maxlen - len(ims) if extra_ims: out += out[-1:]*extra_ims new_images.append(out) images_out = [numpy.concatenate([ims[i] for ims in new_images]) for i in range(maxlen)] return images_out, shape
def _find_worms_task(image_path, well): print('Finding worm '+well) image = freeimage.read(image_path) well_mask, edges, worm_mask = find_worm.find_worm_from_brightfield(image) freeimage.write(well_mask.astype(numpy.uint8)*255, image_path.parent / (well + '_well_mask.png')) freeimage.write(worm_mask.astype(numpy.uint8)*255, image_path.parent / (well + '_worm_mask.png')) return is_valid_mask(worm_mask)
def straighten_worms_from_rw(rw, warp_path): warp_dir = pathlib.Path(warp_path) if not warp_dir.exists(): warp_dir.mkdir() current_idx = rw.flipbook.current_page_idx img, sx, sy = rw.flipbook.pages[current_idx].img_path bf_img_file = get_bf_image(img) bf_img = freeimage.read(bf_img_file) #need to crop image like the risWidget ones x = slice(max(0, sx.start - 50), min(bf_img.shape[0], sx.stop + 50)) y = slice(max(0, sy.start - 50), min(bf_img.shape[1], sy.stop + 50)) crop_img = bf_img[x, y] warp_name = bf_img_file.stem.split(" ")[0] + "_" + str( current_idx) + "_warp.png" traceback = rw.flipbook.pages[current_idx].spline_data dist = rw.flipbook.pages[current_idx].dist_data #print("worm length: ",len(traceback)) tck = skeleton.generate_splines(traceback, dist) #print("tck length: ",len(tck)) width_tck = skeleton.width_spline(traceback, dist) warp_image(tck, width_tck, crop_img, warp_dir.joinpath(warp_name))
def flatfield_correct(im_fpath, ff_fpath, ffc_fpath): if not im_fpath.exists(): return False, 'skipping "{}" (file not found)'.format(str(im_fpath)) if not ff_fpath.exists(): return False, 'skipping "{}" (flatfield reference image file "{}" not found)'.format(str(ff_fpath)) try: im = freeimage.read(str(im_fpath)) ff = freeimage.read(str(ff_fpath)) ffc = im.astype(numpy.float32) * ff ffc *= (65535.0 * 0.9) / float(numpy.percentile(ffc, 98)) ffc[ffc < 0] = 0 ffc[ffc > 65535] = 65535 freeimage.write(ffc.astype(numpy.uint16), str(ffc_fpath), freeimage.IO_FLAGS.PNG_Z_BEST_SPEED) except Exception as e: return False, 'exception while correcting "{}": {}'.format(str(im_fpath), e) return True, '{} done'.format(str(im_fpath))
def corrected_worm_frame_image(position_root, timepoint, image_type, center_tck, optocoupler=None): if image_type == 'bf': image = freeimage.read(position_root / f'{timepoint} {image_type}.png') image = pin_image_mode(image, optocoupler=optocoupler) else: image = flatfield_correct(position_root, timepoint, image_type) return worm_spline.to_worm_frame(image, center_tck)
def lawn_maker(bf_files, super_vignette): ''' Find the bacterial lawn in one worm image. ''' lawn_masks = [] for a_bf_file in bf_files: # Prepare a worm image for use in lawn-finding. renormalized_image = freeimage.read(a_bf_file) renormalized_image = cv2.medianBlur(renormalized_image, 3) renormalized_image = imageOperations.renormalize_image(renormalized_image) # Remove extraneous edges and out-of-lawn junk by finding the lawn and also applying an "ultra-vignette" mask. ultra_vignette = scipy.ndimage.morphology.binary_erosion(super_vignette, iterations = 10) my_edges = skimage.feature.canny(renormalized_image, sigma = 0.02) my_edges[np.invert(ultra_vignette)] = False my_edges = scipy.ndimage.morphology.binary_dilation(my_edges, iterations = 10) my_lawn = scipy.ndimage.morphology.binary_fill_holes(my_edges) try: my_lawn = zplib_image_mask.get_largest_object(my_lawn).astype('bool') my_lawn = scipy.ndimage.morphology.binary_erosion(my_lawn, iterations = 10) my_lawn = zplib_image_mask.get_largest_object(my_lawn).astype('bool') except: my_lawn = np.zeros(my_lawn.shape).astype('bool') lawn_masks.append(my_lawn) my_lawn = np.max(np.array(lawn_masks), axis = 0) return my_lawn
def train_texture_samples(subdir, samples_dict, regression_variable, endings, samples_per_image, age_ranges): ''' Read in samples for texture classification. ''' # Organize some information. total_files = os.listdir(subdir) data_points = [ ' '.join(a_file.split('.')[0].split(' ')[0:-1]) for a_file in total_files if a_file.split(' ')[-1] == 'hmask.png' ] with open(subdir + os.path.sep + 'position_metadata_extended.json', 'r') as read_file: my_metadata = json.loads(read_file.read()) metadata_dict = { my_metadata[i]['timepoint']: my_metadata[i][regression_variable.lower()] for i in range(0, len(my_metadata)) } egg_age_dict = { my_metadata[i]['timepoint']: my_metadata[i]['egg_age'] for i in range(0, len(my_metadata)) } # Exclude larval animals from ghost_age computation. if regression_variable.lower() == 'ghost_age': data_points = [ a_point for a_point in data_points if egg_age_dict[a_point] > 0 ] # Actualyl sample my images. for a_point in data_points: my_age = metadata_dict[a_point] / 24 if regression_variable.lower() == 'ghost_age': my_age = abs(my_age) mask_file = freeimage.read(subdir + os.path.sep + a_point + ' ' + endings[1]) image_file = freeimage.read(subdir + os.path.sep + a_point + ' ' + endings[0]) my_samples = sample_8star(image_file, mask_file, 17, sample_number=samples_per_image) for age_range in age_ranges: if age_range[0] <= my_age < age_range[1]: samples_dict[age_range].extend(my_samples) return samples_dict
def normalized_bf_image(self, i): bf = freeimage.read(self.timepoint_list[i].image_path('bf')) mode = process_images.get_image_mode(bf, optocoupler=self.timepoint_list.optocoupler(i)) # map image image intensities in range (100, 2*mode) to range (0, 2) bf = colorize.scale(bf, min=100, max=2*mode, output_max=2) # now shift range to (-1, 1) bf -= 1 return bf
def load_images_fromfns(image_fns, filter_kw='', master_vig=None): image_list = [] for image_fn in image_fns: image = freeimage.read(image_fn) if master_vig is not None: image[master_vig == 0] = 0 image_list.append(image) return image_list
def OLDoverallBackgroundSubtract(data_dir, match_string, temporal_radius, save_dir): ''' Do background subtraction to find worms. ''' my_files = sorted(os.listdir(data_dir)) my_files = [a_file for a_file in my_files if match_string == a_file.split('_')[-1]] # Intialize my special background context. temp_folder = save_dir + '\\' + 'temp' try: os.stat(temp_folder) except: os.mkdir(temp_folder) for i in range(0, temporal_radius): shutil.copy(data_dir + '\\' + my_files[i], temp_folder + '\\' + my_files[i]) # Run the actual simple subtraction, saving out masked files. for i in range(temporal_radius, len(my_files)-temporal_radius): #context_files = [freeimage.read(data_dir + '\\' + my_files[j]) for j in range(i-temporal_radius, i+temporal_radius+1)] context_files = [freeimage.read(data_dir + '\\' + my_files[j]) for j in range(i-temporal_radius, i+1)] raw_file = freeimage.read(data_dir + '\\' + my_files[i]) (simple_foreground_file, background_file) = simple_running_median_subtraction(raw_file, context_files) thresholded_mask = percentile_floor(simple_foreground_file, threshold_proportion = 0.975) final_mask = clean_dust_and_holes(thresholded_mask) raw_file[final_mask.astype('bool')] = background_file[final_mask.astype('bool')] freeimage.write(raw_file, temp_folder + '\\' + my_files[i]) # Fill in remaining tail files. for i in range(len(my_files)-temporal_radius, len(my_files)): shutil.copy(data_dir + '\\' + my_files[i], temp_folder + '\\' + my_files[i]) # Now let's do it for real! for i in range(temporal_radius, len(my_files)-temporal_radius): context_files = [freeimage.read(temp_folder + '\\' + my_files[j]) for j in range(i-temporal_radius, i+temporal_radius+1)] raw_file = freeimage.read(data_dir + '\\' + my_files[i]) (simple_foreground_file, background_file) = simple_running_median_subtraction(raw_file, context_files) thresholded_pic = percentile_floor(simple_foreground_file, threshold_proportion = 0.975) final_mask = clean_dust_and_holes(thresholded_pic) freeimage.write(final_mask, save_dir + '\\' + my_files[i]) return
def overlay_masks(rw, position_directory): position_directory = pathlib.Path(position_directory) expt_dir = position_directory.parent position_annotations = load_data.read_annotations(expt_dir)[position_directory.name] files_to_load = [] page_names = [] global_positions, timepoint_annotations = position_annotations for timepoint, timepoint_data in timepoint_annotations.items(): image_key = position_directory.name + '_' + timepoint image = freeimage.read(str(position_directory / (timepoint + ' bf.png'))) mask_file = expt_dir / 'derived_data' / 'mask' / position_directory.name / (timepoint + ' bf.png') if mask_file.exists(): mask_image = freeimage.read(str(expt_dir / 'derived_data' / 'mask' / position_directory.name / (timepoint + ' bf.png'))) > 0 files_to_load.append([image, mask_image]) else: files_to_load.append([image]) rw.flipbook_pages = files_to_load
def save_mask_lcc(experiment_root): experiment_root = pathlib.Path(experiment_root) mask_root = experiment_root / 'derived_data' / 'mask' for position_mask_root in sorted(mask_root.iterdir()): for mask_file in sorted(position_mask_root.iterdir()): mask_image = freeimage.read(str(mask_file)) > 0 new_mask = mask.get_largest_object(mask_image).astype(numpy.uint8) freeimage.write(new_mask*255, str(mask_file))
def _start_autofocus(self, focus_filter_period_range, focus_filter_mask, **camera_state): camera_state.update(self._CAMERA_MODE) self._camera.push_state(**camera_state) if focus_filter_mask is not None: focus_filter_mask = freeimage.read(focus_filter_mask) > 0 self._metric = BrennerAutofocus(self._camera.get_aoi_shape(), focus_filter_period_range, focus_filter_mask)
def size_histogram(a_directory): ''' return a list of sizes ''' my_files = [a_directory + os.path.sep + a_file for a_file in os.listdir(a_directory)] my_images = [freeimage.read(a_file) for a_file in my_files] my_masks = [an_image[:, :, 0].astype('bool') for an_image in my_images] my_sizes = [np.sum(a_mask) for a_mask in my_masks] return my_sizes
def crop_img(rw): current_idx = rw.flipbook.current_page_idx img, sx, sy = rw.flipbook.pages[current_idx].img_path bf_img_file = get_bf_image(img) bf_img = freeimage.read(bf_img_file) #need to crop image like the risWidget ones x = slice(max(0, sx.start - 50), min(bf_img.shape[0], sx.stop + 50)) y = slice(max(0, sy.start - 50), min(bf_img.shape[1], sy.stop + 50)) crop_img = bf_img[x, y]
def overallBackgroundSubtract(data_dpath, match_glob, temporal_radius, save_dpath, save_dpath2 = '', save_dpath3 = '', demonstration_mode = False): ''' Do background subtraction to find worms. This uses only past data, masking out the worms to create a background that won't disappear once the worm stops moving. ''' data_dpath = Path(data_dpath) save_dpath = Path(save_dpath) if save_dpath2: save_dpath2 = Path(save_dpath2) if save_dpath3: save_dpath3 = Path(save_dpath3) my_file_fpaths = sorted(data_dpath.glob(match_glob)) # Initialize my special background context. temp_dpath = save_dpath / 'temp' if not temp_dpath.exists(): temp_dpath.mkdir(parents=True) for i in range(0, temporal_radius): shutil.copy(str(my_file_fpaths[i]), str(temp_dpath / my_file_fpaths[i].name)) # Run the actual simple subtraction, saving out masked files. context_files = [freeimage.read(str(my_file_fpaths[j])) for j in range(0, temporal_radius)] for i in range(temporal_radius, len(my_file_fpaths)): real_raw_file = freeimage.read(str(my_file_fpaths[i])) raw_file = real_raw_file.copy() context_files.append(raw_file) (foreground_file, background_file) = simple_running_median_subtraction(raw_file, context_files) thresholded_mask = percentile_floor(foreground_file, threshold_proportion = 0.975) final_mask = clean_dust_and_holes(thresholded_mask) raw_file[final_mask.astype('bool')] = background_file[final_mask.astype('bool')] if demonstration_mode: freeimage.write(real_raw_file, str(save_dpath / my_file_fpaths[i].name)) freeimage.write(background_file, str(save_dpath2 / my_file_fpaths[i].name)) freeimage.write(final_mask, str(save_dpath3 / my_file_fpaths[i].name)) if not demonstration_mode: freeimage.write(raw_file, str(temp_dpath / my_file_fpaths[i].name)) freeimage.write(final_mask,str(save_dpath / my_file_fpaths[i].name)) context_files = context_files[1:] return
def view_slices_experiment(expt_dir, positions, calibration_dir, super_vignette, rw, measurement_name=None, slices=None): """Straighten a bunch of worms and then put them up on risWidget for QC """ expt_dir = pathlib.Path(expt_dir) annotation_dir = expt_dir / 'annotations' calibration_dir = pathlib.Path(calibration_dir) super_vignette = pickle.load(open(super_vignette, 'rb')) worm_measurements = collections.OrderedDict() #iterate through the worms for worm, timepoints in positions.items(): print("Measuring worm: " + worm) annotation_file = list(annotation_dir.glob('*' + worm + '.pickle'))[0] _, annotations = pickle.load(open(annotation_file, 'rb')) for tp, images in timepoints.items(): #normalize gfp image raw_image = freeimage.read(images[0]) bf_image = freeimage.read(images[1]) flatfield_image = freeimage.read(calibration_dir / (tp + " fl_flatfield.tiff")) corrected_gfp = normalize_gfp_image(raw_image, super_vignette, flatfield_image) #warp worm to unit worm tcks = annotations[tp]['pose'] warped_image, mask = warp_image(tcks, corrected_gfp) warped_bf, mask = warp_image(tcks, bf_image) if slices is not None: for measure, slc in slices.items(): #print("Measuring slice: "+measure) image_slice, mask_slice = slice_worms( warped_image, mask, slc) bf_slice, mask_slice = slice_worms(warped_bf, mask, slc) #print(image_slice, bf_slice) rw.flipbook_pages.append( [image_slice, bf_slice, mask_slice]) rw.flipbook_pages[-1].name = (worm + " " + tp + " " + measure)
def normalized_bf_image(timepoint): """Given a timepoint, return a normalized brightfield image.""" bf = freeimage.read(timepoint.image_path('bf')) mode = process_images.get_image_mode( bf, optocoupler=timepoint.position.experiment.metadata['optocoupler']) # map image image intensities in range (100, 2*mode) to range (0, 2) bf = colorize.scale(bf, min=100, max=2 * mode, output_max=2) # now shift range to (-1, 1) bf -= 1 return bf
def calculate_iou(prediction, ground_truth, plot_val=False, save_val=False, save_dir=None, pyr=False): """Find intersection over union for 2 images Prediction and ground_truth are boolean arrays """ pred_orig = freeimage.read(prediction) gt_orig = freeimage.read(ground_truth) folder, worm_id = ground_truth.parts[-2:] worm_id = worm_id.split(' ')[0] #get rid of stuff touching the edges if pyr: pred = mask.remove_edge_objects(pred_orig) gt = mask.remove_edge_objects(gt_orig) #find the worm in the mask (largest object presumably) pred_image = mask.get_largest_object(pred) ground_truth = mask.get_largest_object(gt ) else: #find the worm in the mask (largest object presumably) pred_image = mask.get_largest_object(pred_orig) ground_truth = mask.get_largest_object(gt_orig) #find intersect and union intersect = (pred_image & ground_truth) union = (pred_image|ground_truth) #plot for validation if save_val: #maybe change this to not be this save_file = save_dir+"/"+folder+"_"+worm_id+"_val.png" #if willie: # save_file = '/home/nicolette/Documents/lab_stuff/worm_segmentation_validation/Willie_iou/'+folder+"_"+worm_id+"_val.png" #else: # save_file = '/home/nicolette/Documents/lab_stuff/MATLAB_scripts/binarySeg_v2/figFolder/background_sub_pyr/iou/'+prediction.stem+"_val.png" print("saving: "+save_file) plot_validation(pred_orig, gt_orig, intersect, union, save_val=True, save_file=save_file) if plot_val: plot_validation(pred_orig, gt_orig, intersect, union) return intersect.sum()/union.sum()
def extract_mask_fromcomposite_batch(comp_path, save_path, comp_str='', save_str=''): try: os.stat(save_path) except: os.mkdir(save_path) [freeimage.write( (freeimage.read(comp_path+os.path.sep+comp_f) == 255).astype('uint16')*65535,save_path+os.path.sep+comp_f[:-4]+save_str+comp_f[-4:]) \ for comp_f in sorted(os.listdir(comp_path))]
def read_grayscale_array_from_image_file(filename, warn = True): """Read an image from disk into a 2-D grayscale array, converting from color if necessary. If 'warn' is True, issue a warning when arrays are converted from color to grayscale. """ image_array = freeimage.read(filename) if len(image_array.shape) == 3: image_array = make_grayscale_array(image_array) if warn: warn_tools.warn('Image %s converted from RGB to grayscale: intensity values have been scaled and combined.'%filename) return image_array
def get_worm(directory_bolus, a_worm, a_time, box_size = None, get_mode = 'worm'): ''' Get a cut-out of a_worm at a_time. ''' # Cut out the chunk that I want from the right image. image_file = directory_bolus.working_directory + os.path.sep + a_worm + os.path.sep + a_time + ' ' + 'bf.png' if get_mode == 'fluorescence': worm_directory = [a_dir for a_dir in directory_bolus.data_directories if ' '.join(a_worm.split(' ')[:-2]) + ' Run ' + a_worm.split(' ')[-2] in a_dir][0] + os.path.sep + a_worm.split(' ')[-1] image_file = worm_directory + os.path.sep + a_time + ' ' + 'green_yellow_excitation_autofluorescence.png' my_image = corrected_fluorescence(image_file) else: my_image = freeimage.read(image_file) # Get the right mask. if get_mode in ['worm', 'fluorescence']: mask_file = directory_bolus.working_directory + os.path.sep + a_worm + os.path.sep + a_time + ' ' + 'mask.png' elif get_mode == 'lawn': worm_directory = [a_dir for a_dir in directory_bolus.data_directories if ' '.join(a_worm.split(' ')[:-2]) + ' Run ' + a_worm.split(' ')[-2] in a_dir][0] + os.path.sep + a_worm.split(' ')[-1] mask_file = worm_directory + os.path.sep + 'great_lawn.png' if os.path.exists(mask_file): my_mask = freeimage.read(mask_file).astype('bool') else: raise BaseException('Can\'t access files.') # Mask out non-worm for fluorescence mode. if get_mode == 'fluorescence': my_image[np.invert(my_mask)] = 0 # Ensure that the final square is the right shape. (square_mask, actual_size) = bound_box(my_mask, box_size = box_size) my_square = my_image[square_mask] my_square = np.reshape(my_square, actual_size) box_size = (box_size, box_size) if actual_size[0] < box_size[0]: my_square = np.concatenate([my_square, np.zeros((box_size[0] - actual_size[0], my_square.shape[1])).astype('uint16')], axis = 0) if actual_size[1] < box_size[1]: my_square = np.concatenate([my_square, np.zeros((my_square.shape[0], box_size[1] - actual_size[1])).astype('uint16')], axis = 1) if (my_square.shape[0]//2, my_square.shape[1]//2) != box_size: raise BaseException('') return my_square
def lawn_distribution(lawn_folder): ''' Find the distribution of lawn sizes in a folder. ''' def size_object(a_mask): ''' Find the two points farthest apart in a mask and return their distance from each other. ''' locations = np.array(np.ma.nonzero(a_mask)).transpose() random_point = locations[0] point_a = locations[np.linalg.norm(locations - random_point, axis = 1).argmax()] point_b = locations[np.linalg.norm(locations - point_a, axis = 1).argmax()] my_distance = np.linalg.norm(point_a - point_b) return my_distance my_lawns = [freeimage.read(lawn_folder + os.path.sep + an_image).astype('bool') for an_image in os.listdir(lawn_folder) if an_image != 'vignette_mask.png'] my_lawns = [zplib_image_mask.get_largest_object(my_lawn).astype('bool') for my_lawn in my_lawns] my_vignette = freeimage.read(lawn_folder + os.path.sep + 'vignette_mask.png').astype('bool') lawn_sizes = [size_object(my_lawn) for my_lawn in my_lawns] field_size = size_object(my_vignette) return (lawn_sizes, field_size)
def egg_outlines(a_directory): ''' For each outlined egg mask in a_directory, convert it to a grayscale 8-bit image with the outline in white and the rest of the image in black. ''' for a_subdir in os.listdir(a_directory): for an_image in os.listdir(a_directory + os.path.sep + a_subdir): if an_image.split(' ')[-1] == 'bf.png': filepath = a_directory + os.path.sep + a_subdir + os.path.sep + an_image my_image = freeimage.read(filepath) masked_conversion = fill_colored_outline(my_image, egg_mode = True) outline_conversion = fill_colored_outline(my_image, egg_mode = True, outline_only = True) freeimage.write(masked_conversion, filepath.replace('bf', 'emask')) freeimage.write(outline_conversion, filepath.replace('bf', 'outline')) return
def train_texture_SVM_sample(data_points, regression_variable, samples_per_image, texture_model): ''' Get sample histograms for texture classification SVM training. ''' histogram_array = [] age_array = [] for a_point in data_points: do_point = True subdir = os.path.sep.join(a_point.split(os.path.sep)[:-1]) with open(subdir + os.path.sep + 'position_metadata_extended.json', 'r') as read_file: my_metadata = json.loads(read_file.read()) metadata_dict = {my_metadata[i]['timepoint']: my_metadata[i][regression_variable.lower()] for i in range(0, len(my_metadata))} egg_age_dict = {my_metadata[i]['timepoint']: my_metadata[i]['egg_age'] for i in range(0, len(my_metadata))} # Exclude larval animals from ghost_age computation. if regression_variable.lower() == 'ghost_age': time_name = a_point.split(os.path.sep)[-1].split(' ')[0] if egg_age_dict[time_name] > 0: do_point = True else: do_point = False if do_point: my_time = a_point.split(os.path.sep)[-1].split(' ')[0] my_age = metadata_dict[my_time]/24 mask_file = freeimage.read(a_point) image_file = freeimage.read(a_point.replace('hmask.png', 'bf.png')) my_samples = sample_8star(image_file, mask_file, 17, sample_number = samples_per_image) my_codebook = np.zeros(texture_model.cluster_vectors.shape[0]) for a_sample in my_samples: my_codebook[texture_model.classify_vector(a_sample)] += 1 my_codebook = my_codebook/np.sum(my_codebook) histogram_array.append(my_codebook) age_array.append(my_age) return (histogram_array, age_array)
def colored_color_outlines(a_directory): ''' For each outlined worm in a_directory, convert it to a grayscale 8-bit image with the outline in white and the rest of the image in black. ''' for an_image in os.listdir(a_directory): if 'new' not in an_image: filepath = a_directory + os.path.sep + an_image my_image = freeimage.read(filepath) my_red = np.array([237, 28, 36]) is_red = np.abs(my_image[:, :, :3] - my_red) is_red = (is_red.mean(axis = 2) < 1) new_image = np.zeros(my_image.shape[:2]).astype('uint8') new_image[is_red] = [-1] freeimage.write(new_image, filepath.replace('.png', '_new.png')) return
def corrected_fluorescence(image_location): ''' Read in a fluroescence image corrected for flatfield and hot pixels. ''' # Figure out where everything is. split_pathsep = image_location.split(os.path.sep) experiment_directory = os.path.sep.join(split_pathsep[:-2]) calibration_directory = experiment_directory + os.path.sep + 'calibrations' time_point = split_pathsep[-1].split(' ')[0] hot_threshold = 500 pickle_file = experiment_directory + os.path.sep + 'super_vignette.pickle' if os.path.isfile(pickle_file): with open(pickle_file, 'rb') as my_file: super_vignette = pickle.load(my_file) else: raise BaseException('Missing super vignette!') # Read in image and apply vignetting. image_path = image_location raw_image = freeimage.read(image_path) raw_image[np.invert(super_vignette)] = 0 # Correct for flatfield. flatfield_path = calibration_directory + os.path.sep + time_point + ' ' + 'fl_flatfield.tiff' calibration_image = freeimage.read(flatfield_path) corrected_image = raw_image*calibration_image # Correct for hot pixels. median_image = scipy.ndimage.filters.median_filter(corrected_image, size = 3) difference_image = np.abs(corrected_image.astype('float64') - median_image.astype('float64')).astype('uint16') hot_pixels = difference_image > hot_threshold median_image_hot_pixels = median_image[hot_pixels] corrected_image[hot_pixels] = median_image_hot_pixels # Return the actual image. return corrected_image
def _compress(self, image_path): image_path = pathlib.Path(image_path) assert image_path.suffix == '.png' image = freeimage.read(image_path) temp = tempfile.NamedTemporaryFile(dir=image_path.parent, prefix=image_path.stem + 'compressing_', suffix='.png', delete=False) try: freeimage.write(image, temp.name, flags=self.level) os.replace(temp.name, image_path) except: if os.path.exists(temp.name): os.unlink(temp.name) raise finally: temp.close()
def make_well_mask(out_dir, image_file, ignore_previous=False): """Calculate and store well mask if necessary. Parameters: out_dir: directory where well_mask.png should exist or be created. image_file: path to an image to create the mask from, if it doesn't exist. ignore_previous: if True, re-make mask even if it alredy exists on disk. """ out_dir = pathlib.Path(out_dir) well_mask_f = out_dir / 'well_mask.png' if ignore_previous or not well_mask_f.exists(): image = freeimage.read(image_file) if image.dtype == numpy.uint16: image = (image >> 8).astype(numpy.uint8) well_mask = extract_wells.get_well_mask(image) freeimage.write((well_mask * 255).astype(numpy.uint8), str(well_mask_f))
def measure_incyte_images(image_dir, image_glob='*FITC*'): image_dir = pathlib.Path(image_dir) assert image_dir.exists() image_files = list(image_dir.glob(image_glob)) well_names = [] for image_file in sorted(image_files): row = image_file.name[0] # first letter is row, then ' - ', then two-digit col col = image_file.name[4:6] well = row + col well_names.append(well) data_rows = [] for image_file in image_files: print(str(image_file)) image = freeimage.read(image_file) worm_mask = find_worm.find_worm_from_fluorescence(image) data_rows.append(measure_fluorescence(image, worm_mask)[0]) write_measures(data_rows, well_names, image_dir.with_suffix('.csv'))
def _computeFocusMeasures(bgs, im_fpath, measure_mask, compute_measures, write_models, write_deltas, write_masks): try: im = freeimage.read(str(im_fpath)) except: return if bgs.model is not None: # NB: Model and delta are written as float32 tiffs try: if write_models: freeimage.write( bgs.model, str(im_fpath.parent / "{} wz_bgs_model.tiff".format(im_fpath.stem)), freeimage.IO_FLAGS.TIFF_DEFLATE, ) delta = numpy.abs(bgs.queryModelDelta(im)) if write_deltas: freeimage.write( delta, str(im_fpath.parent / "{} wz_bgs_model_delta.tiff".format(im_fpath.stem)), freeimage.IO_FLAGS.TIFF_DEFLATE, ) mask = bgs.queryModelMask(im, delta) antimask = mask == 0 if write_masks: freeimage.write( (mask * 255).astype(numpy.uint8), str(im_fpath.parent / "{} wz_bgs_model_mask.png".format(im_fpath.stem)), ) except: return if compute_measures: focus_measures = {} focus_measures["whole_image_hp_brenner_sum_of_squares"], focus_measures[ "whole_image_bp_brenner_sum_of_squares" ] = MaskedMultiBrenner((2560, 2160)).metric(im, measure_mask) model_delta_squares = delta.astype(numpy.float64) ** 2 model_delta_squares[~measure_mask] = 0 focus_measures["model_delta_sum_of_squares"] = model_delta_squares.sum() focus_measures["model_mask_count"] = mask.sum() model_delta_squares[antimask] = 0 focus_measures["model_mask_region_delta_sum_of_squares"] = model_delta_squares.sum() focus_measures["model_mask_region_image_hp_brenner_sum_of_squares"], focus_measures[ "model_mask_region_image_bp_brenner_sum_of_squares" ] = MaskedMultiBrenner((2560, 2160)).metric(im, mask) return focus_measures