For multi-plant workflows, images with multiple plants are processed. Individual pictures for each plant can be saved, allowing a secondary workflow (see VIS tutorial for example) to be used, or individual plants can be analyzed within the same workflow by iterating over each in a loop. The challenge of multi-plant processing is that a single plant can be composed of several contours, therefore contours need to be sorted and clustered together in some way. There are several functions that help with multi-plant image processing. First, the current clustering functions work by asking the user to provide an approximation of the number of desired 'rows' and 'columns' that they would like to split the image into. There does not need to be a plant in each spot, but the grid is used as an approximate region to cluster contours within. The rotation and shift functions allow the image to be moved to optimize accurate clustering. Major assumptions that are made are that plants grow but that the imaging position does not change drastically. Also, the clustering functions will not work properly once plants start overlapping, since contours would also start overlapping.
To run a multi-plant workflow over a single VIS image there are two required inputs:
Image processing will work with adjustments if images are well lit and free of background that is similar in color to plant material.
2. Output directory: If debug mode is set to 'print' output images from each step are produced.
# Import libraries
import numpy as np
from plantcv import plantcv as pcv
class options:
def __init__(self):
self.image = "./img/original_image.jpg"
self.debug = "plot"
self.writeimg= False
self.result = "multi_plant_tutorial_results.json"
self.outdir = "." # Store the output to the current directory
# Get options
args = options()
# Set debug to the global parameter
pcv.params.debug = args.debug
# Read image
# Inputs:
# filename - Image file to be read in
# mode - How to read in the image; either 'native' (default), 'rgb', 'gray', or 'csv'
img, path, filename = pcv.readimage(filename=args.image)
# Check if this is a night image, for some of these dataset's images were captured
# at night, even if nothing is visible. To make sure that images are not taken at
# night we check that the image isn't mostly dark (0=black, 255=white).
# if it is a night image it throws a fatal error and stops the workflow.
if np.average(img) < 50:
pcv.fatal_error("Night Image")
else:
pass
# Normalize the white color so you can later
# compare color between images.
# Inputs:
# img = image object, RGB color space
# roi = region for white reference, if none uses the whole image,
# otherwise (x position, y position, box width, box height)
# white balance image based on white toughspot
img1 = pcv.white_balance(img, roi=(52,100,20,20))