Beispiel #1
0
    def run_function(self, function, pixel_data, mask):
        '''Apply the function once to the image, returning the result'''
        count = function.repeat_count
        function_name = function.function.value
        scale = function.scale.value
        custom_repeats = function.custom_repeats.value

        is_binary = pixel_data.dtype.kind == 'b'
        if function.structuring_element == SE_ARBITRARY:
            strel = np.array(function.strel.get_matrix())
        elif function.structuring_element == SE_DISK:
            strel = morph.strel_disk(scale / 2.0)
        elif function.structuring_element == SE_DIAMOND:
            strel = morph.strel_diamond(scale / 2.0)
        elif function.structuring_element == SE_LINE:
            strel = morph.strel_line(scale, function.angle.value)
        elif function.structuring_element == SE_OCTAGON:
            strel = morph.strel_octagon(scale / 2.0)
        elif function.structuring_element == SE_PAIR:
            strel = morph.strel_pair(function.x_offset.value,
                                     function.y_offset.value)
        elif function.structuring_element == SE_PERIODIC_LINE:
            xoff = function.x_offset.value
            yoff = function.y_offset.value
            n = max(scale / 2.0 / np.sqrt(float(xoff * xoff + yoff * yoff)), 1)
            strel = morph.strel_periodicline(xoff, yoff, n)
        elif function.structuring_element == SE_RECTANGLE:
            strel = morph.strel_rectangle(function.width.value,
                                          function.height.value)
        else:
            strel = morph.strel_square(scale)

        if (function_name
                in (F_BRANCHPOINTS, F_BRIDGE, F_CLEAN, F_DIAG, F_CONVEX_HULL,
                    F_DISTANCE, F_ENDPOINTS, F_FILL, F_FILL_SMALL, F_HBREAK,
                    F_LIFE, F_MAJORITY, F_REMOVE, F_SHRINK, F_SKEL, F_SKELPE,
                    F_SPUR, F_THICKEN, F_THIN, F_VBREAK) and not is_binary):
            # Apply a very crude threshold to the image for binary algorithms
            logger.warning("Warning: converting image to binary for %s\n" %
                           function_name)
            pixel_data = pixel_data != 0

        if (function_name
                in (F_BRANCHPOINTS, F_BRIDGE, F_CLEAN, F_DIAG, F_CONVEX_HULL,
                    F_DISTANCE, F_ENDPOINTS, F_FILL, F_FILL_SMALL, F_HBREAK,
                    F_INVERT, F_LIFE, F_MAJORITY, F_REMOVE, F_SHRINK, F_SKEL,
                    F_SKELPE, F_SPUR, F_THICKEN, F_THIN, F_VBREAK, F_OPENLINES)
                or
            (is_binary
             and function_name in (F_CLOSE, F_DILATE, F_ERODE, F_OPEN))):
            # All of these have an iterations argument or it makes no
            # sense to iterate
            if function_name == F_BRANCHPOINTS:
                return morph.branchpoints(pixel_data, mask)
            elif function_name == F_BRIDGE:
                return morph.bridge(pixel_data, mask, count)
            elif function_name == F_CLEAN:
                return morph.clean(pixel_data, mask, count)
            elif function_name == F_CLOSE:
                if mask is None:
                    return scind.binary_closing(pixel_data,
                                                strel,
                                                iterations=count)
                else:
                    return (scind.binary_closing(
                        pixel_data & mask, strel, iterations=count) |
                            (pixel_data & ~mask))
            elif function_name == F_CONVEX_HULL:
                if mask is None:
                    return morph.convex_hull_image(pixel_data)
                else:
                    return morph.convex_hull_image(pixel_data & mask)
            elif function_name == F_DIAG:
                return morph.diag(pixel_data, mask, count)
            elif function_name == F_DILATE:
                return scind.binary_dilation(pixel_data,
                                             strel,
                                             iterations=count,
                                             mask=mask)
            elif function_name == F_DISTANCE:
                image = scind.distance_transform_edt(pixel_data)
                if function.rescale_values.value:
                    image = image / np.max(image)
                return image
            elif function_name == F_ENDPOINTS:
                return morph.endpoints(pixel_data, mask)
            elif function_name == F_ERODE:
                return scind.binary_erosion(pixel_data,
                                            strel,
                                            iterations=count,
                                            mask=mask)
            elif function_name == F_FILL:
                return morph.fill(pixel_data, mask, count)
            elif function_name == F_FILL_SMALL:

                def small_fn(area, foreground):
                    return (not foreground) and (area <= custom_repeats)

                return morph.fill_labeled_holes(pixel_data, mask, small_fn)
            elif function_name == F_HBREAK:
                return morph.hbreak(pixel_data, mask, count)
            elif function_name == F_INVERT:
                if is_binary:
                    if mask is None:
                        return ~pixel_data
                    result = pixel_data.copy()
                    result[mask] = ~result[mask]
                    return result
                elif mask is None:
                    return 1 - pixel_data
                else:
                    result = pixel_data.copy()
                    result[mask] = 1 - result[mask]
                    return result
            elif function_name == F_LIFE:
                return morph.life(pixel_data, count)
            elif function_name == F_MAJORITY:
                return morph.majority(pixel_data, mask, count)
            elif function_name == F_OPEN:
                if mask is None:
                    return scind.binary_opening(pixel_data,
                                                strel,
                                                iterations=count)
                else:
                    return (scind.binary_opening(
                        pixel_data & mask, strel, iterations=count) |
                            (pixel_data & ~mask))
            elif function_name == F_OPENLINES:
                return morph.openlines(pixel_data,
                                       linelength=custom_repeats,
                                       mask=mask)
            elif function_name == F_REMOVE:
                return morph.remove(pixel_data, mask, count)
            elif function_name == F_SHRINK:
                return morph.binary_shrink(pixel_data, count)
            elif function_name == F_SKEL:
                return morph.skeletonize(pixel_data, mask)
            elif function_name == F_SKELPE:
                return morph.skeletonize(
                    pixel_data, mask,
                    scind.distance_transform_edt(pixel_data) *
                    poisson_equation(pixel_data))
            elif function_name == F_SPUR:
                return morph.spur(pixel_data, mask, count)
            elif function_name == F_THICKEN:
                return morph.thicken(pixel_data, mask, count)
            elif function_name == F_THIN:
                return morph.thin(pixel_data, mask, count)
            elif function_name == F_VBREAK:
                return morph.vbreak(pixel_data, mask)
            else:
                raise NotImplementedError(
                    "Unimplemented morphological function: %s" % function_name)
        else:
            for i in range(count):
                if function_name == F_BOTHAT:
                    new_pixel_data = morph.black_tophat(pixel_data,
                                                        mask=mask,
                                                        footprint=strel)
                elif function_name == F_CLOSE:

                    new_pixel_data = morph.closing(pixel_data,
                                                   mask=mask,
                                                   footprint=strel)
                elif function_name == F_DILATE:
                    new_pixel_data = morph.grey_dilation(pixel_data,
                                                         mask=mask,
                                                         footprint=strel)
                elif function_name == F_ERODE:
                    new_pixel_data = morph.grey_erosion(pixel_data,
                                                        mask=mask,
                                                        footprint=strel)
                elif function_name == F_OPEN:
                    new_pixel_data = morph.opening(pixel_data,
                                                   mask=mask,
                                                   footprint=strel)
                elif function_name == F_TOPHAT:
                    new_pixel_data = morph.white_tophat(pixel_data,
                                                        mask=mask,
                                                        footprint=strel)
                else:
                    raise NotImplementedError(
                        "Unimplemented morphological function: %s" %
                        function_name)
                if np.all(new_pixel_data == pixel_data):
                    break
                pixel_data = new_pixel_data
            return pixel_data
Beispiel #2
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
 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
Beispiel #4
0
    def run_function(self, function, pixel_data, mask):
        '''Apply the function once to the image, returning the result'''
        count = function.repeat_count
        function_name = function.function.value
        scale = function.scale.value
        custom_repeats = function.custom_repeats.value

        is_binary = pixel_data.dtype.kind == 'b'
        if function.structuring_element == SE_ARBITRARY:
            strel = np.array(function.strel.get_matrix())
        elif function.structuring_element == SE_DISK:
            strel = morph.strel_disk(scale / 2.0)
        elif function.structuring_element == SE_DIAMOND:
            strel = morph.strel_diamond(scale / 2.0)
        elif function.structuring_element == SE_LINE:
            strel = morph.strel_line(scale, function.angle.value)
        elif function.structuring_element == SE_OCTAGON:
            strel = morph.strel_octagon(scale / 2.0)
        elif function.structuring_element == SE_PAIR:
            strel = morph.strel_pair(function.x_offset.value,
                                     function.y_offset.value)
        elif function.structuring_element == SE_PERIODIC_LINE:
            xoff = function.x_offset.value
            yoff = function.y_offset.value
            n = max(scale / 2.0 / np.sqrt(float(xoff * xoff + yoff * yoff)), 1)
            strel = morph.strel_periodicline(
                    xoff, yoff, n)
        elif function.structuring_element == SE_RECTANGLE:
            strel = morph.strel_rectangle(
                    function.width.value, function.height.value)
        else:
            strel = morph.strel_square(scale)

        if (function_name in (F_BRANCHPOINTS, F_BRIDGE, F_CLEAN, F_DIAG,
                              F_CONVEX_HULL, F_DISTANCE, F_ENDPOINTS, F_FILL,
                              F_FILL_SMALL, F_HBREAK, F_LIFE, F_MAJORITY,
                              F_REMOVE, F_SHRINK, F_SKEL, F_SKELPE, F_SPUR,
                              F_THICKEN, F_THIN, F_VBREAK)
            and not is_binary):
            # Apply a very crude threshold to the image for binary algorithms
            logger.warning("Warning: converting image to binary for %s\n" %
                           function_name)
            pixel_data = pixel_data != 0

        if (function_name in (F_BRANCHPOINTS, F_BRIDGE, F_CLEAN, F_DIAG,
                              F_CONVEX_HULL, F_DISTANCE, F_ENDPOINTS, F_FILL,
                              F_FILL_SMALL,
                              F_HBREAK, F_INVERT, F_LIFE, F_MAJORITY, F_REMOVE,
                              F_SHRINK,
                              F_SKEL, F_SKELPE, F_SPUR, F_THICKEN, F_THIN,
                              F_VBREAK, F_OPENLINES) or
                (is_binary and
                         function_name in (F_CLOSE, F_DILATE, F_ERODE, F_OPEN))):
            # All of these have an iterations argument or it makes no
            # sense to iterate
            if function_name == F_BRANCHPOINTS:
                return morph.branchpoints(pixel_data, mask)
            elif function_name == F_BRIDGE:
                return morph.bridge(pixel_data, mask, count)
            elif function_name == F_CLEAN:
                return morph.clean(pixel_data, mask, count)
            elif function_name == F_CLOSE:
                if mask is None:
                    return scind.binary_closing(pixel_data,
                                                strel,
                                                iterations=count)
                else:
                    return (scind.binary_closing(pixel_data & mask,
                                                 strel,
                                                 iterations=count) |
                            (pixel_data & ~ mask))
            elif function_name == F_CONVEX_HULL:
                if mask is None:
                    return morph.convex_hull_image(pixel_data)
                else:
                    return morph.convex_hull_image(pixel_data & mask)
            elif function_name == F_DIAG:
                return morph.diag(pixel_data, mask, count)
            elif function_name == F_DILATE:
                return scind.binary_dilation(pixel_data,
                                             strel,
                                             iterations=count,
                                             mask=mask)
            elif function_name == F_DISTANCE:
                image = scind.distance_transform_edt(pixel_data)
                if function.rescale_values.value:
                    image = image / np.max(image)
                return image
            elif function_name == F_ENDPOINTS:
                return morph.endpoints(pixel_data, mask)
            elif function_name == F_ERODE:
                return scind.binary_erosion(pixel_data, strel,
                                            iterations=count,
                                            mask=mask)
            elif function_name == F_FILL:
                return morph.fill(pixel_data, mask, count)
            elif function_name == F_FILL_SMALL:
                def small_fn(area, foreground):
                    return (not foreground) and (area <= custom_repeats)

                return morph.fill_labeled_holes(pixel_data, mask, small_fn)
            elif function_name == F_HBREAK:
                return morph.hbreak(pixel_data, mask, count)
            elif function_name == F_INVERT:
                if is_binary:
                    if mask is None:
                        return ~ pixel_data
                    result = pixel_data.copy()
                    result[mask] = ~result[mask]
                    return result
                elif mask is None:
                    return 1 - pixel_data
                else:
                    result = pixel_data.copy()
                    result[mask] = 1 - result[mask]
                    return result
            elif function_name == F_LIFE:
                return morph.life(pixel_data, count)
            elif function_name == F_MAJORITY:
                return morph.majority(pixel_data, mask, count)
            elif function_name == F_OPEN:
                if mask is None:
                    return scind.binary_opening(pixel_data,
                                                strel,
                                                iterations=count)
                else:
                    return (scind.binary_opening(pixel_data & mask,
                                                 strel,
                                                 iterations=count) |
                            (pixel_data & ~ mask))
            elif function_name == F_OPENLINES:
                return morph.openlines(pixel_data, linelength=custom_repeats, mask=mask)
            elif function_name == F_REMOVE:
                return morph.remove(pixel_data, mask, count)
            elif function_name == F_SHRINK:
                return morph.binary_shrink(pixel_data, count)
            elif function_name == F_SKEL:
                return morph.skeletonize(pixel_data, mask)
            elif function_name == F_SKELPE:
                return morph.skeletonize(
                        pixel_data, mask,
                        scind.distance_transform_edt(pixel_data) *
                        poisson_equation(pixel_data))
            elif function_name == F_SPUR:
                return morph.spur(pixel_data, mask, count)
            elif function_name == F_THICKEN:
                return morph.thicken(pixel_data, mask, count)
            elif function_name == F_THIN:
                return morph.thin(pixel_data, mask, count)
            elif function_name == F_VBREAK:
                return morph.vbreak(pixel_data, mask)
            else:
                raise NotImplementedError("Unimplemented morphological function: %s" %
                                          function_name)
        else:
            for i in range(count):
                if function_name == F_BOTHAT:
                    new_pixel_data = morph.black_tophat(pixel_data, mask=mask,
                                                        footprint=strel)
                elif function_name == F_CLOSE:

                    new_pixel_data = morph.closing(pixel_data, mask=mask,
                                                   footprint=strel)
                elif function_name == F_DILATE:
                    new_pixel_data = morph.grey_dilation(pixel_data, mask=mask,
                                                         footprint=strel)
                elif function_name == F_ERODE:
                    new_pixel_data = morph.grey_erosion(pixel_data, mask=mask,
                                                        footprint=strel)
                elif function_name == F_OPEN:
                    new_pixel_data = morph.opening(pixel_data, mask=mask,
                                                   footprint=strel)
                elif function_name == F_TOPHAT:
                    new_pixel_data = morph.white_tophat(pixel_data, mask=mask,
                                                        footprint=strel)
                else:
                    raise NotImplementedError("Unimplemented morphological function: %s" %
                                              function_name)
                if np.all(new_pixel_data == pixel_data):
                    break
                pixel_data = new_pixel_data
            return pixel_data