def run(self, workspace): image_name = self.image_name.value objects_name = self.objects_name.value image = workspace.image_set.get_image(image_name) pixel_data = image.pixel_data labels = workspace.interaction_request( self, pixel_data, workspace.measurements.image_set_number) if labels is None: # User cancelled. Soldier on as best we can. workspace.cancel_request() labels = numpy.zeros(pixel_data.shape[:2], int) objects = Objects() objects.segmented = labels workspace.object_set.add_objects(objects, objects_name) ################## # # Add measurements # m = workspace.measurements # # The object count # object_count = numpy.max(labels) add_object_count_measurements(m, objects_name, object_count) # # The object locations # add_object_location_measurements(m, objects_name, labels) workspace.display_data.labels = labels workspace.display_data.pixel_data = pixel_data
def run(self, workspace): """Find the outlines on the current image set workspace - The workspace contains pipeline - instance of cpp for this run image_set - the images in the image set being processed object_set - the objects (labeled masks) in this image set measurements - the measurements for this run frame - the parent frame to whatever frame is created. None means don't draw. """ gridding = workspace.get_grid(self.grid_name.value) if self.shape_choice == SHAPE_RECTANGLE: labels = self.run_rectangle(workspace, gridding) elif self.shape_choice == SHAPE_CIRCLE_FORCED: labels = self.run_forced_circle(workspace, gridding) elif self.shape_choice == SHAPE_CIRCLE_NATURAL: labels = self.run_natural_circle(workspace, gridding) elif self.shape_choice == SHAPE_NATURAL: labels = self.run_natural(workspace, gridding) objects = Objects() objects.segmented = labels object_count = gridding.rows * gridding.columns workspace.object_set.add_objects(objects, self.output_objects_name.value) add_object_location_measurements(workspace.measurements, self.output_objects_name.value, labels, object_count) add_object_count_measurements(workspace.measurements, self.output_objects_name.value, object_count) if self.show_window: workspace.display_data.gridding = gridding workspace.display_data.labels = labels
def run(self, workspace): input_objects = workspace.object_set.get_objects( self.object_name.value) output_objects = cpo.Objects() output_objects.segmented = self.do_labels(input_objects.segmented) if input_objects.has_small_removed_segmented: output_objects.small_removed_segmented = self.do_labels( input_objects.small_removed_segmented) if input_objects.has_unedited_segmented: output_objects.unedited_segmented = self.do_labels( input_objects.unedited_segmented) workspace.object_set.add_objects(output_objects, self.output_object_name.value) add_object_count_measurements( workspace.measurements, self.output_object_name.value, np.max(output_objects.segmented), ) add_object_location_measurements( workspace.measurements, self.output_object_name.value, output_objects.segmented, ) if self.show_window: workspace.display_data.input_objects_segmented = input_objects.segmented workspace.display_data.output_objects_segmented = output_objects.segmented
def run(self, workspace): input_objects = workspace.object_set.get_objects( self.object_name.value) output_objects = cellprofiler_core.object.Objects() output_objects.segmented = self.do_labels(input_objects.segmented) # If we're shrinking objects we treat objects from the final segmentation as truth when generating # the unedited segmentations. This prevents edited/hole-filled objects from ending up with slightly # different centers (which would impact other modules). if input_objects.has_small_removed_segmented and self.operation not in ( O_EXPAND, O_EXPAND_INF, O_DIVIDE, ): shrunk_objects = self.do_labels( input_objects.small_removed_segmented) output_objects.small_removed_segmented = numpy.where( input_objects.segmented > 0, output_objects.segmented, shrunk_objects) if input_objects.has_unedited_segmented and self.operation not in ( O_EXPAND, O_EXPAND_INF, O_DIVIDE, ): shrunk_objects = self.do_labels(input_objects.unedited_segmented) output_objects.unedited_segmented = numpy.where( input_objects.segmented > 0, output_objects.segmented, shrunk_objects) workspace.object_set.add_objects(output_objects, self.output_object_name.value) add_object_count_measurements( workspace.measurements, self.output_object_name.value, numpy.max(output_objects.segmented), ) add_object_location_measurements( workspace.measurements, self.output_object_name.value, output_objects.segmented, ) if self.show_window: workspace.display_data.input_objects_segmented = input_objects.segmented workspace.display_data.output_objects_segmented = output_objects.segmented
def run(self, workspace): for object_name in (self.objects_x.value, self.objects_y.value): if object_name not in workspace.object_set.object_names: raise ValueError( "The %s objects are missing from the pipeline." % object_name) objects_x = workspace.object_set.get_objects(self.objects_x.value) objects_y = workspace.object_set.get_objects(self.objects_y.value) dimensions = objects_x.dimensions assert (objects_x.shape == objects_y.shape ), "Objects sets must have the same dimensions" labels_x = objects_x.segmented.copy().astype("uint16") labels_y = objects_y.segmented.copy().astype("uint16") output = combineobjects(self.merge_method.value, labels_x, labels_y, dimensions) output_labels = skimage.morphology.label(output) output_objects = Objects() output_objects.segmented = output_labels workspace.object_set.add_objects(output_objects, self.output_object.value) m = workspace.measurements object_count = numpy.max(output_labels) add_object_count_measurements(m, self.output_object.value, object_count) add_object_location_measurements(m, self.output_object.value, output_labels) if self.show_window: workspace.display_data.input_object_x_name = self.objects_x.value workspace.display_data.input_object_x = objects_x.segmented workspace.display_data.input_object_y_name = self.objects_y.value workspace.display_data.input_object_y = objects_y.segmented workspace.display_data.output_object_name = self.output_object.value workspace.display_data.output_object = output_objects.segmented workspace.display_data.dimensions = dimensions
def run(self, workspace): """Run the module on the current data set workspace - has the current image set, object set, measurements and the parent frame for the application if the module is allowed to display. If the module should not display, workspace.frame is None. """ # # The object set holds "objects". Each of these is a container # for holding up to three kinds of image labels. # object_set = workspace.object_set # # Get the primary objects (the centers to be removed). # Get the string value out of primary_object_name. # primary_objects = object_set.get_objects( self.primary_objects_name.value) # # Get the cleaned-up labels image # primary_labels = primary_objects.segmented # # Do the same with the secondary object secondary_objects = object_set.get_objects( self.secondary_objects_name.value) secondary_labels = secondary_objects.segmented # # If one of the two label images is smaller than the other, we # try to find the cropping mask and we apply that mask to the larger # try: if any([ p_size < s_size for p_size, s_size in zip( primary_labels.shape, secondary_labels.shape) ]): # # Look for a cropping mask associated with the primary_labels # and apply that mask to resize the secondary labels # secondary_labels = primary_objects.crop_image_similarly( secondary_labels) tertiary_image = primary_objects.parent_image elif any([ p_size > s_size for p_size, s_size in zip( primary_labels.shape, secondary_labels.shape) ]): primary_labels = secondary_objects.crop_image_similarly( primary_labels) tertiary_image = secondary_objects.parent_image elif secondary_objects.parent_image is not None: tertiary_image = secondary_objects.parent_image else: tertiary_image = primary_objects.parent_image except ValueError: # No suitable cropping - resize all to fit the secondary # labels which are the most critical. # primary_labels, _ = size_similarly(secondary_labels, primary_labels) if secondary_objects.parent_image is not None: tertiary_image = secondary_objects.parent_image else: tertiary_image = primary_objects.parent_image if tertiary_image is not None: tertiary_image, _ = size_similarly(secondary_labels, tertiary_image) # If size/shape differences were too extreme, raise an error. if primary_labels.shape != secondary_labels.shape: raise ValueError( "This module requires that the object sets have matching widths and matching heights.\n" "The %s and %s objects do not (%s vs %s).\n" "If they are paired correctly you may want to use the ResizeObjects module " "to make them the same size." % ( self.secondary_objects_name, self.primary_objects_name, secondary_labels.shape, primary_labels.shape, )) # # Find the outlines of the primary image and use this to shrink the # primary image by one. This guarantees that there is something left # of the secondary image after subtraction # primary_outline = outline(primary_labels) tertiary_labels = secondary_labels.copy() if self.shrink_primary: primary_mask = numpy.logical_or(primary_labels == 0, primary_outline) else: primary_mask = primary_labels == 0 tertiary_labels[primary_mask == False] = 0 # # Get the outlines of the tertiary image # tertiary_outlines = outline(tertiary_labels) != 0 # # Make the tertiary objects container # tertiary_objects = Objects() tertiary_objects.segmented = tertiary_labels tertiary_objects.parent_image = tertiary_image # # Relate tertiary objects to their parents & record # child_count_of_secondary, secondary_parents = secondary_objects.relate_children( tertiary_objects) if self.shrink_primary: child_count_of_primary, primary_parents = primary_objects.relate_children( tertiary_objects) else: # Primary and tertiary don't overlap. # Establish overlap between primary and secondary and commute _, secondary_of_primary = secondary_objects.relate_children( primary_objects) mask = secondary_of_primary != 0 child_count_of_primary = numpy.zeros(mask.shape, int) child_count_of_primary[mask] = child_count_of_secondary[ secondary_of_primary[mask] - 1] primary_parents = numpy.zeros(secondary_parents.shape, secondary_parents.dtype) primary_of_secondary = numpy.zeros(secondary_objects.count + 1, int) primary_of_secondary[secondary_of_primary] = numpy.arange( 1, len(secondary_of_primary) + 1) primary_of_secondary[0] = 0 primary_parents = primary_of_secondary[secondary_parents] # # Write out the objects # workspace.object_set.add_objects(tertiary_objects, self.subregion_objects_name.value) # # Write out the measurements # m = workspace.measurements # # The parent/child associations # for parent_objects_name, parents_of, child_count, relationship in ( ( self.primary_objects_name, primary_parents, child_count_of_primary, R_REMOVED, ), ( self.secondary_objects_name, secondary_parents, child_count_of_secondary, R_PARENT, ), ): m.add_measurement( self.subregion_objects_name.value, FF_PARENT % parent_objects_name.value, parents_of, ) m.add_measurement( parent_objects_name.value, FF_CHILDREN_COUNT % self.subregion_objects_name.value, child_count, ) mask = parents_of != 0 image_number = numpy.ones(numpy.sum(mask), int) * m.image_set_number child_object_number = numpy.argwhere(mask).flatten() + 1 parent_object_number = parents_of[mask] m.add_relate_measurement( self.module_num, relationship, parent_objects_name.value, self.subregion_objects_name.value, image_number, parent_object_number, image_number, child_object_number, ) object_count = tertiary_objects.count # # The object count # add_object_count_measurements(workspace.measurements, self.subregion_objects_name.value, object_count) # # The object locations # add_object_location_measurements(workspace.measurements, self.subregion_objects_name.value, tertiary_labels) if self.show_window: workspace.display_data.primary_labels = primary_labels workspace.display_data.secondary_labels = secondary_labels workspace.display_data.tertiary_labels = tertiary_labels workspace.display_data.tertiary_outlines = tertiary_outlines
def run(self, workspace): """Run the module on an image set""" object_name = self.object_name.value remaining_object_name = self.remaining_objects.value original_objects = workspace.object_set.get_objects(object_name) if self.mask_choice == MC_IMAGE: mask = workspace.image_set.get_image( self.masking_image.value, must_be_binary=True ) mask = mask.pixel_data else: masking_objects = workspace.object_set.get_objects( self.masking_objects.value ) mask = masking_objects.segmented > 0 if self.wants_inverted_mask: mask = ~mask # # Load the labels # labels = original_objects.segmented.copy() nobjects = numpy.max(labels) # # Resize the mask to cover the objects # mask, m1 = size_similarly(labels, mask) mask[~m1] = False # # Apply the mask according to the overlap choice. # if nobjects == 0: pass elif self.overlap_choice == P_MASK: labels = labels * mask else: pixel_counts = fixup_scipy_ndimage_result( scipy.ndimage.sum( mask, labels, numpy.arange(1, nobjects + 1, dtype=numpy.int32) ) ) if self.overlap_choice == P_KEEP: keep = pixel_counts > 0 else: total_pixels = fixup_scipy_ndimage_result( scipy.ndimage.sum( numpy.ones(labels.shape), labels, numpy.arange(1, nobjects + 1, dtype=numpy.int32), ) ) if self.overlap_choice == P_REMOVE: keep = pixel_counts == total_pixels elif self.overlap_choice == P_REMOVE_PERCENTAGE: fraction = self.overlap_fraction.value keep = pixel_counts / total_pixels >= fraction else: raise NotImplementedError( "Unknown overlap-handling choice: %s", self.overlap_choice.value ) keep = numpy.hstack(([False], keep)) labels[~keep[labels]] = 0 # # Renumber the labels matrix if requested # if self.retain_or_renumber == R_RENUMBER: unique_labels = numpy.unique(labels[labels != 0]) indexer = numpy.zeros(nobjects + 1, int) indexer[unique_labels] = numpy.arange(1, len(unique_labels) + 1) labels = indexer[labels] parent_objects = unique_labels else: parent_objects = numpy.arange(1, nobjects + 1) # # Add the objects # remaining_objects = Objects() remaining_objects.segmented = labels remaining_objects.unedited_segmented = original_objects.unedited_segmented workspace.object_set.add_objects(remaining_objects, remaining_object_name) # # Add measurements # m = workspace.measurements m.add_measurement( remaining_object_name, FF_PARENT % object_name, parent_objects, ) if numpy.max(original_objects.segmented) == 0: child_count = numpy.array([], int) else: child_count = fixup_scipy_ndimage_result( scipy.ndimage.sum( labels, original_objects.segmented, numpy.arange(1, nobjects + 1, dtype=numpy.int32), ) ) child_count = (child_count > 0).astype(int) m.add_measurement( object_name, FF_CHILDREN_COUNT % remaining_object_name, child_count, ) if self.retain_or_renumber == R_RETAIN: remaining_object_count = nobjects else: remaining_object_count = len(unique_labels) add_object_count_measurements(m, remaining_object_name, remaining_object_count) add_object_location_measurements(m, remaining_object_name, labels) # # Save the input, mask and output images for display # if self.show_window: workspace.display_data.original_labels = original_objects.segmented workspace.display_data.final_labels = labels workspace.display_data.mask = mask
def run(self, workspace): objects_name = self.objects_name.value objects = workspace.object_set.get_objects(objects_name) assert isinstance(objects, Objects) labels = objects.segmented if self.relabel_option == OPTION_SPLIT: output_labels, count = scipy.ndimage.label( labels > 0, numpy.ones((3, 3), bool)) else: if self.merge_option == UNIFY_DISTANCE: mask = labels > 0 if self.distance_threshold.value > 0: # # Take the distance transform of the reverse of the mask # and figure out what points are less than 1/2 of the # distance from an object. # d = scipy.ndimage.distance_transform_edt(~mask) mask = d < self.distance_threshold.value / 2 + 1 output_labels, count = scipy.ndimage.label( mask, numpy.ones((3, 3), bool)) output_labels[labels == 0] = 0 if self.wants_image: output_labels = self.filter_using_image(workspace, mask) elif self.merge_option == UNIFY_PARENT: parents_name = self.parent_object.value parents_of = workspace.measurements[objects_name, "_".join( (C_PARENT, parents_name))] output_labels = labels.copy().astype(numpy.uint32) output_labels[labels > 0] = parents_of[labels[labels > 0] - 1] if self.merging_method == UM_CONVEX_HULL: ch_pts, n_pts = centrosome.cpmorphology.convex_hull( output_labels) ijv = centrosome.cpmorphology.fill_convex_hulls( ch_pts, n_pts) output_labels[ijv[:, 0], ijv[:, 1]] = ijv[:, 2] output_objects = Objects() output_objects.segmented = output_labels if objects.has_small_removed_segmented: output_objects.small_removed_segmented = copy_labels( objects.small_removed_segmented, output_labels) if objects.has_unedited_segmented: output_objects.unedited_segmented = copy_labels( objects.unedited_segmented, output_labels) output_objects.parent_image = objects.parent_image workspace.object_set.add_objects(output_objects, self.output_objects_name.value) measurements = workspace.measurements add_object_count_measurements( measurements, self.output_objects_name.value, numpy.max(output_objects.segmented), ) add_object_location_measurements(measurements, self.output_objects_name.value, output_objects.segmented) # # Relate the output objects to the input ones and record # the relationship. # children_per_parent, parents_of_children = objects.relate_children( output_objects) measurements.add_measurement( self.objects_name.value, FF_CHILDREN_COUNT % self.output_objects_name.value, children_per_parent, ) measurements.add_measurement( self.output_objects_name.value, FF_PARENT % self.objects_name.value, parents_of_children, ) if self.show_window: workspace.display_data.orig_labels = objects.segmented workspace.display_data.output_labels = output_objects.segmented if self.merge_option == UNIFY_PARENT: workspace.display_data.parent_labels = workspace.object_set.get_objects( self.parent_object.value).segmented