Tutorial 6: Size and colour reference¶
Unless images are taken in a highly standardized environment, e.g. via a scanner or a microscope, variation will be introduced in terms of exposure or distance between camera and photographed object, zooming, etc. To compensate this variation among images within and across datasets, Phenopype contains some preprocessing tools that can automatically correct images.
Load project¶
We will use the project we created before in Tutorial 5:
import phenopype as pp
import os
os.chdir(r"C:\Users\mluerig\Downloads\phenopype-tutorials-main")
myproj = pp.Project(r"tutorial_project")
--------------------------------------------
Found existing project root directory - loading from:
C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project
Project "tutorial_project" successfully loaded with 3 images
--------------------------------------------
First we will need to select and measure the pixel-ratio in a reference image, to which we want to match all images in the project.
Adding a reference to the project¶
With the class method add_reference
we can set a project specific scale by measuring the pixel-ratio in a reference image. The steps for this are:
Click on two points with a known distance, e.g. on a piece of mm-paper that you put in the image, and hit
Enter
.Enter the length that will be used to calculate the pixel-ratio.
Mark the boundaries of the reference card to create a template for automatic scale detection that is saved on the project’s root directory (in the template folder).
Fig 1 The reference image can be any image, but choose it carefully: if you plan on doing brightness and colour corrections, it should be in the middle of the distribution of all exposures and colours so corrections will not over-expose or over-saturate the images.
We will use the image stickleback_side.jpg
from the image
folder in tutorials
:
myproj.add_reference(
reference_image_path=r"tutorials/data/stickleback_side.jpg",
reference_tag="scale1",
)
Reference image not saved, file already exists - use "overwrite==True" or chose different name.
setting active global project reference to "scale1" for 0__stickle1 (active=True)
setting active global project reference to "scale1" for 0__stickle2 (active=True)
setting active global project reference to "scale1" for 0__stickle3 (active=True)
We are now all set to automatically detect the reference card in our images.
Detecting a reference¶
To detect the reference template in our images, we need the function detect_reference
from the preprocessing
module. To do so on the existing project, we will use the edit_config
method that was demonstrated in Tutorial 5. Again, we want to modify the config in two places: first in the preprocessing chunk, to perform the actual reference detection, and then in the visualization chunk, to show the outline of the detected reference:
## modify the "preprocessing" section
target1 = """ - preprocessing:"""
replacement1 = """ - preprocessing:
- detect_reference"""
myproj.edit_config(
tag="plates-v1",
target=target1,
replacement=replacement1,
)
# phenopype quickstart template
# -----------------------------
# This template is intended to go with the phenopype quickstart materials
# - for details see https://www.phenopype.org/docs/quickstart/ and refer to
# Figure 2 in Luerig 2021 (https://doi.org/10.1111/2041-210X.13771) or
# phenopype tutorial 3 (https://www.phenopype.org/docs/tutorials/tutorial_3).
# For a better job of measuring individual plate area see the phenopype
# gallery (https://www.phenopype.org/gallery/example_5/).
config_info:
config_name: pype_config_plates-v1.yaml
date_created: '2022-05-06 15:04:33'
date_last_modified:
template_name: quickstart-template.yaml
template_path: C:\Users\mluerig\Downloads\phenopype-quickstart-main\quickstart-template.yaml
processing_steps:
- preprocessing:
- detect_reference
- create_mask:
ANNOTATION: {type: mask, id: a, edit: false}
tool: polygon
label: plates
- blur:
kernel_size: 9
- segmentation:
- threshold:
method: adaptive
blocksize: 99
constant: 5
- detect_contour:
ANNOTATION: {type: contour, id: a, edit: overwrite}
retrieval: ext
min_area: 150
- measurement:
- compute_shape_features:
ANNOTATION: {type: shape_features, id: a, edit: overwrite}
- visualization:
- select_canvas:
canvas: raw
- draw_contour
- draw_mask:
label: true
- export:
- save_canvas
- save_annotation:
overwrite: true
This is what the new config may look like (can differ beteeen files) - proceed?y
New config saved for 0__stickle1
New config saved for 0__stickle2
New config saved for 0__stickle3
## "visualization" modification to add `draw_reference`:
target2 = """- draw_mask:
label: true"""
replacement2 = """- draw_mask:
label: true
- draw_reference:
line_colour: aqua
line_width: 10
scale: true"""
myproj.edit_config(
tag="plates-v1",
target=target2,
replacement=replacement2,
)
# phenopype quickstart template
# -----------------------------
# This template is intended to go with the phenopype quickstart materials
# - for details see https://www.phenopype.org/docs/quickstart/ and refer to
# Figure 2 in Luerig 2021 (https://doi.org/10.1111/2041-210X.13771) or
# phenopype tutorial 3 (https://www.phenopype.org/docs/tutorials/tutorial_3).
# For a better job of measuring individual plate area see the phenopype
# gallery (https://www.phenopype.org/gallery/example_5/).
config_info:
config_name: pype_config_plates-v1.yaml
date_created: '2022-05-06 15:04:33'
date_last_modified:
template_name: quickstart-template.yaml
template_path: C:\Users\mluerig\Downloads\phenopype-quickstart-main\quickstart-template.yaml
processing_steps:
- preprocessing:
- detect_reference
- create_mask:
ANNOTATION: {type: mask, id: a, edit: false}
tool: polygon
label: plates
- blur:
kernel_size: 9
- segmentation:
- threshold:
method: adaptive
blocksize: 99
constant: 5
- detect_contour:
ANNOTATION: {type: contour, id: a, edit: overwrite}
retrieval: ext
min_area: 150
- measurement:
- compute_shape_features:
ANNOTATION: {type: shape_features, id: a, edit: overwrite}
- visualization:
- select_canvas:
canvas: raw
- draw_contour
- draw_mask:
label: true
- draw_reference:
line_colour: aqua
line_width: 10
scale: true
- export:
- save_canvas
- save_annotation:
overwrite: true
This is what the new config may look like (can differ beteeen files) - proceed?y
New config saved for 0__stickle1
New config saved for 0__stickle2
New config saved for 0__stickle3
Now we run our loop with the new pype
configuration:
for path in myproj.dir_paths:
pp.Pype(path, tag="plates-v1")
- no annotation_type selected - returning all annotations
AUTOLOAD
- annotations loaded:
{
"mask": ["a"],
"contour": ["a"],
"shape_features": ["a"],
"reference": ["a"]
}
- reference template image loaded from root directory
Stage: add annotation control args
Updating pype config: applying staged changes
------------+++ new pype iteration 2022-05-06 15:08:46 +++--------------
PREPROCESSING
detect_reference
- loaded existing annotation of type "reference" with ID "a": skipping (edit=False)
create_mask
- loaded existing annotation of type "mask" with ID "a": skipping (edit=False)
blur
SEGMENTATION
threshold
- multichannel image supplied, converting to grayscale
- decompose image: using gray channel
- including pixels from 1 drawn masks
- excluding pixels from reference
detect_contour
- loaded existing annotation of type "contour" with ID "a": overwriting (edit=overwrite)
- found 16 contours that match criteria
MEASUREMENT
compute_shape_features
- loaded existing annotation of type "shape_features" with ID "a": overwriting (edit=overwrite)
VISUALIZATION
select_canvas
- raw image
draw_contour
draw_mask
draw_reference
EXPORT
save_canvas
- image saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle1\canvas_plates-v1.jpg (overwritten).
save_annotation
- loading existing annotation file
- no annotation_type selected - exporting all annotations
- updating annotations of type "mask" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "contour" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "shape_features" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "reference" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
------------+++ finished pype iteration +++--------------
-------(End with Ctrl+Enter or re-run with Enter)--------
AUTOSHOW
------------+++ new pype iteration 2022-05-06 15:08:52 +++--------------
PREPROCESSING
detect_reference
- loaded existing annotation of type "reference" with ID "a": skipping (edit=False)
create_mask
- loaded existing annotation of type "mask" with ID "a": skipping (edit=False)
blur
SEGMENTATION
threshold
- multichannel image supplied, converting to grayscale
- decompose image: using gray channel
- including pixels from 1 drawn masks
- excluding pixels from reference
detect_contour
- loaded existing annotation of type "contour" with ID "a": overwriting (edit=overwrite)
- found 16 contours that match criteria
MEASUREMENT
compute_shape_features
- loaded existing annotation of type "shape_features" with ID "a": overwriting (edit=overwrite)
VISUALIZATION
select_canvas
- raw image
draw_contour
draw_mask
draw_reference
EXPORT
save_canvas
- image saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle1\canvas_plates-v1.jpg (overwritten).
save_annotation
- loading existing annotation file
- no annotation_type selected - exporting all annotations
- updating annotations of type "mask" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "contour" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "shape_features" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "reference" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
------------+++ finished pype iteration +++--------------
-------(End with Ctrl+Enter or re-run with Enter)--------
AUTOSHOW
TERMINATE
AUTOSAVE
- nothing to autosave
- no annotation_type selected - returning all annotations
AUTOLOAD
- annotations loaded:
{
"mask": ["a"],
"contour": ["a"],
"shape_features": ["a"]
}
- reference template image loaded from root directory
Stage: add annotation control args
Updating pype config: applying staged changes
------------+++ new pype iteration 2022-05-06 15:08:54 +++--------------
PREPROCESSING
detect_reference
---------------------------------------------------
Reference card found with 226 keypoint matches:
template image has 36.44 pixel per mm.
current image has 35.21 pixel per mm.
= 96.626 %% of template image.
---------------------------------------------------
create_mask
- loaded existing annotation of type "mask" with ID "a": skipping (edit=False)
blur
SEGMENTATION
threshold
- multichannel image supplied, converting to grayscale
- decompose image: using gray channel
- including pixels from 1 drawn masks
- excluding pixels from reference
detect_contour
- loaded existing annotation of type "contour" with ID "a": overwriting (edit=overwrite)
- found 9 contours that match criteria
MEASUREMENT
compute_shape_features
- loaded existing annotation of type "shape_features" with ID "a": overwriting (edit=overwrite)
VISUALIZATION
select_canvas
- raw image
draw_contour
draw_mask
draw_reference
EXPORT
save_canvas
- image saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle2\canvas_plates-v1.jpg (overwritten).
save_annotation
- loading existing annotation file
- no annotation_type selected - exporting all annotations
- updating annotations of type "mask" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "contour" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "shape_features" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- writing annotations of type "reference" with id "a" to "annotations_plates-v1.json"
------------+++ finished pype iteration +++--------------
-------(End with Ctrl+Enter or re-run with Enter)--------
AUTOSHOW
TERMINATE
AUTOSAVE
- nothing to autosave
- no annotation_type selected - returning all annotations
AUTOLOAD
- annotations loaded:
{
"mask": ["a"],
"contour": ["a"],
"shape_features": ["a"]
}
- reference template image loaded from root directory
Stage: add annotation control args
Updating pype config: applying staged changes
------------+++ new pype iteration 2022-05-06 15:08:56 +++--------------
PREPROCESSING
detect_reference
---------------------------------------------------
Reference card found with 254 keypoint matches:
template image has 36.44 pixel per mm.
current image has 35.264 pixel per mm.
= 96.772 %% of template image.
---------------------------------------------------
create_mask
- loaded existing annotation of type "mask" with ID "a": skipping (edit=False)
blur
SEGMENTATION
threshold
- multichannel image supplied, converting to grayscale
- decompose image: using gray channel
- including pixels from 1 drawn masks
- excluding pixels from reference
detect_contour
- loaded existing annotation of type "contour" with ID "a": overwriting (edit=overwrite)
- found 10 contours that match criteria
MEASUREMENT
compute_shape_features
- loaded existing annotation of type "shape_features" with ID "a": overwriting (edit=overwrite)
VISUALIZATION
select_canvas
- raw image
draw_contour
draw_mask
draw_reference
EXPORT
save_canvas
- image saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle3\canvas_plates-v1.jpg (overwritten).
save_annotation
- loading existing annotation file
- no annotation_type selected - exporting all annotations
- updating annotations of type "mask" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "contour" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- updating annotations of type "shape_features" with id "a" in "annotations_plates-v1.json" (overwrite="entry")
- writing annotations of type "reference" with id "a" to "annotations_plates-v1.json"
------------+++ finished pype iteration +++--------------
-------(End with Ctrl+Enter or re-run with Enter)--------
AUTOSHOW
TERMINATE
AUTOSAVE
- nothing to autosave
myproj.collect_results(tag="plates-v1",
files="canvas", #
folder="canvas-v1",
overwrite=True)
Created C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\results\canvas-v1
Search string: ['canvas_plates-v1']
Collected canvas_plates-v1.jpg from 0__stickle1
0__stickle1_canvas_plates-v1.jpg saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\results\canvas-v1\0__stickle1_canvas_plates-v1.jpg.
Collected canvas_plates-v1.jpg from 0__stickle2
0__stickle2_canvas_plates-v1.jpg saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\results\canvas-v1\0__stickle2_canvas_plates-v1.jpg.
Collected canvas_plates-v1.jpg from 0__stickle3
0__stickle3_canvas_plates-v1.jpg saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\results\canvas-v1\0__stickle3_canvas_plates-v1.jpg.