Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi ROI #1493

Open
ozgurculfa opened this issue Apr 13, 2024 · 5 comments
Open

Multi ROI #1493

ozgurculfa opened this issue Apr 13, 2024 · 5 comments

Comments

@ozgurculfa
Copy link

Hello Everyone,
Is there any way of doing multi ROI plot with a customized ROI option?

Thanks

@nfahlgren
Copy link
Member

nfahlgren commented Apr 13, 2024

Hi @ozgurculfa, am I understanding correctly that you are looking to use pcv.roi.custom but to create multiple ROIs?

It is possible to create custom placed ROIs (but only circles) with pcv.roi.multi, but not yet possible to have pcv.roi.custom create multiple ROIs.

Technically you could make this work by semi-manually building a multi-ROI object like this:

from plantcv import plantcv as pcv

# Read RGB image
img, imgpath, imgname = pcv.readimage(filename="myimage.png")

# Convert to grayscale
gray_img = pcv.rgb2gray_lab(rgb_img=img, channel="a")

# Threshold to segment
bin_img = pcv.threshold.otsu(gray_img=gray_img, object_type="dark")

# Create empty ROIs object
rois = pcv.Objects()

# Create custom ROI 1 and append to rois
roi = pcv.roi.custom(img=img, vertices=[(338, 578), (591, 589), (580, 804), (354, 804)])
rois.append(contour=roi.contours[0], h=roi.hierarchy[0])

# Create custom ROI 2 and append to rois
roi = pcv.roi.custom(img=img, vertices=[(1632, 1057), (1900, 1078), (1890, 1294), (1637, 1272)])
rois.append(contour=roi.contours[0], h=roi.hierarchy[0])

# Create a labeled mask for the 2 ROIs
lbl_mask, num = pcv.create_labels(mask=bin_img, rois=rois)

Figure 1
Figure 2
Figure 3 (1)
Figure 6 (1)

@ozgurculfa
Copy link
Author

Hi Noah,
Thank you so much for your reply. I was able to get multi roi images finally. But would you be able to tell me how to analyze each roi ? I am trying to get the integral of each roi separately but I was not able to save and load data for that purpose. I appreciate your help.
Thanks again,
Ozgur

@nfahlgren
Copy link
Member

Hi Ozgur,

The built-in analysis methods in PlantCV will all iterate over each ROI, but I think you are looking to store a custom measurement if I understand correctly.

We do not have a user method for using multiple ROIs like that (but it is an interesting idea).

In the meantime, it is possible to use the same method we use for iteration in our analysis functions directly. Here's an example using an extension of the code above:

import numpy as np
from plantcv import plantcv as pcv
from plantcv.plantcv._helpers import _iterate_analysis

# Read RGB image
img, imgpath, imgname = pcv.readimage(filename="myimage.png")

# Convert to grayscale
gray_img = pcv.rgb2gray_lab(rgb_img=img, channel="a")

# Threshold to segment
bin_img = pcv.threshold.otsu(gray_img=gray_img, object_type="dark")

# Create empty ROIs object
rois = pcv.Objects()

# Create custom ROI 1 and append to rois
roi = pcv.roi.custom(img=img, vertices=[(338, 578), (591, 589), (580, 804), (354, 804)])
rois.append(contour=roi.contours[0], h=roi.hierarchy[0])

# Create custom ROI 2 and append to rois
roi = pcv.roi.custom(img=img, vertices=[(1632, 1057), (1900, 1078), (1890, 1294), (1637, 1272)])
rois.append(contour=roi.contours[0], h=roi.hierarchy[0])

# Create a labeled mask for the 2 ROIs
lbl_mask, num = pcv.create_labels(mask=bin_img, rois=rois)

# Create a function to do one or more custom measurements
# The function must have the inputs img, mask, label
def my_func(img, mask, label):
    # Custom measurement example
    px_count = np.count_nonzero(mask)
    # Store the custom measurement
    pcv.outputs.add_observation(sample=label, variable='px_count', trait='pixel count',
                                method='custom', scale='pixels', datatype=int,
                                value=px_count, label='pixels')
    return img

# Apply your custom function to each submask (each ROI region)
outimg = _iterate_analysis(img=img, labeled_mask=lbl_mask, n_labels=num, label=pcv.params.sample_label, function=my_func)

# Print observations just to show it is working
print(pcv.outputs.observations)

# {'default_1': {'px_count': {'trait': 'pixel count',
#   'method': 'custom',
#   'scale': 'pixels',
#   'datatype': "<class 'int'>",
#   'value': 13872,
#   'label': 'pixels'}},
# 'default_2': {'px_count': {'trait': 'pixel count',
#   'method': 'custom',
#   'scale': 'pixels',
#   'datatype': "<class 'int'>",
#   'value': 16876,
#   'label': 'pixels'}}}

@ozgurculfa
Copy link
Author

Hi Noah,
I really appreciate your help and still trying to figure out the same problem. I need to go through each ROI and do some calculations on them. I couldn't quite understand how data is stored. Would you be able to tell me how to access matrix of each roi and extract them so I can manipulate each matrix I get from each roi.
Thanks
Ozgur

@HaleySchuhl
Copy link
Contributor

Hi @ozgurculfa ,

The last step in a PlantCV workflow is pcv.outputs.save_results(filename= imgname + "_results.txt"). The default format is JSON so if you are analyzing images one by one it can be helpful to use outformat = "csv" and then concatenate the results files from all your images. From there you can analyze your resulting data with R or your favorite software.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants