Skip to content

Instantly share code, notes, and snippets.

@AdamDimech
Last active June 18, 2019 23:19
Show Gist options
  • Save AdamDimech/e54fe95f7face972192fbd76fa83bf9a to your computer and use it in GitHub Desktop.
Save AdamDimech/e54fe95f7face972192fbd76fa83bf9a to your computer and use it in GitHub Desktop.
Problem-solving with a PlantCV update
#!/usr/bin/python
import sys, traceback
import cv2
import numpy as np
import argparse
import string
import matplotlib as mpl
# Import PlantCV
from plantcv import plantcv as pcv
### Parse command-line arguments
def options():
parser = argparse.ArgumentParser(description="Imaging processing with opencv")
parser.add_argument("-i", "--image", help="Input image file.", required=True)
parser.add_argument("-o", "--outdir", help="Output directory for image files.", required=False)
parser.add_argument("-r", "--result", help="result file.", required= False )
parser.add_argument("-w", "--writeimg", help="write out images.", default=False, action="store_true")
parser.add_argument("-D", "--debug", help="can be set to 'print' or None (or 'plot' if in jupyter) prints intermediate images.")
args = parser.parse_args()
return args
### Main pipeline
def main():
# Get options
args = options()
pcv.params.debug = args.debug # set debug mode
pcv.params.debug_outdir = args.outdir # set output directory
# Read image
img, path, filename = pcv.readimage(args.image, mode="rgb")
# Rotate image
img = pcv.rotate(img, -90, False)
# Remove obvious area of no interest:
maskeda, box1_img, rect_contour1, hierarchy1 = pcv.rectangle_mask(img, (3750,0), (5500,7000), color="white")
maskedb, box2_img, rect_contour2, hierarchy2 = pcv.rectangle_mask(img, (0,0), (5500,300), color="white")
maskedc, box3_img, rect_contour3, hierarchy3 = pcv.rectangle_mask(img, (0,3200), (5500,3700), color="white")
maskedd, box4_img, rect_contour4, hierarchy4 = pcv.rectangle_mask(img, (0,0), (1400,7000), color="white")
# combine boxes to filter the edges and car out of the photo
bx12_img = pcv.logical_or(box1_img, box2_img)
bx123_img = pcv.logical_or(bx12_img, box3_img)
bx1234_img = pcv.logical_or(bx123_img, box4_img)
# invert this mask and then apply it the masked image.
inv_bx1234_img = pcv.invert(bx1234_img)
img = pcv.apply_mask(img, inv_bx1234_img, 'white')
# Convert RGB to HSV and extract the saturation channel
s = pcv.rgb2gray_hsv(img, 'h')
# Threshold
s_thresh = pcv.threshold.binary(s, 14, 146, 'light')
# Median Blur
s_mblur = pcv.median_blur(s_thresh, 5)
s_cnt = pcv.median_blur(s_thresh, 5)
#gaussian_img = pcv.gaussian_blur(img=s_thresh, ksize=(5, 5), sigmax=0, sigmay=None)
# Convert RGB to LAB and extract the blue channel ('b')
b = pcv.rgb2gray_lab(img, 'b')
# Threshold the blue channel image
b_thresh = pcv.threshold.binary(b, 120, 255, 'dark')
b_cnt = pcv.threshold.binary(b, 120, 255, 'light')
# Fill small objects
b_fill = pcv.fill(b_thresh, 10)
# Remove specs of dirt from the image that will be processed as ROI (4,1 worked well)
b_thresh = pcv.dilate(b_thresh,4,1)
b_cnt = pcv.erode(b_cnt,4,1)
# Join the threshold saturation and blue-yellow images
bs = pcv.logical_or(s_mblur, b_cnt)
# Appy Mask (for VIS images, mask_color='white')
masked = pcv.apply_mask(img, bs, 'white')
# Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
masked_a = pcv.rgb2gray_lab(masked, 'a')
masked_b = pcv.rgb2gray_lab(masked, 'b')
# Threshold the green-magenta and blue images
maskeda_thresh = pcv.threshold.binary(masked_a, 128, 255, 'light')
maskeda_thresh1 = pcv.threshold.binary(masked_a, 135, 255, 'light')
maskedb_thresh = pcv.threshold.binary(masked_b, 126, 255, 'dark')
# Join the thresholded saturation and blue-yellow images (OR)
ab1 = pcv.logical_or(maskeda_thresh, maskedb_thresh)
ab = pcv.logical_or(maskeda_thresh1, ab1)
xor_img = pcv.logical_xor(maskeda_thresh, maskedb_thresh)
# Fill small objects (reduce image noise)
ab_fill = pcv.fill(ab, 2)
# Apply mask (for VIS images, mask_color=white)
masked2 = pcv.apply_mask(masked, ab_fill, 'white')
# Identify objects
id_objects, obj_hierarchy = pcv.find_objects(masked2, ab_fill)
# Define the region of interest (ROI)
roi1, roi_hierarchy= pcv.roi.rectangle(x=1450, y=250, h=2950, w=2350, img=masked2)
# Decide which objects to keep
#roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img, 'cutto', roi1, roi_hierarchy, id_objects, obj_hierarchy)
roi_objects, hierarchy3, mask, obj_area = pcv.roi_objects(img, roi1, roi_hierarchy, id_objects, obj_hierarchy, roi_type='partial')
# Object combine kept objects
obj, mask = pcv.object_composition(img, roi_objects, hierarchy3)
############### Analysis ################
outfile=False
if args.writeimg == True:
outfile = args.outdir + "/" + filename
# Find shape properties, output shape image (optional)
shape_imgs = pcv.analyze_object(img, obj, mask)
# Shape properties relative to user boundary line (optional)
boundary_img1 = pcv.analyze_bound_horizontal(img, obj, mask, 1680)
# Determine color properties: Histograms, Color Slices, output color analyzed histogram (optional)
# color_histogram = pcv.analyze_color(img, kept_mask, 'all')
# Pseudocolor the grayscale image
pseudocolored_img = pcv.visualize.pseudocolor(gray_img=s, obj=None, mask=mask, axes=True, colorbar=True, cmap='jet')
# Old
#pseudocolored_img = pcv.analyze_color(img, mask, 256, hist_plot_type=None)
# Write shape and color data to results file
pcv.print_results(filename=args.result)
if __name__ == '__main__':
main()
# End message
print("Complete")
Traceback (most recent call last):
File "C:/Path/To/plantcv_pipeline.py", line 142, in <module>
main()
File "C:/Path/To/plantcv_pipeline.py", line 133, in main
pseudocolored_img = pcv.visualize.pseudocolor(gray_img=s, obj=None, mask=mask, axes=True, colorbar=True, cmap='jet')
AttributeError: module 'plantcv.plantcv' has no attribute 'visualize'
Processing results...
Traceback (most recent call last):
File "C:\Path\To\plantcv_pipeline.py", line 262, in <module>
main()
File "C:\Path\To\plantcv_pipeline.py", line 247, in main
pcvp.process_results(valid_meta=args.valid_meta, job_dir=args.jobdir, json_file=args.json)
File "C:\Path\To\plantcv_pipeline.py", line 42, in process_results
obs = json.load(results)
File "C:\Anaconda\envs\plantcv\lib\json\__init__.py", line 299, in load
parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
File "C:\Anaconda\envs\plantcv\lib\json\__init__.py", line 354, in loads
return _default_decoder.decode(s)
File "C:\Anaconda\envs\plantcv\lib\json\decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Anaconda\envs\plantcv\lib\json\decoder.py", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment