def fit_ransac(peduncle_img, bg_img=None, save=False, name="", pwd=""): # skeletonize peduncle segment h, w = peduncle_img.shape mask_index = np.argwhere(peduncle_img) x = mask_index[:, 1].reshape(-1, 1) # x, spould be 2D y = mask_index[:, 0] # y # Robustly fit linear model with RANSAC algorithm mad_y = mad(y) ransac = linear_model.RANSACRegressor(max_trials=500, residual_threshold=0.8 * mad_y) ransac.fit(x, y) inlier_mask = ransac.inlier_mask_ outlier_mask = np.logical_not(inlier_mask) i_remove = [y[outlier_mask], x[outlier_mask, 0]] peduncle_img[tuple(i_remove)] = 0 # skeleton_img = skeletonize_img(peduncle_img) # skeleton = skan.Skeleton(skeleton_img) # # # branch data # for i, path in enumerate(skeleton.path_coordinates): # px_coords = path.astype(int) if save: line_x = np.arange(x.min(), x.max())[:, np.newaxis] line_y = h - ransac.predict(line_x) fig = plt.figure() plt.scatter(x[inlier_mask], h - y[inlier_mask], color='yellowgreen', marker='.', label='Inliers') plt.scatter(x[outlier_mask], h - y[outlier_mask], color='gold', marker='.', label='Outliers') plt.plot(line_x, line_y, color='navy', linewidth=2, label='RANSAC regressor') plt.axis('equal') plt.legend(loc='lower right') plt.xlabel("Input") plt.ylabel("Response") if pwd is not None: save_fig(fig, pwd, name + "_00", title="RANSAC") plt.close(fig) return peduncle_img
def get_truss_visualization(self, local=False, save=False): pwd = os.path.join(self.pwd, '08_result') if local: frame_id = self.LOCAL_FRAME_ID shape = self.shape # self.bbox[2:4] zoom = True name = 'local' skeleton_width = 4 grasp_linewidth = 3 else: frame_id = self.ORIGINAL_FRAME_ID shape = self.shape zoom = False name = 'original' skeleton_width = 2 grasp_linewidth = 1 grasp = self.get_grasp_location(local=local) tomato = self.get_tomatoes(local=local) xy_junc = coords_from_points(self.junction_points, frame_id) img = self.get_rgb(local=local) # generate peduncle image xy_peduncle = coords_from_points(self.peduncle_points, frame_id) rc_peduncle = np.around(np.array(xy_peduncle)).astype(np.int)[:,(1, 0)] arr = np.zeros(shape, dtype=np.uint8) arr[rc_peduncle[:, 0], rc_peduncle[:, 1]] = 1 # plot plt.figure() plot_image(img) plot_features(tomato=tomato, zoom=zoom) visualize_skeleton(img, arr, coord_junc=xy_junc, show_img=False, skeleton_width=skeleton_width) if (grasp["xy"] is not None) and (grasp["angle"] is not None): settings = self.settings['compute_grasp'] if self.px_per_mm is not None: minimum_grasp_length_px = self.px_per_mm * settings['grasp_length_min_mm'] open_dist_px = settings['open_dist_mm'] * self.px_per_mm finger_thickenss_px = settings['finger_thinkness_mm'] * self.px_per_mm else: minimum_grasp_length_px = settings['grasp_length_min_px'] plot_grasp_location(grasp["xy"], grasp["angle"], finger_width=minimum_grasp_length_px, finger_thickness=finger_thickenss_px, finger_dist=open_dist_px, linewidth=grasp_linewidth) if save: if name is None: name = self.name else: name = self.name + '_' + name save_fig(plt.gcf(), pwd, name) return figure_to_image(plt.gcf())
def a_hist(img_a, centers, lbl, bins=80, a_min=-1.0, a_max=1.0, name="", pwd=""): # plot Hue (HSV) fig, ax = plt.subplots(1) plt.yscale("log") center_background = centers[lbl["background"]] center_tomato = centers[lbl["tomato"]] center_peduncle = centers[lbl["peduncle"]] ax.axvline(x=center_background, color='b') ax.axvline(x=center_tomato, color='r') ax.axvline(x=center_peduncle, color='g') x0 = a_min x1 = (center_background + center_peduncle) / 2 x2 = (center_peduncle + center_tomato) / 2 x3 = a_max alpha = 0.2 plt.axvspan(x0, x1, color='b', alpha=alpha, lw=0) plt.axvspan(x1, x2, color='g', alpha=alpha, lw=0) plt.axvspan(x2, x3, color='r', alpha=alpha, lw=0) angle = img_a.flatten() # .astype('uint16') radii, bins, patches = ax.hist(angle, bins=bins, range=(a_min, a_max), color="black", lw=0) ax.set_xlabel("a") ax.set_ylabel("frequency") save_fig(fig, pwd, name + "_a_hist") # , titleSize=10
def hue_hist(img_hue, centers, lbl, name, pwd): # [-180, 180] => [0, 360] centers[centers < 0] += 360 # plot Hue (HSV) fig, ax = plt.subplots(1) plt.yscale("log") center_background = centers[lbl["background"]] center_tomato = centers[lbl["tomato"]] center_peduncle = centers[lbl["peduncle"]] ax.axvline(x=center_background, color='b') ax.axvline(x=center_tomato, color='r') ax.axvline(x=center_peduncle, color='g') x0 = 0 x1 = (center_tomato + center_peduncle) / 2 x2 = (center_peduncle + center_background) / 2 x3 = (center_background + center_tomato + 360) / 2 x4 = 360 alpha = 0.2 plt.axvspan(x0, x1, color='r', alpha=alpha, lw=0) plt.axvspan(x1, x2, color='g', alpha=alpha, lw=0) plt.axvspan(x2, x3, color='b', alpha=alpha, lw=0) plt.axvspan(x3, x4, color='r', alpha=alpha, lw=0) bins = 180 angle = img_hue.flatten().astype('uint16') * 2 radii, bins, patches = ax.hist(angle, bins=bins, range=(0, 360), color="black", lw=0) ax.set_xlabel("hue [$^\circ$]") ax.set_ylabel("frequency") save_fig(fig, pwd, name + "_hue_hist") # , titleSize=10
def fit_ransac(peduncle_img, bg_img=None, save=False, name="", pwd=""): pend_color = np.array([0, 150, 30]) stem_color = np.array([110, 255, 128]) # skeletonize peduncle segment shape = peduncle_img.shape factor = 5 mask_index = np.argwhere(peduncle_img) cols = mask_index[:, 1].reshape(-1, 1) # x, spould be 2D rows = mask_index[:, 0] # y i = range(0, len(rows), factor) fit_cols = cols[i] # x, spould be 2D fit_rows = rows[i] # y # Robustly fit linear model with RANSAC algorithm mad = mean_absolute_deviation(rows) residual_threshold = 0.8 * mad ransac = linear_model.RANSACRegressor( max_trials=1000, residual_threshold=residual_threshold) ransac.fit(fit_cols, fit_rows) # predict on full data set rows_pred = ransac.predict(cols) # idenitfy in and outliers data_train = np.stack((rows, cols[:, 0]), axis=1) data_pred = np.stack((rows_pred, cols[:, 0]), axis=1) dist = euclidean_distances(data_train, data_pred) inlier_mask = np.min(dist, axis=1) < residual_threshold outlier_mask = np.logical_not(inlier_mask) coord_inlier = [rows[inlier_mask], cols[inlier_mask, 0]] coord_outlier = [rows[outlier_mask], cols[outlier_mask, 0]] img_inlier = np.zeros(shape, dtype=np.uint8) img_outlier = np.zeros(shape, dtype=np.uint8) img_inlier[tuple(coord_inlier)] = 255 img_outlier[tuple(coord_outlier)] = 255 inlier_contours, hierarchy = cv2.findContours(img_inlier, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:] outlier_contours, hierarchy = cv2.findContours( img_outlier, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:] fig = plt.figure() plot_image(bg_img) for contour in inlier_contours: plt.plot(contour[:, 0, 0], contour[:, 0, 1], linestyle='-', linewidth=1, color=pend_color.astype(float) / 255) for contour in outlier_contours: plt.plot(contour[:, 0, 0], contour[:, 0, 1], linestyle='-', linewidth=1, color=stem_color.astype(float) / 255) line_cols = np.arange(fit_cols.min(), fit_cols.max())[:, np.newaxis] line_rows = ransac.predict(line_cols) plt.plot(line_cols, line_rows, color='navy', linewidth=2, label='RANSAC regressor') plt.legend(loc='lower right') if pwd is not None: save_fig(fig, pwd, name, title="RANSAC") return img_inlier
def visualize_skeleton(img, skeleton_img, skeletonize=False, coord_junc=None, coord_end=None, junc_nodes=None, end_nodes=None, branch_data=None, name="", pwd=None, show_nodes=True, skeleton_color=None, skeleton_width=4, show_img=True): if skeleton_color is None: skeleton_color = (0, 150, 30) if skeletonize: skeleton_img = skeletonize_img(skeleton_img) if show_img: fig = plt.figure() plot_image(img) else: fig = plt.gcf() add_contour(skeleton_img, skeleton_color, linewidth=skeleton_width, zorder=6) if (len(np.argwhere(skeleton_img)) > 2) and show_nodes: if (coord_junc is None) and (coord_end is None): coord_junc, coord_end = get_node_coord(skeleton_img) if coord_junc is not None: add_circles(coord_junc, radii=4, fc=JUNC_COLOR, linewidth=0, zorder=7) if coord_end is not None: add_circles(coord_end, radii=4, fc=END_COLOR, linewidth=0, zorder=7) if branch_data: branch_center = {} branch_angle = {} for branch_type in branch_data: branch_center[branch_type] = [] branch_angle[branch_type] = [] for branch in branch_data[branch_type]: branch_center[branch_type].append(branch['center_node_coord']) branch_angle[branch_type].append(branch['angle']) add_arrows(branch_center['junction-junction'], np.deg2rad(branch_angle['junction-junction']), color=JUNC_COLOR, linewidth=2) add_arrows(branch_center['junction-endpoint'], np.deg2rad(branch_angle['junction-endpoint']), color=END_COLOR, linewidth=2) if (junc_nodes is not None) or (end_nodes is not None): if junc_nodes is not None: for junc_node, coord in zip(junc_nodes, coord_junc): plt.text(coord[0], coord[1], str(junc_node)) if end_nodes is not None: for end_node, coord in zip(end_nodes, coord_end): plt.text(coord[0], coord[1], str(end_node)) if pwd: save_fig(fig, pwd, name)
def detect_peduncle(peduncle_img, settings=None, px_per_mm=None, bg_img=None, save=False, name="", pwd=""): if settings is None: settings = settings.detect_peduncle() if (bg_img is not None) and save: fig = plt.figure() plot_image(bg_img) save_fig(fig, pwd, name + "_00") if bg_img is None: bg_img = peduncle_img if px_per_mm: branch_length_min_px = px_per_mm * settings['branch_length_min_mm'] else: branch_length_min_px = settings['branch_length_min_px'] skeleton_img = skeletonize_img(peduncle_img) junc_coords, end_coords = get_node_coord(skeleton_img) if save: visualize_skeleton(bg_img, skeleton_img, coord_junc=junc_coords, coord_end=end_coords, name=name + "_01", pwd=pwd) if save: fit_ransac(peduncle_img, bg_img=bg_img.copy(), save=True, name=name + "_ransac", pwd=pwd) # update_image = True # while update_image: skeleton_img, b_remove = threshold_branch_length(skeleton_img, branch_length_min_px) # update_image = b_remove.any() junc_coords, end_coords = get_node_coord(skeleton_img) if save: visualize_skeleton(bg_img.copy(), skeleton_img, coord_junc=junc_coords, coord_end=end_coords, name=name + "_02", pwd=pwd) graph, pixel_coordinates, degree_image = skan.skeleton_to_csgraph( skeleton_img, unique_junctions=True) dist, pred = csgraph.shortest_path(graph, directed=False, return_predecessors=True) end_nodes = coords_to_nodes(pixel_coordinates, end_coords[:, [1, 0]]) junc_nodes = coords_to_nodes(pixel_coordinates, junc_coords[:, [1, 0]]) path, path_length_px, branch_data = find_path(dist, pred, junc_nodes, end_nodes, pixel_coordinates, bg_image=bg_img.copy(), do_animate=False) branch_data = get_branch_center(branch_data, dist, pixel_coordinates, skeleton_img) path_img = path_mask(path, pixel_coordinates, skeleton_img.shape) junc_coords = pixel_coordinates[get_ids_on_path(path, pixel_coordinates, junc_nodes)][:, [1, 0]] end_coords = pixel_coordinates[get_ids_on_path(path, pixel_coordinates, end_nodes)][:, [1, 0]] end_coords = np.array([ pixel_coordinates[path[0]][[1, 0]], pixel_coordinates[path[-1]][[1, 0]] ]) # make sure that end nodes are not labeled as junctions if junc_coords.shape[0] != 0: for end_coord in end_coords: dst = distance(junc_coords, end_coord) mask = dst > 0.1 junc_coords = junc_coords[mask] if save: visualize_skeleton( bg_img, path_img, coord_junc= junc_coords, # junc_nodes=junc_nodes, end_nodes=end_nodes, coord_end=end_coords, name=name + "_03", pwd=pwd) if save: visualize_skeleton(bg_img, path_img, coord_junc=junc_coords, branch_data=branch_data, coord_end=end_coords, name=name + "_04", pwd=pwd) return path_img, branch_data, junc_coords, end_coords
def both_hist(img_hue, img_a, centers, lbl, a_bins=80, pwd="", name="", hue_min=0, hue_max=180, hue_radius=1.0, a_min=-1.0, a_max=1.0, true_scale=False): a_height = 500 if true_scale: hue_height = 2 * np.pi * hue_radius / 2 * a_height # 180*scale else: hue_height = 2 * 500 hue_step = float(hue_max - hue_min) / float(hue_height) a_step = float(a_max - a_min) / float(a_height) # label every possible location values_a, values_hue = np.mgrid[a_min:a_max:a_step, hue_min:hue_max:hue_step] shape = values_hue.shape labels = assign_labels(values_hue, centers, img_a=values_a, hue_radius=hue_radius) tomato = label2img(labels, lbl["tomato"], shape) peduncle = label2img(labels, lbl["peduncle"], shape) background = label2img(labels, lbl["background"], shape) # hue_range = [0, 360] a_range = [a_min, a_max] my_range = [a_range, hue_range] x = img_a.flatten() y = img_hue.flatten().astype('uint16') * 2 scale = 4.0 hue_bins = 180 * scale a_bins = a_bins * scale hist, _, _, _ = plt.hist2d(x, y, range=my_range, bins=[a_bins / scale, hue_bins / scale]) hist[hist > 0] = np.log(hist[hist > 0]) img_hist_gray = 255 - (hist / np.amax(hist) * 255).astype(np.uint8) img_hist_rgb = grey_2_rgb( img_hist_gray ) # (255*mapping.to_rgba(img_hist_gray)[:, :, 0:3]).astype(np.uint8) # rescale based on scala param new_shape = (shape[1], shape[0]) # [width, height] img_hist_rgb = cv2.resize(img_hist_rgb, new_shape, interpolation=cv2.INTER_NEAREST) # overlay with histogram plot_segments(img_hist_rgb, background, tomato, peduncle, show_background=True, alpha=0.1, linewidth=1, show_axis=True, use_image_colours=False, ncols=2) # cmap = mpl.cm.hot_r # norm = mpl.colors.Normalize(vmin=0, vmax=100) # plt.gcf().colorbar(cm.ScalarMappable(norm=norm, cmap=cmap)) # ticks=['low', 'high'], format='%s' # plot cluster centers centers_hue = np.rad2deg(centers['hue']) centers_hue[centers_hue < 0] += 360 hue_coords = (centers_hue / 2) / hue_step # [rad] a_coords = (centers['a'] - a_min) / a_step for label in lbl: i = lbl[label] if label == 'tomato': color = 'r' elif label == 'peduncle': color = 'g' elif label == 'background': color = 'b' plt.plot(hue_coords[i], a_coords[i], 'o', color=color, markeredgecolor='w', markersize=4, markeredgewidth=0.5, alpha=1.0) # fix axis, only plot x axis for last image, only plot title for first # if name == final_image_id: plt.xticks([hue_min, hue_height / 2, hue_height - 1], map(str, (0, 180, 360))) plt.xlabel("hue [$^\circ$]") plt.title('K-means clustering result') # else: # plt.xticks([]) plt.ylabel("a*") plt.yticks([0, a_height / 2, a_height - 1], map(str, (a_min, (a_min + a_max) / 2, a_max))) if True: axs = plt.gcf().get_axes() plt.sca(axs[-1]) cmap = mpl.cm.hot_r norm = mpl.colors.Normalize(vmin=0, vmax=100) cb1 = mpl.colorbar.ColorbarBase(plt.gca(), cmap=cmap, norm=norm, orientation='vertical') cb1.set_label('frequency', labelpad=-20) plt.yticks([]) cb1.set_ticks([0, 100], True) plt.yticks([0, 100], ['low', 'high']) save_fig(plt.gcf(), pwd, name + "_hist", no_ticks=False)