def display(self, workspace, figure): orig_pixels = workspace.display_data.orig_pixels output_pixels = workspace.display_data.output_pixels figure.set_subplots((2, 2)) figure.subplot_imshow_grayscale(0, 0, orig_pixels, "Original: %s" % self.image_name.value) if self.method == M_CANNY: # Canny is binary figure.subplot_imshow_bw(0, 1, output_pixels, self.output_image_name.value, sharexy=figure.subplot(0, 0)) else: figure.subplot_imshow_grayscale(0, 1, output_pixels, self.output_image_name.value, sharexy=figure.subplot(0, 0)) color_image = np.zeros( (output_pixels.shape[0], output_pixels.shape[1], 3)) color_image[:, :, 0] = stretch(orig_pixels) color_image[:, :, 1] = stretch(output_pixels) figure.subplot_imshow(1, 0, color_image, "Composite image", sharexy=figure.subplot(0, 0))
def display(self, workspace, figure): '''Display the results of relabeling workspace - workspace containing saved display data ''' from cellprofiler.gui.cpfigure import renumber_labels_for_display import matplotlib.cm as cm figure.set_subplots((1, 2)) figure.subplot_imshow_labels(0, 0, workspace.display_data.orig_labels, title=self.objects_name.value) output_labels = renumber_labels_for_display( workspace.display_data.output_labels) if self.relabel_option == OPTION_UNIFY and ( (self.unify_option == UNIFY_DISTANCE and self.wants_image) or (self.unify_option == UNIFY_PARENT)): if self.unify_option == UNIFY_DISTANCE and self.wants_image: # # Make a nice picture which superimposes the labels on the # guiding image # image = (stretch(workspace.display_data.image) * 255).astype( np.uint8) elif self.unify_option == UNIFY_PARENT: parent_objects = workspace.object_set.get_objects( self.parent_object.value) labels = parent_objects.segmented image = labels.astype(float) / (1.0 if np.max(labels) == 0 else np.max(labels)) image = (stretch(image) * 255).astype(np.uint8) image = np.dstack((image, image, image)) my_cm = cm.get_cmap(cpprefs.get_default_colormap()) my_cm.set_bad((0, 0, 0)) sm = cm.ScalarMappable(cmap=my_cm) m_output_labels = np.ma.array(output_labels, mask=output_labels == 0) output_image = sm.to_rgba(m_output_labels, bytes=True)[:, :, :3] image[output_labels > 0] = (image[output_labels > 0] / 4 * 3 + output_image[output_labels > 0, :] / 4) figure.subplot_imshow(0, 1, image, title=self.output_objects_name.value, sharexy=figure.subplot(0, 0)) else: figure.subplot_imshow_labels(0, 1, workspace.display_data.output_labels, title=self.output_objects_name.value, sharexy=figure.subplot(0, 0))
def display(self, workspace): """Display the results of relabeling workspace - workspace containing saved display data """ from cellprofiler.gui.cpfigure import renumber_labels_for_display import matplotlib.cm as cm figure = workspace.create_or_find_figure( title="ReassignObjectNumbers, image cycle #%d" % (workspace.measurements.image_set_number), subplots=(1, 2) ) figure.subplot_imshow_labels(0, 0, workspace.display_data.orig_labels, title=self.objects_name.value) output_labels = renumber_labels_for_display(workspace.display_data.output_labels) if self.relabel_option == OPTION_UNIFY: if self.unify_option == UNIFY_DISTANCE and self.wants_image: # # Make a nice picture which superimposes the labels on the # guiding image # image = (stretch(workspace.display_data.image) * 255).astype(np.uint8) elif self.unify_option == UNIFY_PARENT: parent_objects = workspace.object_set.get_objects(self.parent_object.value) labels = parent_objects.segmented image = labels.astype(float) / (1.0 if np.max(labels) == 0 else np.max(labels)) image = (stretch(image) * 255).astype(np.uint8) image = np.dstack((image, image, image)) my_cm = cm.get_cmap(cpprefs.get_default_colormap()) my_cm.set_bad((0, 0, 0)) sm = cm.ScalarMappable(cmap=my_cm) m_output_labels = np.ma.array(output_labels, mask=output_labels == 0) output_image = sm.to_rgba(m_output_labels, bytes=True)[:, :, :3] image[output_labels > 0] = image[output_labels > 0] / 4 * 3 + output_image[output_labels > 0, :] / 4 figure.subplot_imshow( 0, 1, image, title=self.output_objects_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0), ) else: figure.subplot_imshow_labels( 0, 1, workspace.display_data.output_labels, title=self.output_objects_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0), )
def display(self, workspace): '''Display the results of relabeling workspace - workspace containing saved display data ''' from cellprofiler.gui.cpfigure import renumber_labels_for_display import matplotlib.cm as cm figure = workspace.create_or_find_figure(title="UnifyObjectsByShape, image cycle #%d"%( workspace.measurements.image_set_number),subplots=(1,2)) figure.subplot_imshow_labels(0,0, workspace.display_data.orig_labels, title = self.objects_name.value) output_labels = renumber_labels_for_display( workspace.display_data.output_labels) objects = workspace.object_set.get_objects(self.objects_name.value) labels = objects.segmented image = labels.astype(float) / (1.0 if np.max(labels) == 0 else np.max(labels)) image = (stretch(image) * 255).astype(np.uint8) image = np.dstack((image,image,image)) my_cm = cm.get_cmap(cpprefs.get_default_colormap()) my_cm.set_bad((0,0,0)) sm = cm.ScalarMappable(cmap=my_cm) m_output_labels = np.ma.array(output_labels, mask = output_labels == 0) output_image = sm.to_rgba(m_output_labels, bytes=True)[:,:,:3] image[output_labels > 0 ] = ( image[output_labels > 0] / 4 * 3 + output_image[output_labels > 0,:] / 4) figure.subplot_imshow(0,1, image, title = self.output_objects_name.value, sharex = figure.subplot(0,0), sharey = figure.subplot(0,0))
def display(self, workspace, figure): orig_pixels = workspace.display_data.orig_pixels output_pixels = workspace.display_data.output_pixels figure.set_subplots((2, 2)) figure.subplot_imshow_grayscale(0, 0, orig_pixels, "Original: %s" % self.image_name.value) if self.method == M_CANNY: # Canny is binary figure.subplot_imshow_bw(0, 1, output_pixels, self.output_image_name.value, sharexy=figure.subplot(0, 0)) else: figure.subplot_imshow_grayscale( 0, 1, output_pixels, self.output_image_name.value, sharexy=figure.subplot(0, 0) ) color_image = np.zeros((output_pixels.shape[0], output_pixels.shape[1], 3)) color_image[:, :, 0] = stretch(orig_pixels) color_image[:, :, 1] = stretch(output_pixels) figure.subplot_imshow(1, 0, color_image, "Composite image", sharexy=figure.subplot(0, 0))
def display(self, workspace, figure): from identify import TS_BINARY_IMAGE object_pct = workspace.display_data.object_pct img = workspace.display_data.img primary_outline = workspace.display_data.primary_outline secondary_outline = workspace.display_data.secondary_outline segmented_out = workspace.display_data.segmented_out global_threshold = workspace.display_data.global_threshold object_count = workspace.display_data.object_count statistics = workspace.display_data.statistics if global_threshold is not None: statistics.append(["Threshold","%.3f" % global_threshold]) if object_count > 0: areas = scind.sum(np.ones(segmented_out.shape), segmented_out, np.arange(1, object_count + 1)) areas.sort() low_diameter = (np.sqrt(float(areas[object_count / 10]) / np.pi) * 2) median_diameter = (np.sqrt(float(areas[object_count / 2]) / np.pi) * 2) high_diameter = (np.sqrt(float(areas[object_count * 9 / 10]) / np.pi) * 2) statistics.append(["10th pctile diameter", "%.1f pixels" % (low_diameter)]) statistics.append(["Median diameter", "%.1f pixels" % (median_diameter)]) statistics.append(["90th pctile diameter", "%.1f pixels" % (high_diameter)]) if self.method != M_DISTANCE_N and self.threshold_scope != TS_BINARY_IMAGE: statistics.append(["Thresholding filter size", "%.1f"%(workspace.display_data.threshold_sigma)]) statistics.append(["Area covered by objects", "%.1f %%" % object_pct]) workspace.display_data.statistics = statistics figure.set_subplots((2, 2)) title = "Input image, cycle #%d" % (workspace.measurements.image_number) figure.subplot_imshow_grayscale(0, 0, img, title) figure.subplot_imshow_labels(1, 0, segmented_out, "%s objects" % self.objects_name.value, sharexy = figure.subplot(0, 0)) primary_img = np.dstack((img, img, img)) # # Stretch the outline image to the full scale # primary_img = stretch(primary_img) # Outline the primary objects cpmi.draw_outline(primary_img, primary_outline > 0, cpprefs.get_primary_outline_color()) # Outline the secondary objects cpmi.draw_outline(primary_img, secondary_outline > 0, cpprefs.get_secondary_outline_color()) figure.subplot_imshow(0, 1, primary_img, "%s and %s outlines"%(self.primary_objects.value,self.objects_name.value), normalize=False, sharexy = figure.subplot(0, 0)) figure.subplot_table( 1, 1, [[x[1]] for x in workspace.display_data.statistics], row_labels = [x[0] for x in workspace.display_data.statistics])
def entropy2(x,y): '''Joint entropy of paired samples X and Y''' # # Bin each image into 256 gray levels # x = (stretch(x) * 255).astype(int) y = (stretch(y) * 255).astype(int) # # create an image where each pixel with the same X & Y gets # the same value # xy = 256*x+y xy = xy.flatten() sparse = scipy.sparse.coo_matrix((np.ones(xy.shape), (xy,np.zeros(xy.shape)))) histogram = sparse.toarray() n=np.sum(histogram) if n > 0 and np.max(histogram) > 0: histogram = histogram[histogram>0] return np.log2(n) - np.sum(histogram * np.log2(histogram)) / n else: return 0
def display(self, workspace): '''Display the results of relabeling workspace - workspace containing saved display data ''' from cellprofiler.gui.cpfigure import renumber_labels_for_display import matplotlib.cm as cm figure = workspace.create_or_find_figure( title="ReassignObjectNumbers, image cycle #%d" % (workspace.measurements.image_set_number), subplots=(1, 2)) figure.subplot_imshow_labels(0, 0, workspace.display_data.orig_labels, title=self.objects_name.value) if self.wants_image: # # Make a nice picture which superimposes the labels on the # guiding image # output_labels = renumber_labels_for_display( workspace.display_data.output_labels) image = (stretch(workspace.display_data.image) * 255).astype( np.uint8) image = np.dstack((image, image, image)) my_cm = cm.get_cmap(cpprefs.get_default_colormap()) my_cm.set_bad((0, 0, 0)) sm = cm.ScalarMappable(cmap=my_cm) m_output_labels = np.ma.array(output_labels, mask=output_labels == 0) output_image = sm.to_rgba(m_output_labels, bytes=True)[:, :, :3] image[output_labels > 0] = (image[output_labels > 0] / 4 * 3 + output_image[output_labels > 0, :] / 4) figure.subplot_imshow(0, 1, image, title=self.output_objects_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0)) else: figure.subplot_imshow_labels(0, 1, workspace.display_data.output_labels, title=self.output_objects_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0))
def on_file_open(self, event): dlg = wx.FileDialog(self.frame, style=wx.FD_OPEN) if dlg.ShowModal() == wx.ID_OK: img = pil_to_array( PILImage.open( os.path.join(dlg.GetDirectory(), dlg.GetFilename()))) if img.ndim == 3: img = img[:, :, 0] + img[:, :, 1] + img[:, :, 2] img = stretch(img.astype(float)) lt = self.frame.MenuBar.Menus[0][0].MenuItems[7].IsChecked() if lt: limg, d = log_transform(img) else: limg = img self.frame.subplot_imshow_grayscale(0, 0, limg) limg = limg.flatten() menu_items = self.frame.MenuBar.Menus[0][0].MenuItems if menu_items[2].IsChecked(): t1 = t2 = otsu(limg) elif menu_items[3].IsChecked(): t1 = t2 = entropy(limg) elif menu_items[4].IsChecked(): t1, t2 = otsu3slow(limg) elif menu_items[5].IsChecked(): t1, t2 = entropy3(limg) else: t1, t2 = otsu3(limg) if lt: t1, t2 = inverse_log_transform(np.array([t1, t2]), d) m1 = img < t1 m2 = np.logical_and(img >= t1, img < t2) m3 = img > t2 cimg = np.zeros((m1.shape[0], m1.shape[1], 3)) cimg[:, :, 0][m1] = img[m1] cimg[:, :, 1][m2] = img[m2] cimg[:, :, 2][m3] = img[m3] self.frame.subplot_imshow(1, 0, cimg, sharex=self.frame.subplot(0, 0), sharey=self.frame.subplot(0, 0)) self.frame.Refresh() wx.MessageBox("Low threshold = %f, high threshold = %f" % (t1, t2), parent=self.frame)
def test_05_02_otsu_entropy(self): '''Test the entropy version of Otsu''' np.random.seed(0) image = np.hstack((np.random.exponential(1.5,size=600), np.random.poisson(15,size=300))) image.shape=(30,30) image = stretch(image) limage, d = T.log_transform(image) threshold = entropy(limage) threshold = T.inverse_log_transform(threshold, d) expected = image > threshold workspace, module = self.make_workspace(image) module.binary.value = A.BINARY module.threshold_method.value = T.TM_OTSU_GLOBAL module.use_weighted_variance.value = I.O_ENTROPY module.two_class_otsu.value = I.O_TWO_CLASS module.run(workspace) output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME) self.assertTrue(np.all(output.pixel_data == expected))
def run_image_gabor(self, image_name, scale, workspace): image = workspace.image_set.get_image(image_name, must_be_grayscale=True) pixel_data = image.pixel_data labels = np.ones(pixel_data.shape, int) if image.has_mask: labels[~image.mask] = 0 pixel_data = stretch(pixel_data, labels > 0) best_score = 0 for angle in range(self.gabor_angles.value): theta = np.pi * angle / self.gabor_angles.value g = gabor(pixel_data, labels, scale, theta) score_r = np.sum(g.real) score_i = np.sum(g.imag) score = np.sqrt(score_r**2 + score_i**2) best_score = max(best_score, score) statistics = self.record_image_measurement(workspace, image_name, scale, F_GABOR, best_score) return statistics
def test_05_06_otsu3_entropy_high(self): '''Test the three-class otsu, entropy, middle = background''' np.random.seed(0) image = np.hstack((np.random.exponential(1.5,size=300), np.random.poisson(15,size=300), np.random.poisson(30,size=300))) image.shape=(30,30) image = stretch(image) limage, d = T.log_transform(image) t1,t2 = entropy3(limage) threshold = T.inverse_log_transform(t1, d) expected = image > threshold workspace, module = self.make_workspace(image) module.binary.value = A.BINARY module.threshold_method.value = T.TM_OTSU_GLOBAL module.use_weighted_variance.value = I.O_ENTROPY module.two_class_otsu.value = I.O_THREE_CLASS module.assign_middle_to_foreground.value = I.O_FOREGROUND module.run(workspace) output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME) self.assertTrue(np.all(output.pixel_data == expected))
def test_05_06_otsu3_entropy_high(self): '''Test the three-class otsu, entropy, middle = background''' np.random.seed(0) image = np.hstack( (np.random.exponential(1.5, size=300), np.random.poisson(15, size=300), np.random.poisson(30, size=300))) image.shape = (30, 30) image = stretch(image) limage, d = T.log_transform(image) t1, t2 = entropy3(limage) threshold = T.inverse_log_transform(t1, d) expected = image > threshold workspace, module = self.make_workspace(image) module.binary.value = A.BINARY module.threshold_method.value = T.TM_OTSU_GLOBAL module.use_weighted_variance.value = I.O_ENTROPY module.two_class_otsu.value = I.O_THREE_CLASS module.assign_middle_to_foreground.value = I.O_FOREGROUND module.run(workspace) output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME) self.assertTrue(np.all(output.pixel_data == expected))
def log_transform(image): '''Renormalize image intensities to log space Returns a tuple of transformed image and a dictionary to be passed into inverse_log_transform. The minimum and maximum from the dictionary can be applied to an image by the inverse_log_transform to convert it back to its former intensity values. ''' orig_min, orig_max = scipy.ndimage.extrema(image)[:2] # # We add 1/2 bit noise to an 8 bit image to give the log a bottom # limage = image.copy() noise_min = orig_min + (orig_max-orig_min)/256.0+np.finfo(image.dtype).eps limage[limage < noise_min] = noise_min d = { "noise_min":noise_min} limage = np.log(limage) log_min, log_max = scipy.ndimage.extrema(limage)[:2] d["log_min"] = log_min d["log_max"] = log_max return stretch(limage), d
def on_file_open(self, event): dlg = wx.FileDialog(self.frame,style=wx.FD_OPEN) if dlg.ShowModal() == wx.ID_OK: img = pil_to_array(PILImage.open(os.path.join(dlg.GetDirectory(),dlg.GetFilename()))) if img.ndim == 3: img = img[:,:,0]+img[:,:,1]+img[:,:,2] img = stretch(img.astype(float)) lt = self.frame.MenuBar.Menus[0][0].MenuItems[7].IsChecked() if lt: limg, d = log_transform(img) else: limg = img self.frame.subplot_imshow_grayscale(0, 0, limg) limg = limg.flatten() menu_items = self.frame.MenuBar.Menus[0][0].MenuItems if menu_items[2].IsChecked(): t1 = t2 = otsu(limg) elif menu_items[3].IsChecked(): t1 = t2 = entropy(limg) elif menu_items[4].IsChecked(): t1, t2 = otsu3slow(limg) elif menu_items[5].IsChecked(): t1, t2 = entropy3(limg) else: t1, t2 = otsu3(limg) if lt: t1,t2 = inverse_log_transform(np.array([t1,t2]), d) m1 = img < t1 m2 = np.logical_and(img >= t1, img < t2) m3 = img > t2 cimg = np.zeros((m1.shape[0],m1.shape[1],3)) cimg[:,:,0][m1]=img[m1] cimg[:,:,1][m2]=img[m2] cimg[:,:,2][m3]=img[m3] self.frame.subplot_imshow(1, 0, cimg, sharex = self.frame.subplot(0,0), sharey = self.frame.subplot(0,0)) self.frame.Refresh() wx.MessageBox("Low threshold = %f, high threshold = %f"%(t1,t2), parent=self.frame)
def display(self, workspace): '''Display the results of relabeling workspace - workspace containing saved display data ''' from cellprofiler.gui.cpfigure import renumber_labels_for_display import matplotlib.cm as cm figure = workspace.create_or_find_figure(title="ReassignObjectNumbers, image cycle #%d"%( workspace.measurements.image_set_number),subplots=(1,2)) figure.subplot_imshow_labels(0,0, workspace.display_data.orig_labels, title = self.objects_name.value) if self.wants_image: # # Make a nice picture which superimposes the labels on the # guiding image # output_labels = renumber_labels_for_display( workspace.display_data.output_labels) image = (stretch(workspace.display_data.image) * 255).astype(np.uint8) image = np.dstack((image,image,image)) my_cm = cm.get_cmap(cpprefs.get_default_colormap()) my_cm.set_bad((0,0,0)) sm = cm.ScalarMappable(cmap=my_cm) m_output_labels = np.ma.array(output_labels, mask = output_labels == 0) output_image = sm.to_rgba(m_output_labels, bytes=True)[:,:,:3] image[output_labels > 0 ] = ( image[output_labels > 0] / 4 * 3 + output_image[output_labels > 0,:] / 4) figure.subplot_imshow(0,1, image, title = self.output_objects_name.value, sharex = figure.subplot(0,0), sharey = figure.subplot(0,0)) else: figure.subplot_imshow_labels(0,1, workspace.display_data.output_labels, title = self.output_objects_name.value, sharex = figure.subplot(0,0), sharey = figure.subplot(0,0))
def run_image_gabor(self, image_name, scale, workspace): image = workspace.image_set.get_image(image_name, must_be_grayscale=True) pixel_data = image.pixel_data labels = np.ones(pixel_data.shape, int) if image.has_mask: labels[~image.mask] = 0 pixel_data = stretch(pixel_data, labels > 0) best_score = 0 for angle in range(self.gabor_angles.value): theta = np.pi * angle / self.gabor_angles.value g = gabor(pixel_data, labels, scale, theta) score_r = np.sum(g.real) score_i = np.sum(g.imag) score = np.sqrt(score_r**2+score_i**2) best_score = max(best_score, score) statistics = self.record_image_measurement(workspace, image_name, scale, F_GABOR, best_score) return statistics
def test_05_04_otsu3_wv_high(self): '''Test the three-class otsu, weighted variance middle = foreground''' np.random.seed(0) image = np.hstack((np.random.exponential(1.5,size=300), np.random.poisson(15,size=300), np.random.poisson(30,size=300))) image.shape=(30,30) image = stretch(image) limage, d = T.log_transform(image) t1,t2 = otsu3(limage) threshold = T.inverse_log_transform(t1, d) workspace, module = self.make_workspace(image) module.binary.value = A.BINARY module.threshold_scope.value = I.TS_GLOBAL module.threshold_method.value = T.TM_OTSU module.use_weighted_variance.value = I.O_WEIGHTED_VARIANCE module.two_class_otsu.value = I.O_THREE_CLASS module.assign_middle_to_foreground.value = I.O_FOREGROUND module.run(workspace) m = workspace.measurements m_threshold = m[cpmeas.IMAGE, I.FF_ORIG_THRESHOLD % module.get_measurement_objects_name()] self.assertAlmostEqual(m_threshold, threshold)
def test_05_05_otsu3_entropy_low(self): '''Test the three-class otsu, entropy, middle = background''' np.random.seed(0) image = np.hstack((np.random.exponential(1.5,size=300), np.random.poisson(15,size=300), np.random.poisson(30,size=300))) image.shape=(30,30) image = stretch(image) limage, d = T.log_transform(image) t1,t2 = entropy3(limage) threshold = T.inverse_log_transform(t2, d) workspace, module = self.make_workspace(image) module.binary.value = A.BINARY module.threshold_scope.value = I.TS_GLOBAL module.threshold_method.value = T.TM_OTSU module.use_weighted_variance.value = I.O_ENTROPY module.two_class_otsu.value = I.O_THREE_CLASS module.assign_middle_to_foreground.value = I.O_BACKGROUND module.run(workspace) output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME) m = workspace.measurements m_threshold = m[cpmeas.IMAGE, I.FF_ORIG_THRESHOLD % module.get_measurement_objects_name()] self.assertAlmostEqual(m_threshold, threshold)
def display(self, workspace, figure): from identify import TS_BINARY_IMAGE object_pct = workspace.display_data.object_pct img = workspace.display_data.img primary_outline = workspace.display_data.primary_outline secondary_outline = workspace.display_data.secondary_outline segmented_out = workspace.display_data.segmented_out global_threshold = workspace.display_data.global_threshold object_count = workspace.display_data.object_count statistics = workspace.display_data.statistics if global_threshold is not None: statistics.append(["Threshold", "%.3f" % global_threshold]) if object_count > 0: areas = scind.sum(np.ones(segmented_out.shape), segmented_out, np.arange(1, object_count + 1)) areas.sort() low_diameter = (np.sqrt(float(areas[object_count / 10]) / np.pi) * 2) median_diameter = ( np.sqrt(float(areas[object_count / 2]) / np.pi) * 2) high_diameter = ( np.sqrt(float(areas[object_count * 9 / 10]) / np.pi) * 2) statistics.append( ["10th pctile diameter", "%.1f pixels" % (low_diameter)]) statistics.append( ["Median diameter", "%.1f pixels" % (median_diameter)]) statistics.append( ["90th pctile diameter", "%.1f pixels" % (high_diameter)]) if self.method != M_DISTANCE_N and self.threshold_scope != TS_BINARY_IMAGE: statistics.append([ "Thresholding filter size", "%.1f" % (workspace.display_data.threshold_sigma) ]) statistics.append( ["Area covered by objects", "%.1f %%" % object_pct]) workspace.display_data.statistics = statistics figure.set_subplots((2, 2)) title = "Input image, cycle #%d" % ( workspace.measurements.image_number) figure.subplot_imshow_grayscale(0, 0, img, title) figure.subplot_imshow_labels(1, 0, segmented_out, "%s objects" % self.objects_name.value, sharexy=figure.subplot(0, 0)) primary_img = np.dstack((img, img, img)) # # Stretch the outline image to the full scale # primary_img = stretch(primary_img) # Outline the primary objects cpmi.draw_outline(primary_img, primary_outline > 0, cpprefs.get_primary_outline_color()) # Outline the secondary objects cpmi.draw_outline(primary_img, secondary_outline > 0, cpprefs.get_secondary_outline_color()) figure.subplot_imshow( 0, 1, primary_img, "%s and %s outlines" % (self.primary_objects.value, self.objects_name.value), normalize=False, sharexy=figure.subplot(0, 0)) figure.subplot_table( 1, 1, [[x[1]] for x in workspace.display_data.statistics], row_labels=[x[0] for x in workspace.display_data.statistics])
def run(self, workspace): image = workspace.image_set.get_image(self.image_name.value, must_be_grayscale=True) orig_pixels = image.pixel_data if image.has_mask: mask = image.mask else: mask = np.ones(orig_pixels.shape, bool) if self.method == M_SOBEL: if self.direction == E_ALL: output_pixels = sobel(orig_pixels, mask) elif self.direction == E_HORIZONTAL: output_pixels = hsobel(orig_pixels, mask) elif self.direction == E_VERTICAL: output_pixels = vsobel(orig_pixels, mask) else: raise NotImplementedError( "Unimplemented direction for Sobel: %s", self.direction.value) elif self.method == M_LOG: sigma = self.get_sigma() size = int(sigma * 4) + 1 output_pixels = laplacian_of_gaussian(orig_pixels, mask, size, sigma) elif self.method == M_PREWITT: if self.direction == E_ALL: output_pixels = prewitt(orig_pixels) elif self.direction == E_HORIZONTAL: output_pixels = hprewitt(orig_pixels, mask) elif self.direction == E_VERTICAL: output_pixels = vprewitt(orig_pixels, mask) else: raise NotImplementedError( "Unimplemented direction for Prewitt: %s", self.direction.value) elif self.method == M_CANNY: high_threshold = self.manual_threshold.value low_threshold = self.low_threshold.value if (self.wants_automatic_low_threshold.value or self.wants_automatic_threshold.value): sobel_image = sobel(orig_pixels, mask) low, high = otsu3(sobel_image[mask]) if self.wants_automatic_low_threshold.value: low_threshold = low * self.threshold_adjustment_factor.value if self.wants_automatic_threshold.value: high_threshold = high * self.threshold_adjustment_factor.value output_pixels = canny(orig_pixels, mask, self.get_sigma(), low_threshold, high_threshold) elif self.method == M_ROBERTS: output_pixels = roberts(orig_pixels, mask) else: raise NotImplementedError( "Unimplemented edge detection method: %s" % self.method.value) if not workspace.frame is None: figure = workspace.create_or_find_figure( title="EnhanceEdges, image cycle #%d" % (workspace.measurements.image_set_number), subplots=(2, 2)) figure.subplot_imshow_grayscale( 0, 0, orig_pixels, "Original: %s" % self.image_name.value) if self.method == M_CANNY: # Canny is binary figure.subplot_imshow_bw(0, 1, output_pixels, self.output_image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0)) else: figure.subplot_imshow_grayscale(0, 1, output_pixels, self.output_image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0)) color_image = np.zeros( (output_pixels.shape[0], output_pixels.shape[1], 3)) color_image[:, :, 0] = stretch(orig_pixels) color_image[:, :, 1] = stretch(output_pixels) figure.subplot_imshow(1, 0, color_image, "Composite image", sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0)) output_image = cpi.Image(output_pixels, parent_image=image) workspace.image_set.add(self.output_image_name.value, output_image)
def stretch(self, input_image): '''Stretch the input image to the range 0:1''' if input_image.has_mask: return stretch(input_image.pixel_data, input_image.mask) else: return stretch(input_image.pixel_data)
def handle_interaction(self, current_shape, orig_image): '''Show the cropping user interface''' import matplotlib as M import matplotlib.cm import wx from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg pixel_data = stretch(orig_image) # # Create the UI - a dialog with a figure inside # style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER dialog_box = wx.Dialog(wx.GetApp().TopWindow, -1, "Select the cropping region", size=(640,480), style = style) sizer = wx.BoxSizer(wx.VERTICAL) figure = matplotlib.figure.Figure() panel = FigureCanvasWxAgg(dialog_box, -1, figure) sizer.Add(panel, 1, wx.EXPAND) btn_sizer = wx.StdDialogButtonSizer() btn_sizer.AddButton(wx.Button(dialog_box, wx.ID_OK)) btn_sizer.AddButton(wx.Button(dialog_box, wx.ID_CANCEL)) btn_sizer.Realize() sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5) dialog_box.SetSizer(sizer) dialog_box.Size = dialog_box.BestSize dialog_box.Layout() axes = figure.add_subplot(1,1,1) assert isinstance(axes, matplotlib.axes.Axes) if pixel_data.ndim == 2: axes.imshow(pixel_data, matplotlib.cm.Greys_r, origin="upper") else: axes.imshow(pixel_data, origin="upper") #t = axes.transData.inverted() current_handle = [ None ] def data_xy(mouse_event): '''Return the mouse event's x & y converted into data-relative coords''' x = mouse_event.xdata y = mouse_event.ydata return (x,y) class handle(M.patches.Rectangle): dm = max((10,min(pixel_data.shape)/50)) height, width = (dm,dm) def __init__(self, x, y, on_move): x = max(0, min(x, pixel_data.shape[1])) y = max(0, min(y, pixel_data.shape[0])) self.__selected = False self.__color = cpprefs.get_primary_outline_color() self.__color = np.hstack((self.__color,[255])).astype(float) / 255.0 self.__on_move = on_move super(handle, self).__init__((x-self.width/2, y-self.height/2), self.width, self.height, edgecolor = self.__color, facecolor = "none") self.set_picker(True) def move(self, x, y): self.set_xy((x-self.width/2, y-self.height/2)) self.__on_move(x, y) def select(self, on): self.__selected = on if on: current_handle[0] = self self.set_facecolor(self.__color) else: self.set_facecolor("none") if current_handle[0] == self: current_handle[0] = None figure.canvas.draw() dialog_box.Update() @property def is_selected(self): return self.__selected @property def center_x(self): '''The handle's notion of its x coordinate''' return self.get_x() + self.get_width() / 2 @property def center_y(self): '''The handle's notion of its y coordinate''' return self.get_y() + self.get_height() / 2 def handle_pick(self, event): mouse_event = event.mouseevent x, y = data_xy(mouse_event) if mouse_event.button == 1: self.select(True) self.orig_x = self.center_x self.orig_y = self.center_y self.first_x = x self.first_y = y def handle_mouse_move_event(self, event): x,y = data_xy(event) if x is None or y is None: return x = x - self.first_x + self.orig_x y = y - self.first_y + self.orig_y if x < 0: x = 0 if x >= pixel_data.shape[1]: x = pixel_data.shape[1] -1 if y < 0: y = 0 if y >= pixel_data.shape[0]: y = pixel_data.shape[0] -1 self.move(x, y) class crop_rectangle(object): def __init__(self, top_left, bottom_right): self.__left, self.__top = top_left self.__right, self.__bottom = bottom_right color = cpprefs.get_primary_outline_color() color = np.hstack((color,[255])).astype(float) / 255.0 self.rectangle = M.patches.Rectangle( (min(self.__left, self.__right), min(self.__bottom, self.__top)), abs(self.__right - self.__left), abs(self.__top - self.__bottom), edgecolor = color, facecolor = "none" ) self.top_left_handle = handle(top_left[0], top_left[1], self.handle_top_left) self.bottom_right_handle = handle(bottom_right[0], bottom_right[1], self.handle_bottom_right) def handle_top_left(self, x, y): self.__left = x self.__top = y self.__reshape() def handle_bottom_right(self, x, y): self.__right = x self.__bottom = y self.__reshape() def __reshape(self): self.rectangle.set_xy((min(self.__left, self.__right), min(self.__bottom,self.__top))) self.rectangle.set_width(abs(self.__right - self.__left)) self.rectangle.set_height(abs(self.__bottom - self.__top)) self.rectangle.figure.canvas.draw() dialog_box.Update() @property def patches(self): return [self.rectangle, self.top_left_handle, self.bottom_right_handle] @property def handles(self): return [self.top_left_handle, self.bottom_right_handle] @property def left(self): return min(self.__left, self.__right) @property def right(self): return max(self.__left, self.__right) @property def top(self): return min(self.__top, self.__bottom) @property def bottom(self): return max(self.__top, self.__bottom) class crop_ellipse(object): def __init__(self, center, radius): '''Draw an ellipse with control points at the ellipse center and a given x and y radius''' self.center_x, self.center_y = center self.radius_x = self.center_x + radius[0] / 2 self.radius_y = self.center_y + radius[1] / 2 color = cpprefs.get_primary_outline_color() color = np.hstack((color,[255])).astype(float) / 255.0 self.ellipse = M.patches.Ellipse(center, self.width, self.height, edgecolor = color, facecolor = "none") self.center_handle = handle(self.center_x, self.center_y, self.move_center) self.radius_handle = handle(self.radius_x, self.radius_y, self.move_radius) def move_center(self, x, y): self.center_x = x self.center_y = y self.redraw() def move_radius(self, x, y): self.radius_x = x self.radius_y = y self.redraw() @property def width(self): return abs(self.center_x - self.radius_x) * 4 @property def height(self): return abs(self.center_y - self.radius_y) * 4 def redraw(self): self.ellipse.center = (self.center_x, self.center_y) self.ellipse.width = self.width self.ellipse.height = self.height self.ellipse.figure.canvas.draw() dialog_box.Update() @property def patches(self): return [self.ellipse, self.center_handle, self.radius_handle] @property def handles(self): return [self.center_handle, self.radius_handle] if self.shape == SH_ELLIPSE: if current_shape is None: current_shape = { EL_XCENTER: pixel_data.shape[1] / 2, EL_YCENTER: pixel_data.shape[0] / 2, EL_XRADIUS: pixel_data.shape[1] / 2, EL_YRADIUS: pixel_data.shape[0] / 2 } ellipse = current_shape shape = crop_ellipse((ellipse[EL_XCENTER], ellipse[EL_YCENTER]), (ellipse[EL_XRADIUS], ellipse[EL_YRADIUS])) else: if current_shape is None: current_shape = { RE_LEFT: pixel_data.shape[1] / 4, RE_TOP: pixel_data.shape[0] / 4, RE_RIGHT: pixel_data.shape[1] * 3 / 4, RE_BOTTOM: pixel_data.shape[0] * 3 / 4 } rectangle = current_shape shape = crop_rectangle((rectangle[RE_LEFT], rectangle[RE_TOP]), (rectangle[RE_RIGHT], rectangle[RE_BOTTOM])) for patch in shape.patches: axes.add_artist(patch) def on_mouse_down_event(event): axes.pick(event) def on_mouse_move_event(event): if current_handle[0] is not None: current_handle[0].handle_mouse_move_event(event) def on_mouse_up_event(event): if current_handle[0] is not None: current_handle[0].select(False) def on_pick_event(event): for h in shape.handles: if id(h) == id(event.artist): h.handle_pick(event) figure.canvas.mpl_connect('button_press_event', on_mouse_down_event) figure.canvas.mpl_connect('button_release_event', on_mouse_up_event) figure.canvas.mpl_connect('motion_notify_event', on_mouse_move_event) figure.canvas.mpl_connect('pick_event', on_pick_event) try: if dialog_box.ShowModal() != wx.ID_OK: raise ValueError("Cancelled by user") finally: dialog_box.Destroy() if self.shape == SH_RECTANGLE: return { RE_LEFT: shape.left, RE_TOP: shape.top, RE_RIGHT: shape.right, RE_BOTTOM: shape.bottom } else: return { EL_XCENTER: shape.center_x, EL_YCENTER: shape.center_y, EL_XRADIUS: shape.width / 2, EL_YRADIUS: shape.height / 2 }
def run(self, workspace): image = workspace.image_set.get_image(self.image_name.value, must_be_grayscale = True) orig_pixels = image.pixel_data if image.has_mask: mask = image.mask else: mask = np.ones(orig_pixels.shape,bool) if self.method == M_SOBEL: if self.direction == E_ALL: output_pixels = sobel(orig_pixels, mask) elif self.direction == E_HORIZONTAL: output_pixels = hsobel(orig_pixels, mask) elif self.direction == E_VERTICAL: output_pixels = vsobel(orig_pixels, mask) else: raise NotImplementedError("Unimplemented direction for Sobel: %s",self.direction.value) elif self.method == M_LOG: sigma = self.get_sigma() size = int(sigma * 4)+1 output_pixels = laplacian_of_gaussian(orig_pixels, mask, size, sigma) elif self.method == M_PREWITT: if self.direction == E_ALL: output_pixels = prewitt(orig_pixels) elif self.direction == E_HORIZONTAL: output_pixels = hprewitt(orig_pixels, mask) elif self.direction == E_VERTICAL: output_pixels = vprewitt(orig_pixels, mask) else: raise NotImplementedError("Unimplemented direction for Prewitt: %s",self.direction.value) elif self.method == M_CANNY: high_threshold = self.manual_threshold.value low_threshold = self.low_threshold.value if (self.wants_automatic_low_threshold.value or self.wants_automatic_threshold.value): sobel_image = sobel(orig_pixels, mask) low, high = otsu3(sobel_image[mask]) if self.wants_automatic_low_threshold.value: low_threshold = low * self.threshold_adjustment_factor.value if self.wants_automatic_threshold.value: high_threshold = high * self.threshold_adjustment_factor.value output_pixels = canny(orig_pixels,mask, self.get_sigma(), low_threshold, high_threshold) elif self.method == M_ROBERTS: output_pixels = roberts(orig_pixels, mask) else: raise NotImplementedError("Unimplemented edge detection method: %s"% self.method.value) if not workspace.frame is None: figure = workspace.create_or_find_figure(title="EnhanceEdges, image cycle #%d"%( workspace.measurements.image_set_number),subplots=(2,2)) figure.subplot_imshow_grayscale(0,0, orig_pixels, "Original: %s"% self.image_name.value) if self.method == M_CANNY: # Canny is binary figure.subplot_imshow_bw(0,1, output_pixels, self.output_image_name.value, sharex = figure.subplot(0,0), sharey = figure.subplot(0,0)) else: figure.subplot_imshow_grayscale(0,1,output_pixels, self.output_image_name.value, sharex = figure.subplot(0,0), sharey = figure.subplot(0,0)) color_image = np.zeros((output_pixels.shape[0], output_pixels.shape[1],3)) color_image[:,:,0] = stretch(orig_pixels) color_image[:,:,1] = stretch(output_pixels) figure.subplot_imshow(1,0, color_image,"Composite image", sharex = figure.subplot(0,0), sharey = figure.subplot(0,0)) output_image = cpi.Image(output_pixels, parent_image = image) workspace.image_set.add(self.output_image_name.value, output_image)