Example 7: Measuring worm length¶
Body length is a commonly measured trait. However, live animals are typically not well behaved in front of camera: typically the body is not aligned straight, which makes length measure difficult and sometimes time consuming. Some computer vision can help here, such as skeletonization (https://en.wikipedia.org/wiki/Topological_skeleton) for an acurate semi automatic approach, and polyline drawing for a less acurate, manual aproach.
Here I demonstrate how to automatically measure the length of california blackworms (Lumbriculus variegatus) in 6 well plates by dragging a mask around them. A future implementation will like include a variant of Hough transformation to automatically detect the circles of the wellplates for a full automatic workflow.
Note: For details on the differen workflows (prototyping-, low throughput- and high throughout) see Tutorial 2. Not all examples include the prototyping workflow.
Input - Worms placed in 6 well plates
Results - extracted body contour (green area) and body length (red line) as a topological skeleton
First we load the image as a container. If you have saved data before with a specific
save_suffix (recommended for reproducibility and to not overwrite files) you can reload it if you have provided it at the point of container creation in
import phenopype as pp image_path = r"./images/worms.jpg" custom_save_path = r"../_temp/output/ex7" ct = pp.load_image(image_path, # path to image cont=True, # create a phenopype container save_suffix="worms1", # indicate a suffix for save- and loading operations dirpath=custom_save_path) # supply an (existing) directory where files get stored and loaded from
Directory to save files set at - E:\git_repos\phenopype\_temp\output
ct.load() # to reload any saved masks or polylines
ct.reset() # reset canvas and images, if you run repeatedly
First we drag a rectangle around each worm in each well. Future releases will include “circle”-shaped mask tools, and the opportunity to automatically find circles using hough transform - OpenCV is already set up to do so: https://docs.opencv.org/3.4/d4/d70/tutorial_hough_circle.html
- create mask
Next step is to perform the segmentation. To adjust vor variable brightness inside the wells we use the
threshold method, and afterwards,
find_contours. If the worms touch the border of the well, or their own body, you can directly manipulate the binary image using the draw function (two clicks draw a line, or use the argument
tool="rectangle". Sometimes a worm may overlap with itself - in that case, use
polylines to measure it manually.
Be aware that low- and high-throughput workflows are designed for consecutive application of functions, meaning that repeated execution of thresholding will be on an already thresholded image. To restart that process, reset the container with
pp.segmentation.threshold(ct, method="adaptive", blocksize=49, constant=5) ## pp.segmentation(draw) # uncomment this if you need to manually separate worms from the well-border pp.segmentation.find_contours(ct, min_diameter=50) ## pp.visualization.polylines(ct) # uncomment this if you need to manually measure a worm pp.measurement.skeletonize(ct) # this will measure the longest distance in a curvy object
- include mask "mask1" pixels - include mask "mask1" pixels - include mask "mask1" pixels - include mask "mask1" pixels - include mask "mask1" pixels - include mask "mask1" pixels
Next we draw the output, and save the results (including a visualization).
pp.visualization.select_canvas(ct, canvas="raw") # first select a background (try "binary") pp.visualization.draw_contours(ct) # this draws both the contour (green) and the skeleton pp.visualization.draw_masks(ct) # will be skipped if loaded before
- raw image - show mask: mask1. - show mask: mask1. - show mask: mask1. - show mask: mask1. - show mask: mask1. - show mask: mask1.
pp.export.save_masks(ct, dirpath=custom_save_path) # pp.export.save_contours(ct, dirpath=custom_save_path) pp.export.save_canvas(ct, dirpath=custom_save_path, resize=1) # resize=1 to have the original sized picture
- masks saved under ../_temp/output\masks_worms1.csv. - contours saved under ../_temp/output\contours_worms1.csv. - canvas saved under ../_temp/output\canvas_worms1.jpg.
Should a worm superimpose itself it is not possible for the skeletonization algorithm to follow the shape through from beginning to end (e.g. in worm 3 in this example). In that case one has to manually draw a line along the worm using the
pp.measurement.polylines(ct) pp.visualization.draw_polylines(ct) pp.export.save_polylines(ct)
- polylines already drawn (overwrite=False) - polylines saved under ../_temp/output\polylines_worms1.csv (overwritten).
Alternatively to the
polylines tool, one can also use the drawing tool if you just need to separte an endpoint or if the worm touches the border. This should be done on the binary image, before the contour are detected.
As for the other examples I have created a preset (
ex7) with appropriate settings for the example. The template can be passed to the
config_preset="ex7" - see below.
import phenopype as pp image_path = r"./images/worms.jpg" print(pp.presets.ex7)
preprocessing: - create_mask segmentation: - threshold: method: adaptive blocksize: 49 constant: 5 # - draw - find_contours: retrieval: ccomp min_diameter: 50 min_area: 0 measurement: - skeletonize # - polylines visualization: - select_canvas: canvas: image - draw_contours: line_width: 2 label_width: 1 label_size: 1 fill: 0.3 - draw_masks # - draw_polylines export: - save_contours: overwrite: true
pp.pype(image_path, name="worms2", dirpath=r"../_temp/output/ex7", config_preset="ex7")
../_temp/output/ex7\pype_config_worms2.yaml ------------+++ new pype iteration 2020:04:28 18:36:50 +++-------------- AUTOLOAD - masks_worms2.csv PREPROCESSING create_mask - mask with label mask1 already created (overwrite=False) SEGMENTATION threshold - include mask "mask1" pixels - include mask "mask1" pixels - include mask "mask1" pixels - include mask "mask1" pixels - include mask "mask1" pixels - include mask "mask1" pixels find_contours MEASUREMENT skeletonize VISUALIZATION NoneType select_canvas - invalid selection - defaulting to raw image ndarray draw_contours ndarray draw_masks - show mask: mask1. - show mask: mask1. - show mask: mask1. - show mask: mask1. - show mask: mask1. - show mask: mask1. EXPORT save_contours - contours saved under ../_temp/output/ex7\contours_worms2.csv (overwritten). AUTOSAVE save_canvas - canvas saved under ../_temp/output/ex7\canvas_worms2.jpg (overwritten). save_masks - masks not saved - file already exists (overwrite=False). TERMINATE
<phenopype.main.pype at 0x281ac3af0c8>