def cluster_points_draw_export(dict_row, params, path_out=None): """ cluster points into centers and export visualisations :param dict dict_row: :param dict params: :param str path_out: :return dict: """ assert all(n in dict_row for n in ['path_points', 'path_image', 'path_segm']), \ 'missing some required fields: %r' % dict_row name = os.path.splitext(os.path.basename(dict_row['path_points']))[0] points = tl_data.load_landmarks_csv(dict_row['path_points']) if not list(points): logging.debug('no points to cluster for "%s"', name) points = tl_data.swap_coord_x_y(points) centres, clust_labels = cluster_center_candidates( points, max_dist=params['DBSCAN_max_dist'], min_samples=params['DBSCAN_min_samples'] ) path_csv = os.path.join(path_out, FOLDER_CENTER, name + '.csv') tl_data.save_landmarks_csv(path_csv, tl_data.swap_coord_x_y(centres)) path_visu = os.path.join(path_out, FOLDER_CLUSTER_VISUAL) img, segm = None, None if dict_row['path_image'] is not None and os.path.isfile(dict_row['path_image']): img = tl_data.io_imread(dict_row['path_image']) if dict_row['path_segm'] is not None and os.path.isfile(dict_row['path_segm']): segm = tl_data.io_imread(dict_row['path_segm']) export_draw_image_centers_clusters(path_visu, name, img, centres, points, clust_labels, segm) dict_row.update({'image': name, 'path_centers': path_csv, 'nb_centres': len(centres)}) return dict_row
def load_image_segm_center(idx_row, path_out=None, dict_relabel=None): """ by paths load images and segmentation and weather centers exist, load them if the path out is given redraw visualisation of inputs :param (int, DF:row) idx_row: tuple of index and row :param str path_out: path to output directory :param dict dict_relabel: look-up table for relabeling :return(str, ndarray, ndarray, [[int, int]]): idx_name, img_rgb, segm, centers """ idx, row_path = idx_row for k in ['path_image', 'path_segm', 'path_centers']: row_path[k] = tl_data.update_path(row_path[k]) if not os.path.exists(row_path[k]): raise FileNotFoundError('missing %s' % row_path[k]) idx_name = get_idx_name(idx, row_path['path_image']) img_struc, img_gene = tl_data.load_img_double_band_split( row_path['path_image'], im_range=None) # img_rgb = np.array(Image.open(row_path['path_img'])) img_rgb = tl_data.merge_image_channels(img_struc, img_gene) if np.max(img_rgb) > 1: img_rgb = img_rgb / float(np.max(img_rgb)) seg_ext = os.path.splitext(os.path.basename(row_path['path_segm']))[-1] if seg_ext == '.npz': with np.load(row_path['path_segm'], allow_pickle=True) as npzfile: segm = npzfile[npzfile.files[0]] if dict_relabel is not None: segm = seg_lbs.merge_probab_labeling_2d(segm, dict_relabel) else: segm = tl_data.io_imread(row_path['path_segm']) if dict_relabel is not None: segm = seg_lbs.relabel_by_dict(segm, dict_relabel) if row_path['path_centers'] is not None and os.path.isfile( row_path['path_centers']): ext = os.path.splitext(os.path.basename(row_path['path_centers']))[-1] if ext == '.csv': centers = tl_data.load_landmarks_csv(row_path['path_centers']) centers = tl_data.swap_coord_x_y(centers) elif ext == '.png': centers = tl_data.io_imread(row_path['path_centers']) # relabel loaded segm into relevant one centers = np.array(LUT_ANNOT_CENTER_RELABEL)[centers] else: logging.warning('not supported file format %s', ext) centers = None else: centers = None if is_drawing(path_out): export_visual_input_image_segm(path_out, idx_name, img_rgb, segm, centers) return idx_name, img_rgb, segm, centers
def expert_visual(row, method_name, path_out, max_fig_size=10): """ export several visualisation segmentation and annotation :param dict row: :param str method_name: :param str path_out: :param int max_fig_size: """ im_name = os.path.splitext(os.path.basename(row['path_image']))[0] img, _ = tl_data.load_image_2d(row['path_image']) # annot = tl_data.load_image(row['path_annot']) egg_segm, _ = tl_data.load_image_2d(row['path_egg-segm']) in_segm, _ = tl_data.load_image_2d(row['path_in-segm']) centers = tl_data.load_landmarks_csv(row['path_centers']) centers = np.array(tl_data.swap_coord_x_y(centers)) fig_size = max_fig_size * np.array(img.shape[:2]) / float(np.max( img.shape)) fig_name = '%s_%s.jpg' % (im_name, method_name) fig, ax = plt.subplots(figsize=fig_size[::-1]) ax.imshow(img[:, :, 0], cmap=plt.cm.gray) ax.imshow(egg_segm, alpha=0.15) ax.contour(egg_segm, levels=np.unique(egg_segm), linewidths=(3, )) ax.plot(centers[:, 1], centers[:, 0], 'ob') tl_visu.figure_image_adjustment(fig, img.shape) path_fig = os.path.join(path_out, NAME_DIR_VISUAL_1, fig_name) fig.savefig(path_fig, bbox_inches='tight', pad_inches=0) plt.close(fig) fig, ax = plt.subplots(figsize=fig_size[::-1]) # ax.imshow(np.max(in_segm) - in_segm, cmap=plt.cm.gray) ax.imshow(LUT_COLOR[in_segm], vmin=0., vmax=1., alpha=0.5) ax.contour(in_segm, levels=np.unique(in_segm), colors='k') ax.imshow(egg_segm, alpha=0.3) ax.contour(egg_segm, levels=np.unique(egg_segm), linewidths=(5, )) ax.plot(centers[:, 1], centers[:, 0], 'or') tl_visu.figure_image_adjustment(fig, img.shape) path_fig = os.path.join(path_out, NAME_DIR_VISUAL_2, fig_name) fig.savefig(path_fig, bbox_inches='tight', pad_inches=0) plt.close(fig) fig, ax = plt.subplots(figsize=fig_size[::-1]) ax.imshow(img[:, :, 0], cmap=plt.cm.gray, alpha=1.) ax.contour(in_segm, levels=np.unique(in_segm), colors='w') ax.imshow(egg_segm, alpha=0.3) ax.contour(egg_segm, levels=np.unique(egg_segm), linewidths=(5, )) ax.plot(centers[:, 1], centers[:, 0], 'og') tl_visu.figure_image_adjustment(fig, img.shape) path_fig = os.path.join(path_out, NAME_DIR_VISUAL_3, fig_name) fig.savefig(path_fig, bbox_inches='tight', pad_inches=0) plt.close(fig)
def detect_center_candidates(name, image, segm, centers_gt, slic, points, features, feature_names, params, path_out, classif): """ for loaded or computer all necessary data, classify centers_gt candidates and if we have annotation validate this results :param str name: :param ndarray image: :param ndarray segm: :param centers_gt: :param slic: np.array :param [(int, int)] points: :param features: :param list(str) feature_names: :param dict params: :param str path_out: :param classif: obj :return dict: """ labels = classif.predict(features) # proba = classif.predict_proba(features) candidates = np.asarray(points)[np.asarray(labels) == 1] path_points = os.path.join(path_out, FOLDER_POINTS) path_visu = os.path.join(path_out, FOLDER_POINTS_VISU) path_csv = os.path.join(path_points, name + '.csv') tl_data.save_landmarks_csv(path_csv, tl_data.swap_coord_x_y(candidates)) export_show_image_points_labels(path_visu, name, image, segm, points, labels, slic, centers_gt) dict_centers = {'image': name, 'path_points': path_csv} if centers_gt is not None: dict_centers = compute_statistic_centers(dict_centers, image, segm, centers_gt, slic, points, labels, params, path_visu) return dict_centers
def image_segmentation(idx_row, params, debug_export=DEBUG_EXPORT): """ image segmentation which prepare inputs (imsegm, centres) and perform segmentation of various imsegm methods :param (int, str) idx_row: input image and centres :param dict params: segmentation parameters :return str: image name """ _, row_path = idx_row for k in dict(row_path): if isinstance(k, str) and k.startswith('path_'): row_path[k] = tl_data.update_path(row_path[k], absolute=True) logging.debug('segmenting image: "%s"', row_path['path_image']) name = os.path.splitext(os.path.basename(row_path['path_image']))[0] img = load_image(row_path['path_image']) # make the image like RGB img_rgb = np.rollaxis(np.tile(img, (3, 1, 1)), 0, 3) seg = load_image(row_path['path_segm'], 'segm') assert img_rgb.shape[:2] == seg.shape, \ 'image %r and segm %r do not match' % (img_rgb.shape[:2], seg.shape) if not os.path.isfile(row_path['path_centers']): logging.warning('no center was detected for "%s"', name) return name centers = tl_data.load_landmarks_csv(row_path['path_centers']) centers = tl_data.swap_coord_x_y(centers) if not list(centers): logging.warning('no center was detected for "%s"', name) return name # img = seg / float(seg.max()) slic = seg_spx.segment_slic_img2d(img_rgb, sp_size=params['slic_size'], relative_compact=params['slic_regul']) path_segm = os.path.join(params['path_exp'], 'input', name + '.png') export_draw_image_segm(path_segm, img_rgb, segm_obj=seg, centers=centers) seg_simple = simplify_segm_3cls(seg) path_segm = os.path.join(params['path_exp'], 'simple', name + '.png') export_draw_image_segm(path_segm, seg_simple - 1.) dict_segment = create_dict_segmentation(params, slic, seg, img, centers) image_name = name + '.png' centre_name = name + '.csv' # iterate over segmentation methods and perform segmentation on this image for method in dict_segment: (fn, args) = dict_segment[method] logging.debug(' -> %s on "%s"', method, name) path_dir = os.path.join(params['path_exp'], method) # n.split('_')[0] path_segm = os.path.join(path_dir, image_name) path_centre = os.path.join(path_dir + DIR_CENTRE_POSIX, centre_name) path_fig = os.path.join(path_dir + DIR_VISUAL_POSIX, image_name) path_debug = os.path.join(path_dir + DIR_DEBUG_POSIX, name) # assuming that segmentation may fail try: t = time.time() if debug_export and 'rg2sp' in method: os.mkdir(path_debug) segm_obj, centers, dict_export = fn(*args, debug_export=path_debug) else: segm_obj, centers, dict_export = fn(*args) # also export ellipse params here or inside the segm fn if dict_export is not None: for k in dict_export: export_partial(k, dict_export[k], path_dir, name) logging.info('running time of %r on image "%s" is %d s', fn.__name__, image_name, time.time() - t) tl_data.io_imsave(path_segm, segm_obj.astype(np.uint8)) export_draw_image_segm(path_fig, img_rgb, seg, segm_obj, centers) # export also centers centers = tl_data.swap_coord_x_y(centers) tl_data.save_landmarks_csv(path_centre, centers) except Exception: logging.exception('segment fail for "%s" via %s', name, method) return name