def calculate_zernikes(self, workspace): zernike_indexes = cpmz.get_zernike_indexes(self.zernike_degree.value + 1) meas = workspace.measurements for o in self.objects: object_name = o.object_name.value objects = workspace.object_set.get_objects(object_name) # # First, get a table of centers and radii of minimum enclosing # circles per object # ij = np.zeros((objects.count + 1, 2)) r = np.zeros(objects.count + 1) for labels, indexes in objects.get_labels(): ij_, r_ = minimum_enclosing_circle(labels, indexes) ij[indexes] = ij_ r[indexes] = r_ # # Then compute x and y, the position of each labeled pixel # within a unit circle around the object # ijv = objects.ijv l = ijv[:, 2] yx = (ijv[:, :2] - ij[l, :]) / r[l, np.newaxis] z = cpmz.construct_zernike_polynomials( yx[:, 1], yx[:, 0], zernike_indexes) for image_group in self.images: image_name = image_group.image_name.value image = workspace.image_set.get_image( image_name, must_be_grayscale=True) pixels = image.pixel_data mask = (ijv[:, 0] < pixels.shape[0]) & \ (ijv[:, 1] < pixels.shape[1]) mask[mask] = image.mask[ijv[mask, 0], ijv[mask, 1]] yx_ = yx[mask, :] l_ = l[mask] z_ = z[mask, :] if len(l_) == 0: for i, (n, m) in enumerate(zernike_indexes): ftr = self.get_zernike_magnitude_name(image_name, n, m) meas[object_name, ftr] = np.zeros(0) if self.wants_zernikes == Z_MAGNITUDES_AND_PHASE: ftr = self.get_zernike_phase_name(image_name, n, m) meas[object_name, ftr] = np.zeros(0) continue areas = scind.sum( np.ones(l_.shape, int), labels=l_, index=objects.indices) for i, (n, m) in enumerate(zernike_indexes): vr = scind.sum( pixels[ijv[mask, 0], ijv[mask, 1]] * z_[:, i].real, labels=l_, index=objects.indices) vi = scind.sum( pixels[ijv[mask, 0], ijv[mask, 1]] * z_[:, i].imag, labels=l_, index=objects.indices) magnitude = np.sqrt(vr * vr + vi * vi) / areas ftr = self.get_zernike_magnitude_name(image_name, n, m) meas[object_name, ftr] = magnitude if self.wants_zernikes == Z_MAGNITUDES_AND_PHASE: phase = np.arctan2(vr, vi) ftr = self.get_zernike_phase_name(image_name, n, m) meas[object_name, ftr] = phase
def zernike(zernike_indexes, labels, indexes): """Compute the Zernike features for the labels with the label #s in indexes returns the score per labels and an array of one image per zernike feature """ # # "Reverse_indexes" is -1 if a label # is not to be processed. Otherwise # reverse_index[label] gives you the index into indexes of the label # and other similarly shaped vectors (like the results) # indexes = np.array(indexes, dtype=np.int32) nindexes = len(indexes) reverse_indexes = np.empty((np.max(indexes) + 1, ), int) reverse_indexes.fill(-1) reverse_indexes[indexes] = np.arange(indexes.shape[0], dtype=int) mask = reverse_indexes[labels] != -1 centers, radii = minimum_enclosing_circle(labels, indexes) ny, nx = labels.shape[0:2] y, x = np.asarray(np.mgrid[0:ny - 1:complex(0, ny), 0:nx - 1:complex(0, nx)], dtype=float) xm = x[mask] ym = y[mask] lm = labels[mask] # # The Zernikes are inscribed in circles with points labeled by # their fractional distance (-1 <= x,y <= 1) from the center. # So we transform x and y by subtracting the center and # dividing by the radius # rev_ind = reverse_indexes[lm] ## ym = (ym-centers[reverse_indexes[lm],0]) / radii[reverse_indexes[lm]] ym -= centers[rev_ind, 0] ym /= radii[rev_ind] ## xm = (xm-centers[reverse_indexes[lm],1]) / radii[reverse_indexes[lm]] xm -= centers[rev_ind, 1] xm /= radii[rev_ind] # # Blow up ym and xm into new x and y vectors # x = np.zeros_like(x) x[mask] = xm y = np.zeros_like(y) y[mask] = ym # # Pass the resulting x and y through the rest of Zernikeland # score = np.zeros((nindexes, len(zernike_indexes))) zf = construct_zernike_polynomials(x, y, zernike_indexes, mask) score = score_zernike(zf, radii, labels, indexes) return score
def zernike(zernike_indexes, labels, indexes): """Compute the Zernike features for the labels with the label #s in indexes returns the score per labels and an array of one image per zernike feature """ # # "Reverse_indexes" is -1 if a label # is not to be processed. Otherwise # reverse_index[label] gives you the index into indexes of the label # and other similarly shaped vectors (like the results) # indexes = np.array(indexes, dtype=np.int32) nindexes = len(indexes) reverse_indexes = -np.ones((np.max(indexes) + 1, ), int) reverse_indexes[indexes] = np.arange(indexes.shape[0], dtype=int) mask = reverse_indexes[labels] != -1 centers, radii = minimum_enclosing_circle(labels, indexes) y, x = np.mgrid[0:labels.shape[0], 0:labels.shape[1]] xm = x[mask].astype(float) ym = y[mask].astype(float) lm = labels[mask] # # The Zernikes are inscribed in circles with points labeled by # their fractional distance (-1 <= x,y <= 1) from the center. # So we transform x and y by subtracting the center and # dividing by the radius # ym = (ym - centers[reverse_indexes[lm], 0]) / radii[reverse_indexes[lm]] xm = (xm - centers[reverse_indexes[lm], 1]) / radii[reverse_indexes[lm]] # # Blow up ym and xm into new x and y vectors # x = np.zeros(x.shape) x[mask] = xm y = np.zeros(y.shape) y[mask] = ym # # Pass the resulting x and y through the rest of Zernikeland # score = np.zeros((nindexes, len(zernike_indexes))) for i in range(len(zernike_indexes)): zf = construct_zernike_polynomials(x, y, zernike_indexes[i:i + 1], mask) one_score = score_zernike(zf, radii, labels, indexes) score[:, i] = one_score[:, 0] return score
def zernike(zernike_indexes, labels, indexes): """Compute the Zernike features for the labels with the label #s in indexes returns the score per labels and an array of one image per zernike feature """ # # "Reverse_indexes" is -1 if a label # is not to be processed. Otherwise # reverse_index[label] gives you the index into indexes of the label # and other similarly shaped vectors (like the results) # indexes = np.array(indexes, dtype=np.int32) nindexes = len(indexes) reverse_indexes = -np.ones((np.max(indexes) + 1,), int) reverse_indexes[indexes] = np.arange(indexes.shape[0], dtype=int) mask = reverse_indexes[labels] != -1 centers, radii = minimum_enclosing_circle(labels, indexes) y, x = np.mgrid[0 : labels.shape[0], 0 : labels.shape[1]] xm = x[mask].astype(float) ym = y[mask].astype(float) lm = labels[mask] # # The Zernikes are inscribed in circles with points labeled by # their fractional distance (-1 <= x,y <= 1) from the center. # So we transform x and y by subtracting the center and # dividing by the radius # ym = (ym - centers[reverse_indexes[lm], 0]) / radii[reverse_indexes[lm]] xm = (xm - centers[reverse_indexes[lm], 1]) / radii[reverse_indexes[lm]] # # Blow up ym and xm into new x and y vectors # x = np.zeros(x.shape) x[mask] = xm y = np.zeros(y.shape) y[mask] = ym # # Pass the resulting x and y through the rest of Zernikeland # score = np.zeros((nindexes, len(zernike_indexes))) for i in range(len(zernike_indexes)): zf = construct_zernike_polynomials(x, y, zernike_indexes[i : i + 1], mask) one_score = score_zernike(zf, radii, labels, indexes) score[:, i] = one_score[:, 0] return score
def run(self, workspace): measurements = workspace.measurements statistics = [["Entropy"]] workspace.display_data.statistics = statistics input_image_name = self.input_image_name.value input_object_name = self.input_object_name.value metric = self.intensity_measurement.value bins = self.bin_number.value image_set = workspace.image_set input_image = image_set.get_image(input_image_name, must_be_grayscale=True) pixels = input_image.pixel_data object_set = workspace.object_set objects = object_set.get_objects(input_object_name) labels = objects.segmented indexes = objects.indices #Calculate the center of the objects- I'm guessing there's a better way to do this but this was already here centers, radius = minimum_enclosing_circle(labels, indexes) feature = self.get_measurement_name(input_image_name, metric, bins) #Do the actual calculation entropy, slicemeasurements = self.slice_and_measure_intensity( pixels, labels, indexes, centers, metric, bins) #Add the measurement back into the workspace measurements.add_measurement(input_object_name, feature, entropy) for eachbin in range(bins): feature_bin = self.get_measurement_name_bins( input_image_name, metric, bins, eachbin + 1) measurements.add_measurement(input_object_name, feature_bin, slicemeasurements[:, eachbin]) emean = numpy.mean(entropy) statistics.append([feature, emean])
def run(self, workspace): # # Get the measurements object - we put the measurements we # make in here # meas = workspace.measurements assert isinstance(meas, cpmeas.Measurements) # # We record some statistics which we will display later. # We format them so that Matplotlib can display them in a table. # The first row is a header that tells what the fields are. # statistics = [["Feature", "Mean", "Median", "SD"]] # # Put the statistics in the workspace display data so we # can get at them when we display # workspace.display_data.statistics = statistics # # Get the input image and object. You need to get the .value # because otherwise you'll get the setting object instead of # the string name. # input_image_name = self.input_image_name.value input_object_name = self.input_object_name.value ################################################################ # # GETTING AN IMAGE FROM THE IMAGE SET # # Get the image set. The image set has all of the images in it. # image_set = workspace.image_set # # Get the input image object. We want a grayscale image here. # The image set will convert a color image to a grayscale one # and warn the user. # input_image = image_set.get_image(input_image_name, must_be_grayscale=True) # # Get the pixels - these are a 2-d Numpy array. # pixels = input_image.pixel_data # ############################################################### # # GETTING THE LABELS MATRIX FROM THE OBJECT SET # # The object set has all of the objects in it. # object_set = workspace.object_set assert isinstance(object_set, cpo.ObjectSet) # # Get objects from the object set. The most useful array in # the objects is "objects.segmented" which is a labels matrix # in which each pixel has an integer value. # # The value, "0", is reserved for "background" - a pixel with # a zero value is not in an object. Each object has an object # number, starting at "1" and each pixel in the object is # labeled with that number. # # The other useful array is "objects.small_removed_segmented" which # is another labels matrix. There are objects that touch the edge of # the image and get filtered out and there are large objects that # get filtered out. Modules like "IdentifySecondaryObjects" may # want to associate pixels near the objects in the labels matrix to # those objects - the large and touching objects should compete with # the real ones, so you should use "objects.small_removed_segmented" # for those cases. # objects = object_set.get_objects(input_object_name) labels = objects.segmented # ########################################### # # The minimum enclosing circle (MEC) is the smallest circle that # will fit around the object. We get the centers and radii of # all of the objects at once. You'll see how that lets us # compute the X and Y position of each pixel in a label all at # one go. # # First, get an array that lists the whole range of indexes in # the labels matrix. # indexes = objects.get_indices() # # Then ask for the minimum_enclosing_circle for each object named # in those indexes. MEC returns the i and j coordinate of the center # and the radius of the circle and that defines the circle entirely. # centers, radius = minimum_enclosing_circle(labels, indexes) ############################################################### # # The module computes a measurement based on the image intensity # inside an object times a Zernike polynomial inscribed in the # minimum enclosing circle around the object. The details are # in the "measure_zernike" function. We call into the function with # an N and M which describe the polynomial. # for n, m in self.get_zernike_indexes(): # Compute the zernikes for each object, returned in an array zr, zi = self.measure_zernike(pixels, labels, indexes, centers, radius, n, m) # Get the name of the measurement feature for this zernike feature = self.get_measurement_name(n, m) # Add a measurement for this kind of object if m != 0: meas.add_measurement(input_object_name, feature, zr) # # Do the same with -m # feature = self.get_measurement_name(n, -m) meas.add_measurement(input_object_name, feature, zi) else: # For zero, the total is the sum of real and imaginary parts meas.add_measurement(input_object_name, feature, zr + zi) # # Record the statistics. # zmean = np.mean(zr) zmedian = np.median(zr) zsd = np.std(zr) statistics.append([feature, zmean, zmedian, zsd])
def run(self, workspace): # # Get the measurements object - we put the measurements we # make in here # meas = workspace.measurements assert isinstance(meas, cpmeas.Measurements) # # We record some statistics which we will display later. # We format them so that Matplotlib can display them in a table. # The first row is a header that tells what the fields are. # statistics = [ [ "Feature", "Mean", "Median", "SD"] ] # # Put the statistics in the workspace display data so we # can get at them when we display # workspace.display_data.statistics = statistics # # Get the input image and object. You need to get the .value # because otherwise you'll get the setting object instead of # the string name. # input_image_name = self.input_image_name.value input_object_name = self.input_object_name.value ################################################################ # # GETTING AN IMAGE FROM THE IMAGE SET # # Get the image set. The image set has all of the images in it. # image_set = workspace.image_set # # Get the input image object. We want a grayscale image here. # The image set will convert a color image to a grayscale one # and warn the user. # input_image = image_set.get_image(input_image_name, must_be_grayscale = True) # # Get the pixels - these are a 2-d Numpy array. # pixels = input_image.pixel_data # ############################################################### # # GETTING THE LABELS MATRIX FROM THE OBJECT SET # # The object set has all of the objects in it. # object_set = workspace.object_set assert isinstance(object_set, cpo.ObjectSet) # # Get objects from the object set. The most useful array in # the objects is "objects.segmented" which is a labels matrix # in which each pixel has an integer value. # # The value, "0", is reserved for "background" - a pixel with # a zero value is not in an object. Each object has an object # number, starting at "1" and each pixel in the object is # labeled with that number. # # The other useful array is "objects.small_removed_segmented" which # is another labels matrix. There are objects that touch the edge of # the image and get filtered out and there are large objects that # get filtered out. Modules like "IdentifySecondaryObjects" may # want to associate pixels near the objects in the labels matrix to # those objects - the large and touching objects should compete with # the real ones, so you should use "objects.small_removed_segmented" # for those cases. # objects = object_set.get_objects(input_object_name) labels = objects.segmented # ########################################### # # The minimum enclosing circle (MEC) is the smallest circle that # will fit around the object. We get the centers and radii of # all of the objects at once. You'll see how that lets us # compute the X and Y position of each pixel in a label all at # one go. # # First, get an array that lists the whole range of indexes in # the labels matrix. # indexes = objects.get_indices() # # Then ask for the minimum_enclosing_circle for each object named # in those indexes. MEC returns the i and j coordinate of the center # and the radius of the circle and that defines the circle entirely. # centers, radius = minimum_enclosing_circle(labels, indexes) ############################################################### # # The module computes a measurement based on the image intensity # inside an object times a Zernike polynomial inscribed in the # minimum enclosing circle around the object. The details are # in the "measure_zernike" function. We call into the function with # an N and M which describe the polynomial. # for n, m in self.get_zernike_indexes(): # Compute the zernikes for each object, returned in an array zr, zi = self.measure_zernike( pixels, labels, indexes, centers, radius, n, m) # Get the name of the measurement feature for this zernike feature = self.get_measurement_name(n, m) # Add a measurement for this kind of object if m != 0: meas.add_measurement(input_object_name, feature, zr) # # Do the same with -m # feature = self.get_measurement_name(n, -m) meas.add_measurement(input_object_name, feature, zi) else: # For zero, the total is the sum of real and imaginary parts meas.add_measurement(input_object_name, feature, zr + zi) # # Record the statistics. # zmean = np.mean(zr) zmedian = np.median(zr) zsd = np.std(zr) statistics.append( [ feature, zmean, zmedian, zsd ] )