Skip to content

Commit

Permalink
contour examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Alasdair Wilson committed Jun 27, 2024
1 parent 1996cc0 commit 3f8b2d1
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 7 deletions.
33 changes: 33 additions & 0 deletions examples/contours/boundary_a_star.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
=====================================
Adding Chan-Vese Contours to an Image
=====================================
This example shows how to add a contour based on an A-star traversal of the image in an area between two existing contours.
This is useful as a method to produce an average path between two contours, for example the 'upper' and 'lower' boundaries of a ripple.
Since it is common for waves to have a shape that is multivalued then a normal averaging method will not effectivey capture the average shape of the two contours.
"""

################################################################################
# We can load an image into a RippleImage object using the RippleImage class and then run `add_boundary_contours` to add our limits for the A* contour to the image.

import matplotlib.pyplot as plt

from ripplemapper.analyse import add_boundary_contours, add_a_star_contours
from ripplemapper.classes import RippleImage
from ripplemapper.data.example import example_data

ripple_img = RippleImage(example_data[1])
add_boundary_contours(ripple_img)

################################################################################
# From here we can run `add_a_star_contours` to add the A* contour that uses these two boundaries as its limits.

add_a_star_contours(ripple_img)

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

ripple_img.plot(include_contours=True)
plt.show()
30 changes: 30 additions & 0 deletions examples/contours/boundary_chan_vese.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
=====================================
Adding Chan-Vese Contours to an Image
=====================================
This example shows how to add a contour based on the chan-vese segmentation of the image.
The Chan-vese algorithm is a level set method for image segmentation.
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.
"""

################################################################################
# We can load an image into a RippleImage object using the RippleImage class and then run `add_chan_vese_contours` to add Chan-Vese contours to the image.

import matplotlib.pyplot as plt

from ripplemapper.analyse import add_chan_vese_contours
from ripplemapper.classes import RippleImage
from ripplemapper.data.example import example_data

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

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

ripple_img.plot(include_contours=True)
plt.show()
7 changes: 6 additions & 1 deletion examples/contours/boundary_contours.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
Adding "Boundary" Contours to an Image
===========================================
One of the foundational
Ripplemapper has a variety of ways to define the water-air interface, the most simple of which is to use the boundary contours of the image.
This example shows how to add boundary contours to an image.
What the boundary contour does is the image is first processed to find "edges" in the image, which are then processed to find the contours of the edges.
There could be any number of contours but in gereral, the longest 2 contours will define the "upper" and "lower" boundary.
These boundaries are defined as being the top and bottom of the "edge" region respectively.
"""

################################################################################
Expand Down
40 changes: 40 additions & 0 deletions examples/contours/removing_small_bumps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""
===========================================
Removing "bumps" from a computed boundary
===========================================
Since many of the methods for computing boundaries rely on contouring data, it is possible that the contours may have small "bumps" in them.
This happens when the contouring "jumps" from one parallel line to the next and back again, it looks like a small discontinuity when plotted.
These can sometimes be removed using ripplemapper.
"""

################################################################################
# We load our image into a RippleImage and then run `add_boundary_contours` to add boundary contours to the image.

import matplotlib.pyplot as plt

from ripplemapper.analyse import add_boundary_contours, remove_small_bumps
from ripplemapper.classes import RippleImage
from ripplemapper.data.example import example_data

ripple_img = RippleImage(example_data[-1])
add_boundary_contours(ripple_img, sigma=2)

################################################################################
# Plotting the contour

ripple_img.contours[0].plot()
plt.show()

################################################################################
# We can remove the small bumps by running `remove_small_bumps`.

remove_small_bumps(ripple_img.contours[0])

################################################################################
# Plotting the now smoothed contour, this is not perfectly smooth but does have some of the abrupt discontoniuties removed.

ripple_img.contours[0].plot()
plt.show()
8 changes: 4 additions & 4 deletions ripplemapper/analyse.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
__all__ = ["add_boundary_contours", "add_a_star_contours", "add_chan_vese_contours", "remove_small_bumps", "remove_small_bumps_from_images"]


def add_boundary_contours(ripple_images: list[RippleImage] or RippleImage, overwrite: bool = False, level=None, **kwargs) -> list[RippleImage]:
def add_boundary_contours(ripple_images: list[RippleImage] | RippleImage, overwrite: bool = False, level=None, **kwargs) -> list[RippleImage]:
"""Add boundary contours to a list of RippleImage objects."""
if isinstance(ripple_images, RippleImage):
ripple_images = [ripple_images]
for ripple_image in ripple_images:
if len(ripple_image.contours) > 0:
for contour in ripple_image.contours:
if 'Upper Boundary' in contour.name or 'Lower Boundary' in contour.name:
if 'Upper Boundary' in contour.method or 'Lower Boundary' in contour.method:
if overwrite:
warnings.warn(f"Overwriting boundary contour for image: {ripple_image.source_file}")
ripple_image.contours.remove(contour)
Expand All @@ -44,7 +44,7 @@ def add_a_star_contours(ripple_images: list[RippleImage] | RippleImage, contour_
warnings.warn(f"RippleImage object must have at least two contours, skipping image: {ripple_image.source_file}")
continue
for contour in ripple_image.contours:
if 'A* traversal' in contour.name:
if 'A* traversal' in contour.method:
if overwrite:
warnings.warn(f"Overwriting A* contour for image: {ripple_image.source_file}")
ripple_image.contours.remove(contour)
Expand All @@ -71,7 +71,7 @@ def add_chan_vese_contours(ripple_images: list[RippleImage] | RippleImage, overw
for ripple_image in ripple_images:
if len(ripple_image.contours) > 0:
for contour in ripple_image.contours:
if 'Chan-Vese' in contour.name:
if 'Chan-Vese' in contour.method:
if overwrite:
warnings.warn(f"Overwriting Chan-Vese contour for image: {ripple_image.source_file}")
ripple_image.contours.remove(contour)
Expand Down
4 changes: 2 additions & 2 deletions ripplemapper/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def preprocess_image(image: np.ndarray, roi_x: list[int]=False, roi_y: list[int]
blurred_gray_image = blurred_gray_image[:, roi_y[0]:roi_y[1]]
return blurred_gray_image

def cv_segmentation(image: np.ndarray, use_gradient=True, **kwargs) -> np.ndarray:
def cv_segmentation(image: np.ndarray, **kwargs) -> np.ndarray:
"""
Perform image segmentation using skimage chan-vese method.
Expand All @@ -36,7 +36,7 @@ def cv_segmentation(image: np.ndarray, use_gradient=True, **kwargs) -> np.ndarra
"""
# Define default values for kwargs in the wrapper
default_kwargs = {
'mu': 0.5,
'mu': 0.1,
'dt': 0.5,
'lambda1': 1,
'lambda2': 3,
Expand Down

0 comments on commit 3f8b2d1

Please sign in to comment.