Skip to content

Commit

Permalink
added use_gradients keyword toa dd_chan_vese_contours
Browse files Browse the repository at this point in the history
  • Loading branch information
alasdairwilson committed Jul 10, 2024
1 parent 7fa2d1a commit 827da4a
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 8 deletions.
12 changes: 11 additions & 1 deletion examples/contours/boundary_chan_vese.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
It is based on the Mumford-Shah functional and is designed to segment images without edges.
In this example, we will the `ripplemapper.analyse` module to segment the image and add the resulting contour to the image.
The CV segmentation is a more unreliable way to form the contours.
"""

################################################################################
Expand All @@ -20,11 +22,19 @@
from ripplemapper.classes import RippleImage
from ripplemapper.data.example import example_data

ripple_img = RippleImage(example_data[1])
ripple_img = RippleImage(example_data[2])
add_chan_vese_contours(ripple_img)

################################################################################
# Plotting the image and its contours

ripple_img.plot(include_contours=True)
plt.show()

################################################################################
# We can also add the Chan-Vese contours to a image where we use a combination of the divergence of the image and the regular image.
# This might improve the segmentation technique

add_chan_vese_contours(ripple_img, use_gradients=True, overwrite=True)
ripple_img.plot(include_contours=True)
plt.show()
9 changes: 7 additions & 2 deletions ripplemapper/analyse.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def add_a_star_contours(ripple_images: list[RippleImage] | RippleImage | RippleI
path = np.flip(np.array(path), axis=0).T # the path output has insane shape, need to flip it
ripple_image.add_contour(path, 'A* traversal')

def add_chan_vese_contours(ripple_images: list[RippleImage] | RippleImage | RippleImageSeries, overwrite: bool = False, **kwargs):
def add_chan_vese_contours(ripple_images: list[RippleImage] | RippleImage | RippleImageSeries, overwrite: bool = False, use_gradients=False, **kwargs):
"""Add Chan-Vese contours to a list of RippleImage objects."""
if isinstance(ripple_images, RippleImageSeries):
ripple_images = ripple_images.images
Expand All @@ -84,7 +84,12 @@ def add_chan_vese_contours(ripple_images: list[RippleImage] | RippleImage | Ripp
else:
warnings.warn(f"Chan-Vese contour already exists, skipping image: {ripple_image.source_file}")
continue
cv = cv_segmentation(ripple_image.image, **kwargs)
if use_gradients:
grad = np.sum(np.abs(np.gradient(ripple_image.image)), axis=0)
img = cv2.GaussianBlur(grad / np.max(grad), (7,7), 0)+(1-(ripple_image.image/np.max(ripple_image.image)))
cv = cv_segmentation(img, **kwargs)
else:
cv = cv_segmentation(ripple_image.image, **kwargs)
contours = find_contours(cv)
ripple_image.add_contour(np.array([contours[0][:,0],contours[0][:,1]]), 'Chan-Vese')

Expand Down
49 changes: 44 additions & 5 deletions ripplemapper/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,22 @@
from skimage import color, feature, filters, morphology
from skimage.segmentation import chan_vese

__all__ = ["preprocess_image", "cv_segmentation", "detect_edges", "process_edges"]
__all__ = ["preprocess_image", "cv_segmentation", "detect_edges", "process_edges", "threshold_image"]

def threshold_image(image: np.ndarray, level=0.8) -> np.ndarray:
"""
Threshold the image to make any pixel above the level equal to the max.
Parameters:
image numpy.ndarray: Input image.
level float: Threshold value.
Returns:
numpy.ndarray: Binary image.
"""
image = np.where(image > level, np.max(image))
return image


def preprocess_image(image: np.ndarray, roi_x: list[int]=False, roi_y: list[int]=False, sigma: float=1) -> np.ndarray:
"""
Expand Down Expand Up @@ -36,10 +51,12 @@ def cv_segmentation(image: np.ndarray, **kwargs) -> np.ndarray:
"""
# Define default values for kwargs in the wrapper
default_kwargs = {
'mu': 0.1,
'mu': 0.2,
'dt': 0.5,
'lambda1': 1,
'lambda2': 3,
'lambda2': 1,
'max_num_iter': 500,
'tol': 1e-3,
}

# Update kwargs with default values if they are not already set
Expand Down Expand Up @@ -77,8 +94,30 @@ def process_edges(edges_gray: np.ndarray, sigma: float=0) -> np.ndarray:
"""
edges_dilated = morphology.binary_dilation(edges_gray, footprint=np.ones((5, 5)))
edges_closed = morphology.binary_closing(edges_dilated, footprint=np.ones((5, 5)))
edges_cleaned = morphology.remove_small_objects(edges_closed, min_size=300)
edges_cleaned = morphology.remove_small_objects(edges_closed, min_size=64)
# optionally blur the edges
if sigma > 0:
edges_cleaned = filters.gaussian(edges_cleaned, sigma=sigma)
return edges_cleaned
return edges_closed


if __name__ == "__main__":
from matplotlib import pyplot as plt

from ripplemapper.analyse import (add_a_star_contours,
add_boundary_contours,
add_chan_vese_contours)
from ripplemapper.io import load_dir_to_obj

x = load_dir_to_obj('/mnt/h/Downloads/D16H10/high_speed/', roi_x=[400,900], skip=25, start=200, end=250)
# calculate divergence of image
# img = cv2.GaussianBlur(np.sum(np.abs(np.gradient(x[1].image)), axis=0)/np.max(x[1].image), (11,11), 0)*cv2.GaussianBlur(1-(x[1].image/np.max(x[1].image)), (11,11), 1)
# img = img/np.max(img)
# x[1].image = img
add_boundary_contours(x[1], sigma=2)
add_a_star_contours(x[1])
add_chan_vese_contours(x[1], use_gradients=True)
x[1].plot()


plt.show()

0 comments on commit 827da4a

Please sign in to comment.