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
Ejemplo n.º 2
0
 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 get_image_from_features(radius, feature_dictionary):
        '''Reconstruct the intensity image from the zernike features

        radius - the radius of the minimum enclosing circle

        feature_dictionary - keys are (n, m) tuples and values are the
        magnitudes.

        returns a greyscale image based on the feature dictionary.
        '''
        i, j = np.mgrid[-radius:(radius + 1),
                        -radius:(radius + 1)].astype(float) / radius
        mask = (i * i + j * j) <= 1

        zernike_indexes = np.array(feature_dictionary.keys())
        zernike_features = np.array(feature_dictionary.values())

        z = construct_zernike_polynomials(j,
                                          i,
                                          np.abs(zernike_indexes),
                                          mask=mask)
        zn = (2 * zernike_indexes[:, 0] + 2) / (
            (zernike_indexes[:, 1] == 0) + 1) / np.pi
        z = z * zn[np.newaxis, np.newaxis, :]
        z = z.real * (zernike_indexes[:, 1] >= 0)[np.newaxis, np.newaxis, :] + \
            z.imag * (zernike_indexes[:, 1] <= 0)[np.newaxis, np.newaxis, :]
        return np.sum(z * zernike_features[np.newaxis, np.newaxis, :], 2)
Ejemplo n.º 4
0
 def test_00_00_zeros(self):
     """Test construct_zernike_polynomials on an empty image"""
     zi = self.make_zernike_indexes()
     zf = z.construct_zernike_polynomials(np.zeros((100, 100)),
                                          np.zeros((100, 100)), zi)
     # All zernikes with m!=0 should be zero
     m_ne_0 = np.array([i for i in range(zi.shape[0]) if zi[i, 1]])
     m_eq_0 = np.array([i for i in range(zi.shape[0]) if zi[i, 1] == 0])
     self.assertTrue(np.all(zf[:, :, m_ne_0] == 0))
     self.assertTrue(np.all(zf[:, :, m_eq_0] != 0))
     scores = z.score_zernike(zf, np.array([]), np.zeros((100, 100), int))
     self.assertEqual(np.product(scores.shape), 0)
Ejemplo n.º 5
0
 def test_00_00_zeros(self):
     """Test construct_zernike_polynomials on an empty image"""
     zi = self.make_zernike_indexes()
     zf = z.construct_zernike_polynomials(np.zeros((100,100)),
                                          np.zeros((100,100)),
                                          zi)
     # All zernikes with m!=0 should be zero
     m_ne_0 = np.array([i for i in range(zi.shape[0]) if zi[i,1]])
     m_eq_0 = np.array([i for i in range(zi.shape[0]) if zi[i,1]==0])
     self.assertTrue(np.all(zf[:,:,m_ne_0]==0))
     self.assertTrue(np.all(zf[:,:,m_eq_0]!=0))
     scores = z.score_zernike(zf, np.array([]), np.zeros((100,100),int))
     self.assertEqual(np.product(scores.shape), 0)
Ejemplo n.º 6
0
 def test_01_01_one_object(self):
     """Test Zernike on one single circle"""
     zi = self.make_zernike_indexes()
     y,x = np.mgrid[-50:51,-50:51].astype(float)/50
     labels = x**2+y**2 <=1
     x[labels==0]=0
     y[labels==0]=0
     zf = z.construct_zernike_polynomials(x, y, zi)
     scores = z.score_zernike(zf,[50], labels)
     # Zernike 0,0 should be 1 and others should be zero within
     # an approximation of 1/radius
     epsilon = 1.0/50.0
     self.assertTrue(abs(scores[0,0]-1) < epsilon )
     self.assertTrue(np.all(scores[0,1:] < epsilon))
Ejemplo n.º 7
0
 def test_01_01_one_object(self):
     """Test Zernike on one single circle"""
     zi = self.make_zernike_indexes()
     y, x = np.mgrid[-50:51, -50:51].astype(float) / 50
     labels = x**2 + y**2 <= 1
     x[labels == 0] = 0
     y[labels == 0] = 0
     zf = z.construct_zernike_polynomials(x, y, zi)
     scores = z.score_zernike(zf, [50], labels)
     # Zernike 0,0 should be 1 and others should be zero within
     # an approximation of 1/radius
     epsilon = 1.0 / 50.0
     self.assertTrue(abs(scores[0, 0] - 1) < epsilon)
     self.assertTrue(np.all(scores[0, 1:] < epsilon))
Ejemplo n.º 8
0
    def score_rotations(self, labels, n):
        """Score the result of n rotations of the label matrix then test for equality"""
        self.assertEqual(labels.shape[0], labels.shape[1],
                         "Must use square matrix for test")
        self.assertEqual(labels.shape[0] & 1, 1, "Must be odd width/height")

        zi = self.make_zernike_indexes()
        test_labels = np.zeros((labels.shape[0] * n, labels.shape[0]))
        test_x = np.zeros((labels.shape[0] * n, labels.shape[0]))
        test_y = np.zeros((labels.shape[0] * n, labels.shape[0]))
        diameter = labels.shape[0]
        radius = labels.shape[0] // 2
        y, x = (
            np.mgrid[-radius:radius + 1, -radius:radius + 1].astype(float) /
            radius)
        anti_mask = x**2 + y**2 > 1
        x[anti_mask] = 0
        y[anti_mask] = 0
        min_pixels = 100000
        max_pixels = 0
        for i in range(0, n):
            angle = 360 * i // n  # believe it or not, in degrees!
            off_x = labels.shape[0] * i
            off_y = 0
            rotated_labels = scind.rotate(labels,
                                          angle,
                                          order=0,
                                          reshape=False)
            pixels = np.sum(rotated_labels)
            min_pixels = min(min_pixels, pixels)
            max_pixels = max(max_pixels, pixels)
            x_mask = x.copy()
            y_mask = y.copy()
            x_mask[rotated_labels == 0] = 0
            y_mask[rotated_labels == 0] = 0
            test_labels[off_x:off_x + diameter,
                        off_y:off_y + diameter] = rotated_labels * (i + 1)
            test_x[off_x:off_x + diameter, off_y:off_y + diameter] = x_mask
            test_y[off_x:off_x + diameter, off_y:off_y + diameter] = y_mask
        zf = z.construct_zernike_polynomials(test_x, test_y, zi)
        scores = z.score_zernike(zf, np.ones((n, )) * radius, test_labels)
        score_0 = scores[0]
        epsilon = 2.0 * (max(1, max_pixels - min_pixels)) / max_pixels
        for score in scores[1:, :]:
            self.assertTrue(np.all(np.abs(score - score_0) < epsilon))
Ejemplo n.º 9
0
    def score_rotations(self,labels,n):
        """Score the result of n rotations of the label matrix then test for equality"""
        self.assertEqual(labels.shape[0],labels.shape[1],"Must use square matrix for test")
        self.assertEqual(labels.shape[0] & 1,1,"Must be odd width/height")

        zi = self.make_zernike_indexes()
        test_labels = np.zeros((labels.shape[0]*n,labels.shape[0]))
        test_x      = np.zeros((labels.shape[0]*n,labels.shape[0]))
        test_y      = np.zeros((labels.shape[0]*n,labels.shape[0]))
        diameter = labels.shape[0]
        radius = labels.shape[0]/2
        y,x=np.mgrid[-radius:radius+1,-radius:radius+1].astype(float)/radius
        anti_mask = x**2+y**2 > 1
        x[anti_mask] = 0
        y[anti_mask] = 0 
        min_pixels = 100000
        max_pixels = 0
        for i in range(0,n):
            angle = 360*i / n # believe it or not, in degrees!
            off_x = labels.shape[0]*i
            off_y = 0
            rotated_labels = scind.rotate(labels,angle,order=0,reshape=False)
            pixels = np.sum(rotated_labels)
            min_pixels = min(min_pixels,pixels)
            max_pixels = max(max_pixels,pixels)
            x_mask = x.copy()
            y_mask = y.copy()
            x_mask[rotated_labels==0]=0
            y_mask[rotated_labels==0]=0
            test_labels[off_x:off_x+diameter,
                        off_y:off_y+diameter] = rotated_labels * (i+1)
            test_x[off_x:off_x+diameter,
                        off_y:off_y+diameter] = x_mask 
            test_y[off_x:off_x+diameter,
                        off_y:off_y+diameter] = y_mask 
        zf = z.construct_zernike_polynomials(test_x,test_y,zi)
        scores = z.score_zernike(zf,np.ones((n,))*radius,test_labels)
        score_0=scores[0]
        epsilon = 2.0*(max(1,max_pixels-min_pixels))/max_pixels
        for score in scores[1:,:]:
            self.assertTrue(np.all(np.abs(score-score_0)<epsilon))
    def get_image_from_features(radius, feature_dictionary):
        '''Reconstruct the intensity image from the zernike features

        radius - the radius of the minimum enclosing circle

        feature_dictionary - keys are (n, m) tuples and values are the
        magnitudes.

        returns a greyscale image based on the feature dictionary.
        '''
        i, j = np.mgrid[-radius:(radius+1), -radius:(radius+1)].astype(float) / radius
        mask = (i*i + j*j) <= 1

        zernike_indexes = np.array(feature_dictionary.keys())
        zernike_features = np.array(feature_dictionary.values())

        z = construct_zernike_polynomials(
            j, i, np.abs(zernike_indexes), mask=mask)
        zn = (2*zernike_indexes[:, 0] + 2) / ((zernike_indexes[:, 1] == 0) + 1) / np.pi
        z = z * zn[np.newaxis, np.newaxis, :]
        z = z.real * (zernike_indexes[:, 1] >= 0)[np.newaxis, np.newaxis, :] +\
            z.imag * (zernike_indexes[:, 1] <= 0)[np.newaxis, np.newaxis, :]
        return np.sum(z * zernike_features[np.newaxis, np.newaxis, :], 2)
Ejemplo n.º 11
0
    def score_scales(self,labels,n):
        """Score the result of n 3x scalings of the label matrix then test for equality"""
        self.assertEqual(labels.shape[0],labels.shape[1],"Must use square matrix for test")
        self.assertEqual(labels.shape[0] & 1,1,"Must be odd width/height")

        width = labels.shape[0] * 3**n
        height = width * (n+1)
        zi = self.make_zernike_indexes()
        test_labels = np.zeros((height,width))
        test_x      = np.zeros((height,width))
        test_y      = np.zeros((height,width))
        radii = []
        for i in range(n+1):
            scaled_labels = scind.zoom(labels,3**i,order=0)
            diameter = scaled_labels.shape[0]
            radius = scaled_labels.shape[0]/2
            radii.append(radius)
            y,x=np.mgrid[-radius:radius+1,-radius:radius+1].astype(float)/radius
            anti_mask = x**2+y**2 > 1
            x[anti_mask] = 0
            y[anti_mask] = 0 
            off_x = width*i
            off_y = 0
            x[scaled_labels==0]=0
            y[scaled_labels==0]=0
            test_labels[off_x:off_x+diameter,
                        off_y:off_y+diameter] = scaled_labels * (i+1)
            test_x[off_x:off_x+diameter,
                        off_y:off_y+diameter] = x 
            test_y[off_x:off_x+diameter,
                        off_y:off_y+diameter] = y 
        zf = z.construct_zernike_polynomials(test_x,test_y,zi)
        scores = z.score_zernike(zf,np.array(radii),test_labels)
        score_0=scores[0]
        epsilon = .02
        for score in scores[1:,:]:
            self.assertTrue(np.all(np.abs(score-score_0)<epsilon))
Ejemplo n.º 12
0
    def score_scales(self, labels, n):
        """Score the result of n 3x scalings of the label matrix then test for equality"""
        self.assertEqual(labels.shape[0], labels.shape[1],
                         "Must use square matrix for test")
        self.assertEqual(labels.shape[0] & 1, 1, "Must be odd width/height")

        width = labels.shape[0] * 3**n
        height = width * (n + 1)
        zi = self.make_zernike_indexes()
        test_labels = np.zeros((height, width))
        test_x = np.zeros((height, width))
        test_y = np.zeros((height, width))
        radii = []
        for i in range(n + 1):
            scaled_labels = scind.zoom(labels, 3**i, order=0)
            diameter = scaled_labels.shape[0]
            radius = scaled_labels.shape[0] // 2
            radii.append(radius)
            y, x = np.mgrid[-radius:radius + 1,
                            -radius:radius + 1].astype(float) / radius
            anti_mask = x**2 + y**2 > 1
            x[anti_mask] = 0
            y[anti_mask] = 0
            off_x = width * i
            off_y = 0
            x[scaled_labels == 0] = 0
            y[scaled_labels == 0] = 0
            test_labels[off_x:off_x + diameter,
                        off_y:off_y + diameter] = scaled_labels * (i + 1)
            test_x[off_x:off_x + diameter, off_y:off_y + diameter] = x
            test_y[off_x:off_x + diameter, off_y:off_y + diameter] = y
        zf = z.construct_zernike_polynomials(test_x, test_y, zi)
        scores = z.score_zernike(zf, np.array(radii), test_labels)
        score_0 = scores[0]
        epsilon = .02
        for score in scores[1:, :]:
            self.assertTrue(np.all(np.abs(score - score_0) < epsilon))
    def measure_zernike(self, pixels, labels, indexes, centers, radius, n, m):
        # I'll put some documentation in here to explain what it does.
        # If someone ever wants to call it, their editor might display
        # the documentation.
        '''Measure the intensity of the image with Zernike (N, M)

        pixels - the intensity image to be measured
        labels - the labels matrix that labels each object with an integer
        indexes - the label #s in the image
        centers - the centers of the minimum enclosing circle for each object
        radius - the radius of the minimum enclosing circle for each object
        n, m - the Zernike coefficients.

        See http://en.wikipedia.org/wiki/Zernike_polynomials for an
        explanation of the Zernike polynomials
        '''
        #
        # The strategy here is to operate on the whole array instead
        # of operating on one object at a time. The most important thing
        # is to avoid having to run the Python interpreter once per pixel
        # in the image and the second most important is to avoid running
        # it per object in case there are hundreds of objects.
        #
        # We play lots of indexing tricks here to operate on the whole image.
        # I'll try to explain some - hopefully, you can reuse.
        center_x = centers[:, 1]
        center_y = centers[:, 0]
        #
        # Make up fake values for 0 (the background). This lets us do our
        # indexing tricks. Really, we're going to ignore the background,
        # but we want to do the indexing without ignoring the background
        # because that's easier.
        #
        center_x = np.hstack([[0], center_x])
        center_y = np.hstack([[0], center_y])
        radius = np.hstack([[1], radius])
        #
        # Now get one array that's the y coordinate of each pixel and one
        # that's the x coordinate. This might look stupid and wasteful,
        # but these "arrays" are never actually realized and made into
        # real memory.
        #
        y, x = np.mgrid[0:labels.shape[0], 0:labels.shape[1]]
        #
        # Get the x and y coordinates relative to the object centers.
        # This uses Numpy broadcasting. For each pixel, we use the
        # value in the labels matrix as an index into the appropriate
        # one-dimensional array. So we get the value for that object.
        #
        y -= center_y[labels]
        x -= center_x[labels]
        #
        # Zernikes take x and y values from zero to one. We scale the
        # integer coordinate values by dividing them by the radius of
        # the circle. Again, we use the indexing trick to look up the
        # values for each object.
        #
        y = y.astype(float) / radius[labels]
        x = x.astype(float) / radius[labels]
        #
        #################################
        #
        # ZERNIKE POLYNOMIALS
        #
        # Now we can get Zernike polynomials per-pixel where each pixel
        # value is calculated according to its object's MEC.
        #
        # We use a mask of all of the non-zero labels so the calculation
        # runs a little faster.
        #
        zernike_polynomial = construct_zernike_polynomials(
            x, y, np.array([[n, m]]), labels > 0)
        #
        # For historical reasons, CellProfiler didn't multiply by the per/zernike
        # normalizing factor: 2*n + 2 / E / pi where E is 2 if m is zero and 1
        # if m is one. We do it here to aid with the reconstruction
        #
        zernike_polynomial *= (2 * n + 2) / (2 if m == 0 else 1) / np.pi
        #
        # Multiply the Zernike polynomial by the image to dissect
        # the image by the Zernike basis set.
        #
        output_pixels = pixels * zernike_polynomial[:, :, 0]
        #
        # Finally, we use Scipy to sum the intensities. Scipy has different
        # versions with different quirks. The "fix" function takes all
        # of that into account.
        #
        # The sum function calculates the sum of the pixel values for
        # each pixel in an object, using the labels matrix to name
        # the pixels in an object
        #
        zr = fix(scind.sum(output_pixels.real, labels, indexes))
        zi = fix(scind.sum(output_pixels.imag, labels, indexes))
        #
        # And we're done! Did you like it? Did you get it?
        #
        return zr, zi
    def measure_zernike(self, pixels, labels, indexes, centers, radius, n, m):
        # I'll put some documentation in here to explain what it does.
        # If someone ever wants to call it, their editor might display
        # the documentation.
        '''Measure the intensity of the image with Zernike (N, M)

        pixels - the intensity image to be measured
        labels - the labels matrix that labels each object with an integer
        indexes - the label #s in the image
        centers - the centers of the minimum enclosing circle for each object
        radius - the radius of the minimum enclosing circle for each object
        n, m - the Zernike coefficients.

        See http://en.wikipedia.org/wiki/Zernike_polynomials for an
        explanation of the Zernike polynomials
        '''
        #
        # The strategy here is to operate on the whole array instead
        # of operating on one object at a time. The most important thing
        # is to avoid having to run the Python interpreter once per pixel
        # in the image and the second most important is to avoid running
        # it per object in case there are hundreds of objects.
        #
        # We play lots of indexing tricks here to operate on the whole image.
        # I'll try to explain some - hopefully, you can reuse.
        center_x = centers[:, 1]
        center_y = centers[:, 0]
        #
        # Make up fake values for 0 (the background). This lets us do our
        # indexing tricks. Really, we're going to ignore the background,
        # but we want to do the indexing without ignoring the background
        # because that's easier.
        #
        center_x = np.hstack([[0], center_x])
        center_y = np.hstack([[0], center_y])
        radius = np.hstack([[1], radius])
        #
        # Now get one array that's the y coordinate of each pixel and one
        # that's the x coordinate. This might look stupid and wasteful,
        # but these "arrays" are never actually realized and made into
        # real memory.
        #
        y, x = np.mgrid[0:labels.shape[0], 0:labels.shape[1]]
        #
        # Get the x and y coordinates relative to the object centers.
        # This uses Numpy broadcasting. For each pixel, we use the
        # value in the labels matrix as an index into the appropriate
        # one-dimensional array. So we get the value for that object.
        #
        y -= center_y[labels]
        x -= center_x[labels]
        #
        # Zernikes take x and y values from zero to one. We scale the
        # integer coordinate values by dividing them by the radius of
        # the circle. Again, we use the indexing trick to look up the
        # values for each object.
        #
        y = y.astype(float) / radius[labels]
        x = x.astype(float) / radius[labels]
        #
        #################################
        #
        # ZERNIKE POLYNOMIALS
        #
        # Now we can get Zernike polynomials per-pixel where each pixel
        # value is calculated according to its object's MEC.
        #
        # We use a mask of all of the non-zero labels so the calculation
        # runs a little faster.
        #
        zernike_polynomial = construct_zernike_polynomials(
            x, y, np.array([ [ n, m ]]), labels > 0)
        #
        # For historical reasons, CellProfiler didn't multiply by the per/zernike
        # normalizing factor: 2*n + 2 / E / pi where E is 2 if m is zero and 1
        # if m is one. We do it here to aid with the reconstruction
        #
        zernike_polynomial *= (2*n + 2) / (2 if m == 0 else 1) / np.pi
        #
        # Multiply the Zernike polynomial by the image to dissect
        # the image by the Zernike basis set.
        #
        output_pixels = pixels * zernike_polynomial[:,:,0]
        #
        # Finally, we use Scipy to sum the intensities. Scipy has different
        # versions with different quirks. The "fix" function takes all
        # of that into account.
        #
        # The sum function calculates the sum of the pixel values for
        # each pixel in an object, using the labels matrix to name
        # the pixels in an object
        #
        zr = fix(scind.sum(output_pixels.real, labels, indexes))
        zi = fix(scind.sum(output_pixels.imag, labels, indexes))
        #
        # And we're done! Did you like it? Did you get it?
        #
        return zr, zi