# 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

## Low throughput¶

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 load_image:

[1]:

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
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

[2]:

ct.load() # to reload any saved masks or polylines

Nothing loaded.

[4]:

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

[5]:

pp.preprocessing.create_mask(ct)

- create mask


Next step is to perform the segmentation. To adjust vor variable brightness inside the wells we use the "adaptive" 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 ct.reset()(see above)

[6]:

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


Next we draw the output, and save the results (including a visualization).

[7]:

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

- raw image

[8]:

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.

[9]:

pp.show_image(ct.canvas)


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 polylines tool.

[11]:

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).

[12]:

pp.show_image(ct.canvas)


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.

## High throughput¶

As for the other examples I have created a preset (ex7) with appropriate settings for the example. The template can be passed to the pype using config_preset="ex7" - see below.

[13]:

import phenopype as pp

image_path = r"./images/worms.jpg"

print(pp.presets.ex7)


preprocessing:
segmentation:
- threshold:
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_polylines
export:
- save_contours:
overwrite: true


[14]:

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 +++--------------

PREPROCESSING
SEGMENTATION
threshold
find_contours
MEASUREMENT
skeletonize
VISUALIZATION
NoneType
select_canvas
- invalid selection - defaulting to raw image
ndarray
draw_contours
ndarray
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).

[14]:

<phenopype.main.pype at 0x281ac3af0c8>

[ ]: