Tutorial 5: Projects#

A central aspect of phenopype is the use of the Project class to efficiently process larger amounts of images. Creating a project object will set up a directory tree in which each folder contains the copy or a link to the original raw image files. Alongside the images to be processed, users can store configuration file, as covered in Tutorial 3 and Tutorial 4.

Once raw images have been added and configuration files are in place, the Pype class can be used within a simple for loop. After all images are processed, the results are stored alongside the raw images and the Pype-configuration files.

Hint:

Anyone with access to the raw images and the configuration files is able to reproduce the results with a few lines of code, making phenopype project directories the perfect format for code sharing and data sharing after publication through online repositories (such as Dryad, Zenodo or OSF).

</div

Task: delineate armour plates (in batch)#

Again we will quantify lateral armor plating in threespine stickleback (Gasterosteus aculeatus), as shown in Tutorial 3, but this time in more than one image. First a project has to be initialized, which will create a root directory to which images can be added. Second, we need to add a Pype configuration file containing the processing instructions. Then we can run image analysis in batch using a for loop.

A) Start project and add images#

A Phenopype project directory can be initialized with the Project class. The phenoype project root folder should be separate from the raw data, e.g. as a folder inside of your main project folder.

4269fa13d0ce47a9affff00e21c516be

Fig 1 Create a phenopype project and organize raw images into separate folders where all relevant data, attributes and results are stored. (Figure from Lürig 2021 [Fig. 3A]).

We will use the images from the tutorials folder (download the tutorials if you have not done so already).

[1]:
import phenopype as pp
import os

os.chdir(r"C:\Users\mluerig\Downloads\phenopype-tutorials-main")

myproj = pp.Project(
    root_dir=r"tutorial_project", ## pick your project directory
    ## overwrite=True,               ## overwrite=True will overwrite the project (after another prompt)
)
--------------------------------------------
Found existing project root directory - loading from:
C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project

Project "tutorial_project" successfully loaded with 3 images
--------------------------------------------

Next step is to add images to the project. You can do so with the add_files method of the created project (a method is an executable function that belongs to an existing object, in this case “myproj). The function offers some flexibility in terms of which files to import. Most important arguments here are include, exclude and filetypes. For example, given the following list of images:

[2]:
os.listdir(r"tutorials/data")
[2]:
['isopods_fish.mp4',
 'stickle1.jpg',
 'stickle2.jpg',
 'stickle3.jpg',
 'stickleback_side.jpg',
 'stickleback_top.jpg']

If we want to import “stickle1”, “stickle2”, and “stickle3”, we can do a combination include and exclude (also prints all other default settings):

[3]:
image_dir = r"tutorials/data"

myproj.add_files(
    image_dir=image_dir,
    include="stickle",       ## can be type "str" or type "list"
    exclude=["side","top"]   ## can be type "str" or type "list"
)
--------------------------------------------
phenopype will search for image files at

C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorials\data

using the following settings:

filetypes: ['jpg', 'JPG', 'jpeg', 'JPEG', 'tif', 'png', 'bmp'], include: stickle, exclude: ['side', 'top'], mode: copy, recursive: False, resize: False, unique: path

Found image stickle1.jpg - 0__stickle1 already exists (overwrite=False)
Found image stickle2.jpg - 0__stickle2 already exists (overwrite=False)
Found image stickle3.jpg - 0__stickle3 already exists (overwrite=False)

Found 3 files
--------------------------------------------

Thre are more settings to add_files: - mode determines whether raw files should be copied to each folder in the Phenopype directory tree (using copy [default]), or just their filepath (using link), which can be useful if data sets contain many or very large images. A third option is mod, which will open the iages and save them again in TIF format. This mode also allows to resize images. - recursive indicates whether only the top directory (False; default), or also all subdirectories (True) should be included in the search. - unique indicates whether files should be unique by their path (filepath [default]) or only by their name (filename) - duplicate files will be skipped.

[4]:
help(pp.Project.add_files)
Help on function add_files in module phenopype.main:

add_files(self, image_dir, filetypes=['jpg', 'JPG', 'jpeg', 'JPEG', 'tif', 'png', 'bmp'], include=[], include_all=True, exclude=[], mode='copy', ext='tif', recursive=False, overwrite=False, resize_factor=1, unique='path', **kwargs)
    Add files to your project from a directory, can look recursively.
    Specify in- or exclude arguments, filetypes, duplicate-action and copy
    or link raw files to save memory on the harddrive. For each found image,
    a folder will be created in the "data" folder within the projects root
    directory. If found images are in subfolders and "recursive==True",
    the respective phenopype directories will be created with
    flattened path as prefix.

    E.g., with "raw_files" as folder with the original image files
    and "phenopype_proj" as rootfolder:

    - raw_files/file.jpg ==> phenopype_proj/data/file.jpg
    - raw_files/subdir1/file.jpg ==> phenopype_proj/data/1__subdir1__file.jpg
    - raw_files/subdir1/subdir2/file.jpg ==> phenopype_proj/data/2__subdir1__subdir2__file.jpg

    Parameters
    ----------
    image_dir: str
        path to directory with images
    filetypes: list or str, optional
        single or multiple string patterns to target files with certain endings.
        "settings.default_filetypes" are configured in settings.py:
        ['jpg', 'JPG', 'jpeg', 'JPEG', 'tif', 'png', 'bmp']
    include: list or str, optional
        single or multiple string patterns to target certain files to include
    include_all (optional): bool,
        either all (True) or any (False) of the provided keywords have to match
    exclude: list or str, optional
        single or multiple string patterns to target certain files to exclude -
        can overrule "include"
    recursive: (optional): bool,
        "False" searches only current directory for valid files; "True" walks
        through all subdirectories
    unique: {"file_path", "filename"}, str, optional:
        how to deal with image duplicates - "file_path" is useful if identically
        named files exist in different subfolders (folder structure will be
        collapsed and goes into the filename), whereas filename will ignore
        all similar named files after their first occurrence.
    mode: {"copy", "mod", "link"} str, optional
        how should the raw files be passed on to the phenopype directory tree:
        "copy" will make a copy of the original file, "mod" will store a
        .tif version of the orginal image that can be resized, and "link"
        will only store the link to the original file location to attributes,
        but not copy the actual file (useful for big files, but the orginal
        location needs always to be available)
    overwrite: {"file", "dir", False} str/bool (optional)
        "file" will overwrite the image file and modify the attributes accordingly,
        "dir" will  overwrite the entire image directory (including all meta-data
        and results!), False will not overwrite anything
    ext: {".tif", ".bmp", ".jpg", ".png"}, str, optional
        file extension for "mod" mode
    resize_factor: float, optional

    kwargs:
        developer options

B) Adding Pype configuration files#

In the next step we prepare the files we added for use with the Pypeclass by addding a configuration file with the add_config method. Instead of adding the functions one by one we can load presets that are appropriate for the given computer vision analysis.

A selection of templates for configuration files to be used by the Pype class can be found in the template section of the docs. They can be freely modified, but need to adhere YAML specifications (see below). Also check the phenopype gallery for inspiration and additional templates.

780475ac751d4cb389b996292c22b761

Fig 2 Create configuration files and store them alongside the raw images. (Figure from Lürig 2021 [Fig. 3B]).

We will use the same template (quickstart-template.yaml) as in Tutorial 3:

[5]:
template = r"C:\Users\mluerig\Downloads\phenopype-quickstart-main\quickstart-template.yaml"
myproj.add_config(
    template_path=template,
    tag="plates-v1",
    overwrite=True,         # overwrite if present in image subdirectory
    # interactive=True,       # modify the template before distributing it
)
- template saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle1\pype_config_plates-v1.yaml (overwritten)
- template saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle2\pype_config_plates-v1.yaml (overwritten)
- template saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle3\pype_config_plates-v1.yaml (overwritten)

Now all images folders contain a configuration file.

Note that we could have modified the first template before distributing it to the image subdirectories - either manually, or with add_config by setting interactive=True.

C) Batch processing#

After adding images and configuration, all is set to process your dataset with high throughput. Using a simple for loop, we then go through all directories one by one. The skip argument will allow to skip files with a given config name you have already analyzed. This allows you to return to the point where you left off.

842fcaf31fdb480b8015c70b87606b54

Fig 3 Apply the Pype class to each folder using a for-loop. Once the Pype class has finished executing all functions from the configuration file, users can decide to either modify the opened configuration file (e.g. either change function parameters or add new functions), which will trigger to run the Pype class again, or to close the GUI window, which will terminate the Pype class instance and save all results to the folder (Figure from Lürig 2021 [Fig. 3C]).

[6]:
for path in myproj.dir_paths:
    pp.Pype(path,
            tag="plates-v1",         ## loads the config file "pype_config_lm.yaml". "lm" gets appended to all results files
            skip=False          ## skip=True will skip over any directories that already contain results files with "lm"
           )
- 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
Stage: add annotation control args
Stage: add annotation control args
Updating pype config: applying staged changes


------------+++ new pype iteration 2022-05-06 15:04:37 +++--------------




PREPROCESSING
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


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
Stage: add annotation control args
Stage: add annotation control args
Updating pype config: applying staged changes


------------+++ new pype iteration 2022-05-06 15:04:46 +++--------------




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


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


------------+++ 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
Stage: add annotation control args
Stage: add annotation control args
Updating pype config: applying staged changes


------------+++ new pype iteration 2022-05-06 15:04:51 +++--------------




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


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


------------+++ finished pype iteration +++--------------
-------(End with Ctrl+Enter or re-run with Enter)--------


AUTOSHOW


TERMINATE

AUTOSAVE
- nothing to autosave

2910e4ce241c44a095a28b90bea2ee6e

Fig 3 Each folder contains all information necessary to reproduce the collected phenopytic data. Ouput from different pype runs can be stored side by side in the same folders (Figure from Lürig 2021 [Fig. 3D]).

D) Collecting results#

After finishing all analyses, you can use the project-method collect_results to copy all results (e.g. the annotation json files or canvas images) to a “results” folder in the root directory.

[7]:
myproj.collect_results(tag="plates-v1",
                       files="annotations", #
                       folder="annotations-v1",
                       overwrite=True)
Search string: ['annotations_plates-v1']
Collected annotations_plates-v1.json from 0__stickle1
0__stickle1_annotations_plates-v1.json saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\results\annotations-v1\0__stickle1_annotations_plates-v1.json (overwritten).
Collected annotations_plates-v1.json from 0__stickle2
0__stickle2_annotations_plates-v1.json saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\results\annotations-v1\0__stickle2_annotations_plates-v1.json (overwritten).
Collected annotations_plates-v1.json from 0__stickle3
0__stickle3_annotations_plates-v1.json saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\results\annotations-v1\0__stickle3_annotations_plates-v1.json (overwritten).

Saving and loading a project#

The Project class does not require a specific save argument, as results, annotations, etc. are saved in the image-specific subfolders in the data-directory.

To load a Project, simply run it on the root path of your project:

[8]:
import phenopype as pp

myproj = pp.Project("tutorial_project")
myproj.dir_paths
--------------------------------------------
Found existing project root directory - loading from:
C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project

Project "tutorial_project" successfully loaded with 3 images
--------------------------------------------
[8]:
['C:\\Users\\mluerig\\Downloads\\phenopype-tutorials-main\\tutorial_project\\data\\0__stickle1',
 'C:\\Users\\mluerig\\Downloads\\phenopype-tutorials-main\\tutorial_project\\data\\0__stickle2',
 'C:\\Users\\mluerig\\Downloads\\phenopype-tutorials-main\\tutorial_project\\data\\0__stickle3']

Adding another configuration#

As mentioned above, it’s possible to have multiple configuration files side by side in phenopype folders. First, download the template repo, and unzip it. Now, for example, if we also want to set some landmarks, we can supply this template:

[9]:
template = r"C:\Users\mluerig\Downloads\phenopype-templates-main\templates\landmarks\landmarks_plain.yaml"

myproj.add_config(
    tag="lm-v1",
    template_path=template,
    overwrite=True,
)
- template saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle1\pype_config_lm-v1.yaml (overwritten)
- template saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle2\pype_config_lm-v1.yaml (overwritten)
- template saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle3\pype_config_lm-v1.yaml (overwritten)

Now simply run another loop:

[10]:
for path in myproj.dir_paths:
    pp.Pype(
        path,
        tag="lm-v1",
    )
- no annotation_type selected - returning all annotations

AUTOLOAD
- annotations loaded:
{
"landmark": ["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:05:05 +++--------------




MEASUREMENT
set_landmark
- loaded existing annotation of type "landmark" with ID "a": skipping (edit=False)


VISUALIZATION
draw_landmark


EXPORT
save_canvas
- image saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle1\canvas_lm-v1.jpg (overwritten).
save_annotation
- loading existing annotation file
- no annotation_type selected - exporting all annotations
- updating annotations of type "landmark" with id "a" in "annotations_lm-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:
{
"landmark": ["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:05:08 +++--------------




MEASUREMENT
set_landmark
- loaded existing annotation of type "landmark" with ID "a": skipping (edit=False)


VISUALIZATION
draw_landmark


EXPORT
save_canvas
- image saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle2\canvas_lm-v1.jpg (overwritten).
save_annotation
- loading existing annotation file
- no annotation_type selected - exporting all annotations
- updating annotations of type "landmark" with id "a" in "annotations_lm-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:
{
"landmark": ["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:05:10 +++--------------




MEASUREMENT
set_landmark
- loaded existing annotation of type "landmark" with ID "a": skipping (edit=False)


VISUALIZATION
draw_landmark


EXPORT
save_canvas
- image saved under C:\Users\mluerig\Downloads\phenopype-tutorials-main\tutorial_project\data\0__stickle3\canvas_lm-v1.jpg (overwritten).
save_annotation
- loading existing annotation file
- no annotation_type selected - exporting all annotations
- updating annotations of type "landmark" with id "a" in "annotations_lm-v1.json" (overwrite="entry")


------------+++ finished pype iteration +++--------------
-------(End with Ctrl+Enter or re-run with Enter)--------


AUTOSHOW


TERMINATE

AUTOSAVE
- nothing to autosave

Note that we added a second template with landmarking steps for the purpose of demonstrating how to have multiple configurations side by side in the image folders, which might also make sense if you want to separate the two work steps. However, it is possible and potentially also more time efficient, to have both, thep plate segmentation step and the landmarking step in one configuration file.

Modify configurations in all subdirectories#

In case you would like to modify your configuration after it has already been distributed, use the edit_config class method. This is a simple string-replacement function that allows you do remove or add elements to all existing configuration files.

For instance, if we wanted to add the landmarking steps to our plates-v1 configuration, we can pecifiy replacement and target strings - they have to exactly match the patterns in the config files, including spaces and indentations. We will modify the template in two places: the measurement, and the visualization step.

[11]:
## "measurement" modification to add `set_landmarks`:

target1 = """    - measurement:
        - compute_shape_features:
            ANNOTATION: {type: morphology, id: a, edit: overwrite}"""
replacement1 = """    - measurement:
        - compute_shape_features:
            ANNOTATION: {type: morphology, id: a, edit: overwrite}
        - set_landmark:
            point_size: 8
            point_colour: lawngreen
            label_size: 2
            label_width: 2"""

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

Now run the loop again - note that since we don’t have to do any new manual annotations (we already set the polygon mask), we can turn off the visual feedback (feedback=False) to let the whole project run from beginning to end without interrupting:

[12]:
for path in myproj.dir_paths:
    pp.Pype(path, tag="plates-v1", feedback=False)
- 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


------------+++ new pype iteration 2022-05-06 15:05:19 +++--------------




PREPROCESSING
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


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




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


------------+++ new pype iteration 2022-05-06 15:05:19 +++--------------




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


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


------------+++ finished pype iteration +++--------------
-------(End with Ctrl+Enter or re-run with Enter)--------




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


------------+++ new pype iteration 2022-05-06 15:05:20 +++--------------




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


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


------------+++ finished pype iteration +++--------------
-------(End with Ctrl+Enter or re-run with Enter)--------




TERMINATE

AUTOSAVE
- nothing to autosave

Move on to Tutorial 6 to learn how to set and detect a project-wide size reference.