예제 #1
0
 def test_02_01_median(self):
     '''A median filter larger than the image = median of image'''
     np.random.seed(0)
     img = np.random.uniform(size=(9, 9))
     result = F.median_filter(img, np.ones((9, 9), bool), 20)
     self.assertEqual(result[0, 0], np.median(img))
     self.assertTrue(np.all(result == np.median(img)))
예제 #2
0
    def run(self, workspace):
        image = workspace.image_set.get_image(self.image_name.value, must_be_grayscale=True)
        pixel_data = image.pixel_data
        if self.wants_automatic_object_size.value:
            object_size = min(30, max(1, np.mean(pixel_data.shape) / 40))
        else:
            object_size = float(self.object_size.value)
        sigma = object_size / 2.35
        if self.smoothing_method.value == GAUSSIAN_FILTER:

            def fn(image):
                return scind.gaussian_filter(image, sigma, mode="constant", cval=0)

            output_pixels = smooth_with_function_and_mask(pixel_data, fn, image.mask)
        elif self.smoothing_method.value == MEDIAN_FILTER:
            output_pixels = median_filter(pixel_data, image.mask, object_size / 2 + 1)
        elif self.smoothing_method.value == SMOOTH_KEEPING_EDGES:
            sigma_range = float(self.sigma_range.value)
            output_pixels = bilateral_filter(pixel_data, image.mask, sigma, sigma_range)
        elif self.smoothing_method.value == FIT_POLYNOMIAL:
            output_pixels = fit_polynomial(pixel_data, image.mask, self.clip.value)
        elif self.smoothing_method.value == CIRCULAR_AVERAGE_FILTER:
            output_pixels = circular_average_filter(pixel_data, object_size / 2 + 1, image.mask)
        elif self.smoothing_method.value == SM_TO_AVERAGE:
            if image.has_mask:
                mean = np.mean(pixel_data[image.mask])
            else:
                mean = np.mean(pixel_data)
            output_pixels = np.ones(pixel_data.shape, pixel_data.dtype) * mean
        else:
            raise ValueError("Unsupported smoothing method: %s" % self.smoothing_method.value)
        output_image = cpi.Image(output_pixels, parent_image=image)
        workspace.image_set.add(self.filtered_image_name.value, output_image)
        workspace.display_data.pixel_data = pixel_data
        workspace.display_data.output_pixels = output_pixels
예제 #3
0
    def test_00_01_all_masked(self):
        '''Test a completely masked image

        Regression test of IMG-1029'''
        result = F.median_filter(np.zeros((10, 10)), np.zeros((10, 10), bool),
                                 3)
        self.assertTrue(np.all(result == 0))
예제 #4
0
    def test_03_01_shape(self):
        '''Make sure the median filter is the expected octagonal shape'''

        radius = 5
        a_2 = int(radius / 2.414213)
        i, j = np.mgrid[-10:11, -10:11]
        octagon = np.ones((21, 21), bool)
        #
        # constrain the octagon mask to be the points that are on
        # the correct side of the 8 edges
        #
        octagon[i < -radius] = False
        octagon[i > radius] = False
        octagon[j < -radius] = False
        octagon[j > radius] = False
        octagon[i + j < -radius - a_2] = False
        octagon[j - i > radius + a_2] = False
        octagon[i + j > radius + a_2] = False
        octagon[i - j > radius + a_2] = False
        np.random.seed(0)
        img = np.random.uniform(size=(21, 21))
        result = F.median_filter(img, np.ones((21, 21), bool), radius)
        sorted = img[octagon]
        sorted.sort()
        min_acceptable = sorted[len(sorted) // 2 - 1]
        max_acceptable = sorted[len(sorted) // 2 + 1]
        self.assertTrue(result[10, 10] >= min_acceptable)
        self.assertTrue(result[10, 10] <= max_acceptable)
예제 #5
0
 def test_01_01_mask(self):
     '''The median filter, masking a single value'''
     img = np.zeros((10, 10))
     img[5, 5] = 1
     mask = np.ones((10, 10), bool)
     mask[5, 5] = False
     result = F.median_filter(img, mask, 3)
     self.assertTrue(np.all(result[mask] == 0))
예제 #6
0
 def test_02_02_median_bigger(self):
     '''Use an image of more than 255 values to test approximation'''
     np.random.seed(0)
     img = np.random.uniform(size=(20, 20))
     result = F.median_filter(img, np.ones((20, 20), bool), 40)
     sorted = np.ravel(img)
     sorted.sort()
     min_acceptable = sorted[198]
     max_acceptable = sorted[202]
     self.assertTrue(np.all(result >= min_acceptable))
     self.assertTrue(np.all(result <= max_acceptable))
예제 #7
0
 def test_04_01_half_masked(self):
     '''Make sure that the median filter can handle large masked areas.'''
     img = np.ones((20, 20))
     mask = np.ones((20, 20), bool)
     mask[10:, :] = False
     img[~mask] = 2
     img[1, 1] = 0  # to prevent short circuit for uniform data.
     result = F.median_filter(img, mask, 5)
     # in partial coverage areas, the result should be only from the masked pixels
     self.assertTrue(np.all(result[:14, :] == 1))
     # in zero coverage areas, the result should be the lowest valud in the valid area
     self.assertTrue(np.all(result[15:, :] == np.min(img[mask])))
예제 #8
0
    def run(self, workspace):
        image = workspace.image_set.get_image(self.image_name.value,
                                              must_be_grayscale=True)
        pixel_data = image.pixel_data
        if self.wants_automatic_object_size.value:
            object_size = min(30, max(1, np.mean(pixel_data.shape) / 40))
        else:
            object_size = float(self.object_size.value)
        sigma = object_size / 2.35
        if self.smoothing_method.value == GAUSSIAN_FILTER:

            def fn(image):
                return scind.gaussian_filter(image,
                                             sigma,
                                             mode="constant",
                                             cval=0)

            output_pixels = smooth_with_function_and_mask(
                pixel_data, fn, image.mask)
        elif self.smoothing_method.value == MEDIAN_FILTER:
            output_pixels = median_filter(pixel_data, image.mask,
                                          object_size / 2 + 1)
        elif self.smoothing_method.value == SMOOTH_KEEPING_EDGES:
            sigma_range = np.float(self.sigma_range.value)

            output_pixels = skimage.restoration.denoise_bilateral(
                image=pixel_data.astype(np.float),
                multichannel=image.multichannel,
                sigma_color=sigma_range,
                sigma_spatial=sigma,
            )
        elif self.smoothing_method.value == FIT_POLYNOMIAL:
            output_pixels = fit_polynomial(pixel_data, image.mask,
                                           self.clip.value)
        elif self.smoothing_method.value == CIRCULAR_AVERAGE_FILTER:
            output_pixels = circular_average_filter(pixel_data,
                                                    object_size / 2 + 1,
                                                    image.mask)
        elif self.smoothing_method.value == SM_TO_AVERAGE:
            if image.has_mask:
                mean = np.mean(pixel_data[image.mask])
            else:
                mean = np.mean(pixel_data)
            output_pixels = np.ones(pixel_data.shape, pixel_data.dtype) * mean
        else:
            raise ValueError("Unsupported smoothing method: %s" %
                             self.smoothing_method.value)
        output_image = cellprofiler_core.image.Image(output_pixels,
                                                     parent_image=image)
        workspace.image_set.add(self.filtered_image_name.value, output_image)
        workspace.display_data.pixel_data = pixel_data
        workspace.display_data.output_pixels = output_pixels
예제 #9
0
    def run_per_layer(self, image, channel):
        if channel >= 0:
            pixel_data = image.pixel_data[:,:,channel].squeeze()
        else:
            pixel_data = image.pixel_data
        mask = image.mask
        if self.wants_automatic_object_size.value:
            object_size = min(30, max(1, np.mean(pixel_data.shape) / 40))
        else:
            object_size = float(self.object_size.value)
        sigma = object_size / 2.35

        if self.smoothing_method.value == GAUSSIAN_FILTER:
            def fn(image):
                return scind.gaussian_filter(image, sigma,
                                             mode='constant', cval=0)

            output_pixels = smooth_with_function_and_mask(pixel_data, fn,
                                                          mask)
        elif self.smoothing_method.value == MEDIAN_FILTER:
            output_pixels = median_filter(pixel_data, mask,
                                          object_size / 2 + 1)
        elif self.smoothing_method.value == SMOOTH_KEEPING_EDGES:
            sigma_range = float(self.sigma_range.value)
            output_pixels = bilateral_filter(pixel_data, mask,
                                             sigma, sigma_range)
        elif self.smoothing_method.value == FIT_POLYNOMIAL:
            output_pixels = fit_polynomial(pixel_data, mask,
                                           self.clip.value)
        elif self.smoothing_method.value == CIRCULAR_AVERAGE_FILTER:
            output_pixels = circular_average_filter(pixel_data,
                                                    object_size / 2 + 1, mask)
        elif self.smoothing_method.value == SM_TO_AVERAGE:
            if image.has_mask:
                mean = np.mean(pixel_data[mask])
            else:
                mean = np.mean(pixel_data)
                output_pixels = np.ones(pixel_data.shape, pixel_data.dtype) * mean

        elif self.smoothing_method.value == REMOVE_OUTLIER:
            # TODO: implement how this deals with masks.
            nbhood = self.outlierneighbourhood.value
            output_pixels = self.remove_outlier_pixels(pixel_data,
                                                         threshold=self.treshold.value,
                                                         radius=nbhood,
                                                         mode='max')
        else:
            raise ValueError("Unsupported smoothing method: %s" %
                             self.smoothing_method.value)

        return output_pixels
예제 #10
0
def test_04_01_median():
    """test the smooth module with median filtering"""
    object_size = 100.0 / 40.0
    np.random.seed(0)
    image = np.random.uniform(size=(100, 100)).astype(np.float32)
    mask = np.ones(image.shape, bool)
    mask[40:60, 45:65] = False
    expected = median_filter(image, mask, object_size / 2 + 1)
    workspace, module = make_workspace(image, mask)
    module.smoothing_method.value = S.MEDIAN_FILTER
    module.run(workspace)
    result = workspace.image_set.get_image(OUTPUT_IMAGE_NAME)
    assert result is not None
    np.testing.assert_almost_equal(result.pixel_data, expected)
예제 #11
0
 def test_04_01_median(self):
     '''test the smooth module with median filtering'''
     object_size = 100.0/ 40.0
     np.random.seed(0)
     image = np.random.uniform(size=(100,100)).astype(np.float32)
     mask = np.ones(image.shape,bool)
     mask[40:60,45:65] = False
     expected = median_filter(image, mask, object_size / 2 + 1)
     workspace, module = self.make_workspace(image, mask)
     module.smoothing_method.value = S.MEDIAN_FILTER
     module.run(workspace)
     result = workspace.image_set.get_image(OUTPUT_IMAGE_NAME)
     self.assertFalse(result is None)
     np.testing.assert_almost_equal(result.pixel_data, expected)
예제 #12
0
 def test_04_02_median_multichannel(self):
     '''test the smooth module with median filtering'''
     object_size = 100.0 / 40.0
     np.random.seed(0)
     image_plane = np.random.uniform(size=(100, 100)).astype(np.float32)
     image = np.repeat(image_plane[:,:,np.newaxis], 3, axis=2)
     mask = np.ones(image.shape[:2], bool)
     mask[40:60, 45:65] = False
     expected_plane = median_filter(image_plane, mask, object_size / 2 + 1)
     expected = np.repeat(expected_plane[:,:,np.newaxis], 3, axis=2)
     workspace, module = self.make_workspace(image, mask)
     module.smoothing_method.value = S.MEDIAN_FILTER
     module.run(workspace)
     result = workspace.image_set.get_image(OUTPUT_IMAGE_NAME)
     self.assertFalse(result is None)
     np.testing.assert_almost_equal(result.pixel_data, expected)
예제 #13
0
    def run_grayscale(self, pixel_data, image):
        if self.wants_automatic_object_size.value:
            object_size = min(30, max(1, np.mean(pixel_data.shape) / 40))
        else:
            object_size = float(self.object_size.value)
        sigma = object_size / 2.35
        if self.smoothing_method.value == GAUSSIAN_FILTER:

            def fn(image):
                return scind.gaussian_filter(image,
                                             sigma,
                                             mode='constant',
                                             cval=0)

            output_pixels = smooth_with_function_and_mask(
                pixel_data, fn, image.mask)
        elif self.smoothing_method.value == MEDIAN_FILTER:
            output_pixels = median_filter(pixel_data, image.mask,
                                          object_size / 2 + 1)
        elif self.smoothing_method.value == SMOOTH_KEEPING_EDGES:
            sigma_range = float(self.sigma_range.value)

            output_pixels = skimage.restoration.denoise_bilateral(
                image=pixel_data,
                multichannel=image.multichannel,
                sigma_color=sigma_range,
                sigma_spatial=sigma)
        elif self.smoothing_method.value == FIT_POLYNOMIAL:
            output_pixels = fit_polynomial(pixel_data, image.mask,
                                           self.clip.value)
        elif self.smoothing_method.value == CIRCULAR_AVERAGE_FILTER:
            output_pixels = circular_average_filter(pixel_data,
                                                    object_size / 2 + 1,
                                                    image.mask)
        elif self.smoothing_method.value == SM_TO_AVERAGE:
            if image.has_mask:
                mean = np.mean(pixel_data[image.mask])
            else:
                mean = np.mean(pixel_data)
            output_pixels = np.ones(pixel_data.shape, pixel_data.dtype) * mean
        else:
            raise ValueError("Unsupported smoothing method: %s" %
                             self.smoothing_method.value)
        return output_pixels
예제 #14
0
 def test_00_02_all_but_one_masked(self):
     mask = np.zeros((10, 10), bool)
     mask[5, 5] = True
     result = F.median_filter(np.zeros((10, 10)), mask, 3)
예제 #15
0
 def test_00_00_zeros(self):
     '''The median filter on an array of all zeros should be zero'''
     result = F.median_filter(np.zeros((10, 10)), np.ones((10, 10), bool),
                              3)
     self.assertTrue(np.all(result == 0))
 def run(self, workspace):
     image = workspace.image_set.get_image(self.image_name.value,
                                           must_be_grayscale = True)
     #
     # Match against Matlab's strel('disk') operation.
     #
     radius = (float(self.object_size.value)-1.0) / 2.0
     mask = image.mask if image.has_mask else None
     pixel_data = image.pixel_data
     if self.method == ENHANCE:
         if self.enhance_method == E_SPECKLES:
             if self.speckle_accuracy == S_SLOW:
                 result = white_tophat(pixel_data, radius, mask)
             else:
                 #
                 # white_tophat = img - opening
                 #              = img - dilate(erode)
                 #              = img - median_filter(median_filter(0%) 100%)
                 result = pixel_data - median_filter(
                     median_filter(pixel_data, mask, radius, percent = 0), 
                     mask, radius, percent = 100)
                 if mask is not None:
                     result[~mask] = pixel_data[~mask]
         elif self.enhance_method == E_NEURITES:
             if self.neurite_choice == N_GRADIENT:
                 #
                 # white_tophat = img - opening
                 # black_tophat = closing - img
                 # desired effect = img + white_tophat - black_tophat
                 #                = img + img - opening - closing + img
                 #                = 3*img - opening - closing
                 result = (3 * pixel_data - 
                           opening(pixel_data, radius, mask) -
                           closing(pixel_data, radius, mask))
                 result[result > 1] = 1
                 result[result < 0] = 0
             else:
                 sigma = self.smoothing.value
                 smoothed = gaussian_filter(pixel_data, sigma)
                 L = hessian(smoothed, return_hessian = False,
                             return_eigenvectors = False)
                 #
                 # The positive values are darker pixels with lighter
                 # neighbors. The original ImageJ code scales the result
                 # by sigma squared - I have a feeling this might be
                 # a first-order correction for e**(-2*sigma), possibly
                 # because the hessian is taken from one pixel away
                 # and the gradient is less as sigma gets larger.
                 #
                 result = -L[:, :, 0] * (L[:, :, 0] < 0) * sigma * sigma
             if image.has_mask:
                 result[~mask] = pixel_data[~mask]
         elif self.enhance_method == E_DARK_HOLES:
             min_radius = max(1,int(self.hole_size.min / 2))
             max_radius = int((self.hole_size.max+1)/2)
             result = enhance_dark_holes(pixel_data, min_radius,
                                         max_radius, mask)
         elif self.enhance_method == E_CIRCLES:
             result = circular_hough(pixel_data, radius + .5, mask=mask)
         elif self.enhance_method == E_TEXTURE:
             result = variance_transform(pixel_data,
                                         self.smoothing.value,
                                         mask = mask)
         elif self.enhance_method == E_DIC:
             result = line_integration(pixel_data, 
                                       self.angle.value,
                                       self.decay.value,
                                       self.smoothing.value)
         else:
             raise NotImplementedError("Unimplemented enhance method: %s"%
                                       self.enhance_method.value)
     elif self.method == SUPPRESS:
         if image.has_mask:
             result = opening(image.pixel_data, radius, image.mask)
         else:
             result = opening(image.pixel_data, radius)
     else:
         raise ValueError("Unknown filtering method: %s"%self.method)
     result_image = cpi.Image(result, parent_image=image)
     workspace.image_set.add(self.filtered_image_name.value, result_image)
     
     if self.show_window:
         workspace.display_data.image = image.pixel_data
         workspace.display_data.result = result
예제 #17
0
    def run(self, workspace):
        image = workspace.image_set.get_image(self.image_name.value,
                                              must_be_grayscale=True)
        #
        # Match against Matlab's strel('disk') operation.
        #
        radius = (float(self.object_size.value) - 1.0) / 2.0
        mask = image.mask if image.has_mask else None
        pixel_data = image.pixel_data
        if self.method == ENHANCE:
            if self.enhance_method == E_SPECKLES:
                if self.speckle_accuracy == S_SLOW:
                    result = white_tophat(pixel_data, radius, mask)
                else:
                    #
                    # white_tophat = img - opening
                    #              = img - dilate(erode)
                    #              = img - median_filter(median_filter(0%) 100%)
                    result = pixel_data - median_filter(median_filter(
                        pixel_data, mask, radius, percent=0),
                                                        mask,
                                                        radius,
                                                        percent=100)
                    if mask is not None:
                        result[~mask] = pixel_data[~mask]
            elif self.enhance_method == E_NEURITES:
                if self.neurite_choice == N_GRADIENT:
                    #
                    # white_tophat = img - opening
                    # black_tophat = closing - img
                    # desired effect = img + white_tophat - black_tophat
                    #                = img + img - opening - closing + img
                    #                = 3*img - opening - closing
                    result = (3 * pixel_data -
                              opening(pixel_data, radius, mask) -
                              closing(pixel_data, radius, mask))
                    result[result > 1] = 1
                    result[result < 0] = 0
                else:
                    sigma = self.smoothing.value
                    smoothed = gaussian_filter(pixel_data, sigma)
                    L = hessian(smoothed,
                                return_hessian=False,
                                return_eigenvectors=False)
                    #
                    # The positive values are darker pixels with lighter
                    # neighbors. The original ImageJ code scales the result
                    # by sigma squared - I have a feeling this might be
                    # a first-order correction for e**(-2*sigma), possibly
                    # because the hessian is taken from one pixel away
                    # and the gradient is less as sigma gets larger.
                    #
                    result = -L[:, :, 0] * (L[:, :, 0] < 0) * sigma * sigma
                if image.has_mask:
                    result[~mask] = pixel_data[~mask]
            elif self.enhance_method == E_DARK_HOLES:
                min_radius = max(1, int(self.hole_size.min / 2))
                max_radius = int((self.hole_size.max + 1) / 2)
                result = enhance_dark_holes(pixel_data, min_radius, max_radius,
                                            mask)
            elif self.enhance_method == E_CIRCLES:
                result = circular_hough(pixel_data, radius + .5, mask=mask)
            elif self.enhance_method == E_TEXTURE:
                result = variance_transform(pixel_data,
                                            self.smoothing.value,
                                            mask=mask)
            elif self.enhance_method == E_DIC:
                result = line_integration(pixel_data, self.angle.value,
                                          self.decay.value,
                                          self.smoothing.value)
            else:
                raise NotImplementedError("Unimplemented enhance method: %s" %
                                          self.enhance_method.value)
        elif self.method == SUPPRESS:
            if image.has_mask:
                result = opening(image.pixel_data, radius, image.mask)
            else:
                result = opening(image.pixel_data, radius)
        else:
            raise ValueError("Unknown filtering method: %s" % self.method)
        result_image = cpi.Image(result, parent_image=image)
        workspace.image_set.add(self.filtered_image_name.value, result_image)

        if self.show_window:
            workspace.display_data.image = image.pixel_data
            workspace.display_data.result = result