def test_contingency_table(): seg = np.array([0, 1, 1, 1, 2, 2, 2, 3]) gt = np.array([1, 1, 1, 2, 2, 2, 2, 0]) ct = ev.contingency_table(seg, gt, ignore_seg=[], ignore_gt=[]) ct0 = ev.contingency_table(seg, gt, ignore_seg=[0], ignore_gt=[0]) ctd = ct.todense() assert_equal( ctd, np.array([[0., 0.125, 0.], [0., 0.25, 0.125], [0., 0., 0.375], [0.125, 0., 0.]])) assert ct.shape == ct0.shape
def test_contingency_table(): seg = np.array([0, 1, 1, 1, 2, 2, 2, 3]) gt = np.array([1, 1, 1, 2, 2, 2, 2, 0]) ct = ev.contingency_table(seg, gt, ignore_seg=[], ignore_gt=[]) ct0 = ev.contingency_table(seg, gt, ignore_seg=[0], ignore_gt=[0]) ctd = ct.todense() assert_equal(ctd, np.array([[0. , 0.125, 0. ], [0. , 0.25 , 0.125], [0. , 0. , 0.375], [0.125, 0. , 0. ]])) assert ct.shape == ct0.shape
def show_greatest_vi(seg, gt): (worst_false_merges, merge_ents, worst_false_splits, split_ents) = evaluate.sorted_vi_components(seg, gt) print "Total entropy of false merges: %f" % sum(merge_ents) print "Total entropy of false splits: %f" % sum(split_ents) worst_false_splits = worst_false_splits[:LIST_CAP] split_ents = split_ents[:LIST_CAP] worst_false_merges = worst_false_merges[:LIST_CAP] merge_ents = merge_ents[:LIST_CAP] # for label, entropies in [("merges", merge_ents), ("splits", split_ents)]: # print "For worst false %s, top %d biggest entropies:" % (label, len(entropies)) # for rank, entropy in enumerate(entropies): # print " %d. %f" % (rank, entropy) # handle worst false splits print worst_false_splits cont_table = evaluate.contingency_table(seg, gt) # view_biggest_cross_section(gt, [worst_false_splits[0]]) # for bad_merge_id_in_seg in worst_false_merges[1:3]: # overlaps = evaluate.split_components(bad_merge_id_in_seg, cont_table, axis=0) # print "bad_merge_id_in_seg:",bad_merge_id_in_seg # print overlaps # overlap_ids = [gt_id for gt_id, perc_of_bad_split, perc_in_bad_split in overlaps] # view_bad_merge(seg, gt, bad_merge_id_in_seg, overlap_ids) for bad_split_id_in_gt in worst_false_splits[:1]: overlaps = evaluate.split_components(bad_split_id_in_gt, cont_table, axis=1) print "bad_split_id_in_gt:", bad_split_id_in_gt print overlaps overlap_ids = [seg_id for seg_id, perc_of_bad_split, perc_in_bad_split in overlaps] view_bad_split(seg, gt, bad_split_id_in_gt, overlap_ids)
def view_all_join(gt, automated_seg, num_elem=6, axis=None): """Generate an interactive figure highlighting the VI error. Parameters ---------- gt: nd-array with shape M*N. This corresponds to the 'ground truth'. auto: nd-array with same shape as gt. This corresponds to the automated segmentation. num_elem: Int, optional. This parameter determines the number of comps shown upon click. Set to output '4' by default. Returns ------- A window with six panels - the top middle image corresponds to the components that are the worst false merges in the automated segmentation, which share significant area with the clicked-upon segment. Likewise, the top middle image shows the worst false splits. """ if gt.shape != automated_seg.shape: return "Input arrays are not of the same shape." elif (type(gt) or type(automated_seg)) != np.ndarray: return "Input arrays not of valid type." vint = np.vectorize(int) # Compute the join seg of the automatic seg and the ground truth. joint_seg = join_segmentations(automated_seg, gt) # Contingency table for merges cont_table_m = ev.contingency_table(automated_seg, joint_seg) # Contingency table for splits cont_table_s = ev.contingency_table(joint_seg, gt) # Sort the VI according to the largest false merge components. merge_idxs_m, merge_errs_m = ev.sorted_vi_components( joint_seg, automated_seg)[0:2] #merges #Sort the VI according to the largest false split components. split_idxs_s, split_errs_s = ev.sorted_vi_components(joint_seg, gt)[0:2] #split #Find the indices of these largest false merge components, and largest false splits, in descending order. merge_idxs_sorted, split_idxs_sorted = np.argsort( merge_idxs_m), np.argsort(split_idxs_s) #Sort the errors according to the indices. merge_unsorted, split_unsorted = merge_errs_m[ merge_idxs_sorted], split_errs_s[split_idxs_sorted] # Color both the seg and gt according to the intensity of the split VI error. merge_err_img, split_err_img = merge_unsorted[ automated_seg], split_unsorted[gt] if axis is None: fig, ax = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True) plt.setp(ax.flat, adjustable='box-forced') else: fig, ax = plt.subplots(nrows=len(axis) // 2, ncols=len(axis) // 2, sharex=True, sharey=True) for i in range(len(axis) // 2): ax[0, i] = ax[i] for i in range(0, (len(axis) // 2)): ax[1, i] = ax[i + 2] ax[0, 0].imshow(RAW) viz.imshow_magma(merge_err_img, alpha=0.4, axis=ax[0, 0]) ax[0, 1].imshow(RAW) axes_image_1 = viz.imshow_rand(joint_seg, alpha=0.4, axis=ax[0, 1]) ax[0, 2].imshow(RAW) viz.imshow_rand(gt, alpha=0.4, axis=ax[0, 2]) ax[1, 0].imshow(RAW) viz.imshow_magma(split_err_img, alpha=0.4, axis=ax[1, 0]) ax[1, 1].imshow(RAW) axes_image = viz.imshow_rand(joint_seg, alpha=0.4, axis=ax[1, 1]) ax[1, 2].imshow(RAW) viz.imshow_rand(automated_seg, alpha=0.4, axis=ax[1, 2]) ax[0, 0].set_title( "Worst merge comps colored by VI error: click to show them on second panel." ) ax[0, 1].set_title("Worst merge comps.") ax[0, 2].set_title("Ground Truth.") ax[1, 0].set_title( "Worst split comps colored by VI error: click to show them on second panel." ) ax[1, 1].set_title("Worst split comps.") ax[1, 2].set_title("Automated Seg.") @jit def drawer(seg, comps, limit=True): """Dynamically redraw the worst split/merge comps.""" a_seg = np.zeros_like(seg.astype('float64')) factor = (seg.max() // num_elem) lim = 0.0 for i, (j, k, z) in enumerate(comps): lim += k if z < 0.01: continue a_seg += (seg == j) * ((i + 1) * factor) if limit: if lim >= 0.98: break return a_seg @jit def _onpress(event): """Matplotlib 'onpress' event handler.""" if not (event.inaxes == ax[1, 0] or event.inaxes == ax[0, 0] or event.inaxes == ax[0, 2] or event.inaxes == ax[1, 2]): fig.text(0.5, 0.5, s="Must click on left or right axes to show comps!", ha="center") fig.canvas.draw_idle() if event.inaxes == ax[0, 0] or event.inaxes == ax[0, 2]: if event.button != 1: return for txt in fig.texts: txt.set_visible(False) fig.canvas.draw() x, y = vint(event.xdata), vint(event.ydata) # Find the indices of the false merge bodies overlapping with the coordinates of the mouse click. worst_merge_comps_m = ev.split_components(automated_seg[y, x], num_elems=None, cont=cont_table_m, axis=0) new_seg_m = drawer(joint_seg, worst_merge_comps_m, limit=False) axes_image_1.set_array(new_seg_m) fig.canvas.draw() if event.inaxes == ax[1, 0] or event.inaxes == ax[1, 2]: if event.button != 1: return for txt in fig.texts: txt.set_visible(False) fig.canvas.draw() x, y = vint(event.xdata), vint(event.ydata) # Find the indices of the false split bodies overlapping with the coordinates of the mouse click. worst_split_comps_s = ev.split_components(gt[y, x], num_elems=None, cont=cont_table_s, axis=1) new_seg_s = drawer(joint_seg, worst_split_comps_s) axes_image.set_array(new_seg_s) fig.canvas.draw() fig.canvas.mpl_connect('button_press_event', _onpress) plt.ioff() plt.show()
def view_all(gt, automated_seg, num_elem=6, axis=None): """Generate an interactive figure highlighting the VI error. Parameters ---------- gt: nd-array with shape M*N. This corresponds to the 'ground truth'. auto: nd-array with same shape as gt. This corresponds to the automated segmentation. num_elem: Int, optional. This parameter determines the number of comps shown upon click. Set to output '6' by default. Returns ------- A panel with six images - the top middle image corresponds to the components that are the worst false merges in the automated segmentation, which share significant area with the clicked-upon segment. Likewise, the top middle image shows the worst false splits. """ if gt.shape != automated_seg.shape: return "Input arrays are not of the same shape." elif (type(gt) or type(automated_seg)) != np.ndarray: return "Input arrays not of valid type." vint = np.vectorize(int) cont = ev.contingency_table(automated_seg, gt) ii1, err1, ii2, err2 = ev.sorted_vi_components(automated_seg, gt) idxs1, idxs2 = np.argsort(ii1), np.argsort(ii2) err_unsorted, err_unsorted_2 = err1[idxs1], err2[idxs2] err_img, err_img_1 = err_unsorted[gt], err_unsorted_2[automated_seg] if axis is None: fig, ax = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True) plt.setp(ax.flat, adjustable='box-forced') else: fig, ax = plt.subplots(nrows=len(axis) // 2, ncols=len(axis) // 2, sharex=True, sharey=True) for i in range(len(axis) // 2): ax[0, i] = ax[i] for i in range(0, (len(axis) // 2)): ax[1, i] = ax[i + 2] ax[0, 0].imshow(RAW) viz.imshow_magma(err_img_1, alpha=0.4, axis=ax[0, 0]) ax[0, 1].imshow(RAW) axes_image_1 = viz.imshow_rand(automated_seg, alpha=0.4, axis=ax[0, 1]) ax[0, 2].imshow(RAW) viz.imshow_rand(gt, alpha=0.4, axis=ax[0, 2]) ax[1, 0].imshow(RAW) viz.imshow_magma(err_img, alpha=0.4, axis=ax[1, 0]) ax[1, 1].imshow(RAW) axes_image = viz.imshow_rand(automated_seg, alpha=0.4, axis=ax[1, 1]) ax[1, 2].imshow(RAW) viz.imshow_rand(automated_seg, alpha=0.4, axis=ax[1, 2]) ax[0, 0].set_title( "Worst merge comps colored by VI error: click to show them on second panel." ) ax[0, 1].set_title("Worst merge comps.") ax[0, 2].set_title("Ground Truth.") ax[1, 0].set_title( "Worst split comps colored by VI error: click to show them on second panel." ) ax[1, 1].set_title("Worst split comps.") ax[1, 2].set_title("Automated Seg.") @jit def drawer(seg, comps, limit=True): """Dynamically redraw the worst split/merge comps.""" a_seg = np.zeros_like(seg.astype('float64')) factor = (seg.max() // num_elem) lim = 0.0 for i, (j, k, z) in enumerate(comps): lim += k # if the area of the component is too small, we don't want to show it. if z < 0.01: continue a_seg += (seg == j) * ((i + 1) * factor) if limit: # Limit the number of components that are shown. if lim >= 0.98: break return a_seg @jit def _onpress(event): """Matplotlib 'onpress' event handler.""" if not (event.inaxes == ax[1, 0] or event.inaxes == ax[0, 0] or event.inaxes == ax[0, 2] or event.inaxes == ax[1, 2]): fig.text(0.5, 0.5, s="Must click on left or right axes to show comps!", ha="center") fig.canvas.draw_idle() if event.inaxes == ax[0, 0] or event.inaxes == ax[0, 2]: if event.button != 1: return for txt in fig.texts: txt.set_visible(False) fig.canvas.draw() x, y = vint(event.xdata), vint(event.ydata) # Identify the worst merge components that are being pointed at by the mouse click. comps = ev.split_components(automated_seg[y, x], cont, axis=0, num_elems=None) # Create the image containing only the identified components. new_seg_1 = drawer(gt, comps, limit=False) # Update the image with the drawn components axes_image_1.set_array(new_seg_1) # Draw this new image with the highlighted components onto the screen. fig.canvas.draw() if event.inaxes == ax[1, 0] or event.inaxes == ax[1, 2]: if event.button != 1: return for txt in fig.texts: txt.set_visible(False) fig.canvas.draw() x, y = vint(event.xdata), vint(event.ydata) # Identify the worst split components that are being pointed at by the mouse click. comps = ev.split_components(gt[y, x], cont, axis=1, num_elems=None) # Create the image containing only the identified components. new_seg = drawer(automated_seg, comps) # Update the image with the drawn components axes_image.set_array(new_seg) # Draw this new image with the highlighted components onto the screen. fig.canvas.draw() fig.canvas.mpl_connect('button_press_event', _onpress) plt.ioff() plt.show()