def main(): # Get options args = options() # Read image (converting fmax and track to 8 bit just to create a mask, use 16-bit for all the math) mask, path, filename = pcv.readimage(args.fmax) #mask = cv2.imread(args.fmax) track = cv2.imread(args.track) mask1, mask2, mask3= cv2.split(mask) # Pipeline step device = 0 # Mask pesky track autofluor device, track1= pcv.rgb2gray_hsv(track, 'v', device, args.debug) device, track_thresh = pcv.binary_threshold(track1, 0, 255, 'light', device, args.debug) device, track_inv=pcv.invert(track_thresh, device, args.debug) device, track_masked = pcv.apply_mask(mask1, track_inv, 'black', device, args.debug) # Threshold the Saturation image device, fmax_thresh = pcv.binary_threshold(track_masked, 20, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(fmax_thresh, 0, device, args.debug) device, s_cnt = pcv.median_blur(fmax_thresh, 0, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 5, device, args.debug) device, sfill_cnt = pcv.fill(s_mblur, s_cnt, 5, device, args.debug) # Identify objects device, id_objects,obj_hierarchy = pcv.find_objects(mask, sfill_cnt, device, args.debug) # Define ROI device, roi1, roi_hierarchy= pcv.define_roi(mask,'circle', device, None, 'default', args.debug,True, 0,0,-100,-100) # Decide which objects to keep device,roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(mask,'partial',roi1,roi_hierarchy,id_objects,obj_hierarchy,device, args.debug) # Object combine kept objects device, obj, masked = pcv.object_composition(mask, roi_objects, hierarchy3, device, args.debug) ################ Analysis ################ # Find shape properties, output shape image (optional) device, shape_header,shape_data,shape_img = pcv.analyze_object(mask, args.fmax, obj, masked, device,args.debug, args.outdir+'/'+filename) # Fluorescence Measurement (read in 16-bit images) fdark=cv2.imread(args.fdark, -1) fmin=cv2.imread(args.fmin, -1) fmax=cv2.imread(args.fmax, -1) device, fvfm_header, fvfm_data=pcv.fluor_fvfm(fdark,fmin,fmax,kept_mask, device, args.outdir+'/'+filename, 1000, args.debug) # Output shape and color data pcv.print_results(args.fmax, shape_header, shape_data) pcv.print_results(args.fmax, fvfm_header, fvfm_data)
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) brass_mask = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 49, 255, 'light', device, args.debug) #Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) #Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, s_mblur, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta device, soil_a = pcv.rgb2gray_lab(masked, 'a', device, args.debug) # # Threshold the green-magenta device, soila_thresh = pcv.binary_threshold(soil_a, 133, 255, 'light', device, args.debug) device, soila_cnt = pcv.binary_threshold(soil_a, 133, 255, 'light', device, args.debug) # # Fill small objects device, soil_fill = pcv.fill(soila_thresh, soila_cnt, 200, device, args.debug) # # Median Filter device, soil_mblur = pcv.median_blur(soil_fill, 13, device, args.debug) device, soil_cnt = pcv.median_blur(soil_fill, 13, device, args.debug) # # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_mblur, soil_cnt, 'white', device, args.debug) # # Identify objects device, id_objects,obj_hierarchy = pcv.find_objects(masked2, soil_cnt, device, args.debug) # # Define ROI device, roi1, roi_hierarchy= pcv.define_roi(img,'rectangle', device, None, 'default', args.debug,True, 400,400,-400,-400) # # Decide which objects to keep device,roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img,'partial',roi1,roi_hierarchy,id_objects,obj_hierarchy,device, args.debug) # # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) # ############## Analysis ################ # Find shape properties, output shape image (optional) device, shape_header,shape_data,shape_img = pcv.analyze_object(img, args.image, obj, mask, device,args.debug,args.outdir+'/'+filename) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header,color_data,norm_slice= pcv.analyze_color(img, args.image, mask, 256, device, args.debug,'all','rgb','v','img',300,args.outdir+'/'+filename) # Output shape and color data pcv.print_results(args.image, shape_header, shape_data) pcv.print_results(args.image, color_header, color_data)
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) brass_mask = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 49, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 150, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 100, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs,'white', device, args.debug) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, 'v', device, args.debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, 'light', device, args.debug) device, brass_inv=pcv.invert(brass_thresh, device, args.debug) device, brass_masked = pcv.apply_mask(masked, brass_inv, 'white', device, args.debug) # Further mask soil and car device, masked_a = pcv.rgb2gray_lab(brass_masked, 'a', device, args.debug) device, soil_car = pcv.binary_threshold(masked_a, 128, 255, 'dark', device, args.debug) device, soil_masked = pcv.apply_mask(brass_masked, soil_car, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, soil_a = pcv.rgb2gray_lab(soil_masked, 'a', device, args.debug) device, soil_b = pcv.rgb2gray_lab(soil_masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, soila_thresh = pcv.binary_threshold(soil_a, 118, 255, 'dark', device, args.debug) device, soilb_thresh = pcv.binary_threshold(soil_b, 155, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, soil_ab = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) device, soil_ab_cnt = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) # Fill small objects device, soil_fill = pcv.fill(soil_ab, soil_ab_cnt, 75, device, args.debug) # Median Filter device, soil_mblur = pcv.median_blur(soil_fill, 5, device, args.debug) device, soil_cnt = pcv.median_blur(soil_fill, 5, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_masked, soil_cnt, 'white', device, args.debug) # Identify objects device, id_objects,obj_hierarchy = pcv.find_objects(masked2, soil_cnt, device, args.debug) # Define ROI device, roi1, roi_hierarchy= pcv.define_roi(img,'circle', device, None, 'default', args.debug,True, 0,0,-50,-50) # Decide which objects to keep device,roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img,'partial',roi1,roi_hierarchy,id_objects,obj_hierarchy,device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## Analysis ################ # Find shape properties, output shape image (optional) device, shape_header,shape_data,shape_img = pcv.analyze_object(img, args.image, obj, mask, device,args.debug,args.outdir+'/'+filename) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header,color_data,color_img= pcv.analyze_color(img, args.image, kept_mask, 256, device, args.debug,'all','v','img',300,args.outdir+'/'+filename) # Output shape and color data pcv.print_results(args.image, shape_header, shape_data) pcv.print_results(args.image, color_header, color_data)
def process_tv_images_core(vis_id, vis_img, nir_id, nir_rgb, nir_cv2, brass_mask, traits, debug=None): device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(vis_img, 's', device, debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 75, 255, 'light', device, debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 150, device, debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(vis_img, 'b', device, debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 100, device, debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(vis_img, bs, 'white', device, debug) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, 'v', device, debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, 'light', device, debug) device, brass_inv = pcv.invert(brass_thresh, device, debug) device, brass_masked = pcv.apply_mask(masked, brass_inv, 'white', device, debug) # Further mask soil and car device, masked_a = pcv.rgb2gray_lab(brass_masked, 'a', device, debug) device, soil_car1 = pcv.binary_threshold(masked_a, 128, 255, 'dark', device, debug) device, soil_car2 = pcv.binary_threshold(masked_a, 128, 255, 'light', device, debug) device, soil_car = pcv.logical_or(soil_car1, soil_car2, device, debug) device, soil_masked = pcv.apply_mask(brass_masked, soil_car, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, soil_a = pcv.rgb2gray_lab(soil_masked, 'a', device, debug) device, soil_b = pcv.rgb2gray_lab(soil_masked, 'b', device, debug) # Threshold the green-magenta and blue images device, soila_thresh = pcv.binary_threshold(soil_a, 124, 255, 'dark', device, debug) device, soilb_thresh = pcv.binary_threshold(soil_b, 148, 255, 'light', device, debug) # Join the thresholded saturation and blue-yellow images (OR) device, soil_ab = pcv.logical_or(soila_thresh, soilb_thresh, device, debug) device, soil_ab_cnt = pcv.logical_or(soila_thresh, soilb_thresh, device, debug) # Fill small objects device, soil_cnt = pcv.fill(soil_ab, soil_ab_cnt, 300, device, debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_masked, soil_cnt, 'white', device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, soil_cnt, device, debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(vis_img, 'rectangle', device, None, 'default', debug, True, 600, 450, -600, -350) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(vis_img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects device, obj, mask = pcv.object_composition(vis_img, roi_objects, hierarchy3, device, debug) # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object(vis_img, vis_id, obj, mask, device, debug) # Determine color properties device, color_header, color_data, color_img = pcv.analyze_color(vis_img, vis_id, mask, 256, device, debug, None, 'v', 'img', 300) # Output shape and color data vis_traits = {} for i in range(1, len(shape_header)): vis_traits[shape_header[i]] = shape_data[i] for i in range(2, len(color_header)): vis_traits[color_header[i]] = serialize_color_data(color_data[i]) ############################# Use VIS image mask for NIR image######################### # Flip mask device, f_mask = pcv.flip(mask, "horizontal", device, debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.116148, 0.116148, device, debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir_rgb, nmask, device, 15, 5, "top", "right", debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(nir_rgb, newmask, device, debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition(nir_rgb, nir_objects, nir_hierarchy, device, debug) ####################################### Analysis ############################################# device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity(nir_cv2, nir_id, nir_combinedmask, 256, device, False, debug) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object(nir_cv2, nir_id, nir_combined, nir_combinedmask, device, debug) nir_traits = {} for i in range(1, len(nshape_header)): nir_traits[nshape_header[i]] = nshape_data[i] for i in range(2, len(nhist_header)): nir_traits[nhist_header[i]] = serialize_color_data(nhist_data[i]) # Add data to traits table traits['tv_area'] = vis_traits['area'] return [vis_traits, nir_traits]
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) #roi = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # Fill small objects #device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) # Fill small objects #device, b_fill = pcv.fill(b_thresh, b_cnt, 150, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, args.debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, 'dark', device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small objects device, ab_fill = pcv.fill(ab, ab_cnt, 200, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(masked, ab_fill, 'white', device, args.debug) # Select area with black bars and find overlapping plant material device, roi1, roi_hierarchy1 = pcv.define_roi(masked2, 'rectangle', device, None, 'default', args.debug, True, 0, 0, -1900, 0) device, id_objects1, obj_hierarchy1 = pcv.find_objects( masked2, ab_fill, device, args.debug) device, roi_objects1, hierarchy1, kept_mask1, obj_area1 = pcv.roi_objects( masked2, 'cutto', roi1, roi_hierarchy1, id_objects1, obj_hierarchy1, device, args.debug) device, masked3 = pcv.apply_mask(masked2, kept_mask1, 'white', device, args.debug) device, masked_a1 = pcv.rgb2gray_lab(masked3, 'a', device, args.debug) device, masked_b1 = pcv.rgb2gray_lab(masked3, 'b', device, args.debug) device, maskeda_thresh1 = pcv.binary_threshold(masked_a1, 122, 255, 'dark', device, args.debug) device, maskedb_thresh1 = pcv.binary_threshold(masked_b1, 170, 255, 'light', device, args.debug) device, ab1 = pcv.logical_or(maskeda_thresh1, maskedb_thresh1, device, args.debug) device, ab_cnt1 = pcv.logical_or(maskeda_thresh1, maskedb_thresh1, device, args.debug) device, ab_fill1 = pcv.fill(ab1, ab_cnt1, 300, device, args.debug) device, roi2, roi_hierarchy2 = pcv.define_roi(masked2, 'rectangle', device, None, 'default', args.debug, True, 1900, 0, 0, 0) device, id_objects2, obj_hierarchy2 = pcv.find_objects( masked2, ab_fill, device, args.debug) device, roi_objects2, hierarchy2, kept_mask2, obj_area2 = pcv.roi_objects( masked2, 'cutto', roi2, roi_hierarchy2, id_objects2, obj_hierarchy2, device, args.debug) device, masked4 = pcv.apply_mask(masked2, kept_mask2, 'white', device, args.debug) device, masked_a2 = pcv.rgb2gray_lab(masked4, 'a', device, args.debug) device, masked_b2 = pcv.rgb2gray_lab(masked4, 'b', device, args.debug) device, maskeda_thresh2 = pcv.binary_threshold(masked_a2, 122, 255, 'dark', device, args.debug) device, maskedb_thresh2 = pcv.binary_threshold(masked_b2, 170, 255, 'light', device, args.debug) device, ab2 = pcv.logical_or(maskeda_thresh2, maskedb_thresh2, device, args.debug) device, ab_cnt2 = pcv.logical_or(maskeda_thresh2, maskedb_thresh2, device, args.debug) device, ab_fill2 = pcv.fill(ab2, ab_cnt2, 200, device, args.debug) device, ab_cnt3 = pcv.logical_or(ab_fill1, ab_fill2, device, args.debug) device, masked3 = pcv.apply_mask(masked2, ab_cnt3, 'white', device, args.debug) # Identify objects device, id_objects3, obj_hierarchy3 = pcv.find_objects( masked2, ab_fill, device, args.debug) # Define ROI device, roi3, roi_hierarchy3 = pcv.define_roi(masked2, 'rectangle', device, None, 'default', args.debug, True, 525, 0, -500, -900) # Decide which objects to keep and combine with objects overlapping with black bars device, roi_objects3, hierarchy3, kept_mask3, obj_area1 = pcv.roi_objects( img, 'cutto', roi3, roi_hierarchy3, id_objects3, obj_hierarchy3, device, args.debug) device, kept_mask4_1 = pcv.logical_or(ab_cnt3, kept_mask3, device, args.debug) device, kept_cnt = pcv.logical_or(ab_cnt3, kept_mask3, device, args.debug) device, kept_mask4 = pcv.fill(kept_mask4_1, kept_cnt, 200, device, args.debug) device, masked5 = pcv.apply_mask(masked2, kept_mask4, 'white', device, args.debug) device, id_objects4, obj_hierarchy4 = pcv.find_objects( masked5, kept_mask4, device, args.debug) device, roi4, roi_hierarchy4 = pcv.define_roi(masked2, 'rectangle', device, None, 'default', args.debug, False, 0, 0, 0, 0) device, roi_objects4, hierarchy4, kept_mask4, obj_area = pcv.roi_objects( img, 'partial', roi4, roi_hierarchy4, id_objects4, obj_hierarchy4, device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects4, hierarchy4, device, args.debug) ############## Analysis ################ # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, args.outdir + '/' + filename) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound( img, args.image, obj, mask, 950, device, args.debug, args.outdir + '/' + filename) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, norm_slice = pcv.analyze_color( img, args.image, kept_mask4, 256, device, args.debug, 'all', 'rgb', 'v', 'img', 300, args.outdir + '/' + filename) # Output shape and color data pcv.print_results(args.image, shape_header, shape_data) pcv.print_results(args.image, color_header, color_data) pcv.print_results(args.image, boundary_header, boundary_data)
def main(): # Get options args = options() # Read image device = 0 img = cv2.imread(args.image, flags=0) path, img_name = os.path.split(args.image) # Read in image which is average of average of backgrounds img_bkgrd = cv2.imread( "/home/mgehan/LemnaTec/plantcv/masks/nir_tv/background_nir_z3500.png", flags=0) # NIR images for burnin2 are up-side down. This may be fixed in later experiments img = ndimage.rotate(img, 0) img_bkgrd = ndimage.rotate(img_bkgrd, 0) # Subtract the image from the image background to make the plant more prominent device, bkg_sub_img = pcv.image_subtract(img, img_bkgrd, device, args.debug) if args.debug: pcv.plot_hist(bkg_sub_img, 'bkg_sub_img') device, bkg_sub_thres_img = pcv.binary_threshold(bkg_sub_img, 150, 255, 'dark', device, args.debug) bkg_sub_thres_img = cv2.inRange(bkg_sub_img, 50, 190) if args.debug: cv2.imwrite('bkgrd_sub_thres.png', bkg_sub_thres_img) #device, bkg_sub_thres_img = pcv.binary_threshold_2_sided(img_bkgrd, 50, 190, device, args.debug) # if a region of interest is specified read it in roi = cv2.imread(args.roi) # Start by examining the distribution of pixel intensity values if args.debug: pcv.plot_hist(img, 'hist_img') # Will intensity transformation enhance your ability to isolate object of interest by thesholding? device, he_img = pcv.HistEqualization(img, device, args.debug) if args.debug: pcv.plot_hist(he_img, 'hist_img_he') # Laplace filtering (identify edges based on 2nd derivative) device, lp_img = pcv.laplace_filter(img, 1, 1, device, args.debug) if args.debug: pcv.plot_hist(lp_img, 'hist_lp') # Lapacian image sharpening, this step will enhance the darkness of the edges detected device, lp_shrp_img = pcv.image_subtract(img, lp_img, device, args.debug) if args.debug: pcv.plot_hist(lp_shrp_img, 'hist_lp_shrp') # Sobel filtering # 1st derivative sobel filtering along horizontal axis, kernel = 1, unscaled) device, sbx_img = pcv.sobel_filter(img, 1, 0, 1, 1, device, args.debug) if args.debug: pcv.plot_hist(sbx_img, 'hist_sbx') # 1st derivative sobel filtering along vertical axis, kernel = 1, unscaled) device, sby_img = pcv.sobel_filter(img, 0, 1, 1, 1, device, args.debug) if args.debug: pcv.plot_hist(sby_img, 'hist_sby') # Combine the effects of both x and y filters through matrix addition # This will capture edges identified within each plane and emphesize edges found in both images device, sb_img = pcv.image_add(sbx_img, sby_img, device, args.debug) if args.debug: pcv.plot_hist(sb_img, 'hist_sb_comb_img') # Use a lowpass (blurring) filter to smooth sobel image device, mblur_img = pcv.median_blur(sb_img, 1, device, args.debug) device, mblur_invert_img = pcv.invert(mblur_img, device, args.debug) # combine the smoothed sobel image with the laplacian sharpened image # combines the best features of both methods as described in "Digital Image Processing" by Gonzalez and Woods pg. 169 device, edge_shrp_img = pcv.image_add(mblur_invert_img, lp_shrp_img, device, args.debug) if args.debug: pcv.plot_hist(edge_shrp_img, 'hist_edge_shrp_img') # Perform thresholding to generate a binary image device, tr_es_img = pcv.binary_threshold(edge_shrp_img, 150, 255, 'dark', device, args.debug) # Prepare a few small kernels for morphological filtering kern = np.zeros((3, 3), dtype=np.uint8) kern1 = np.copy(kern) kern1[1, 1:3] = 1 kern2 = np.copy(kern) kern2[1, 0:2] = 1 kern3 = np.copy(kern) kern3[0:2, 1] = 1 kern4 = np.copy(kern) kern4[1:3, 1] = 1 # Prepare a larger kernel for dilation kern[1, 0:3] = 1 kern[0:3, 1] = 1 # Perform erosion with 4 small kernels device, e1_img = pcv.erode(tr_es_img, kern1, 1, device, args.debug) device, e2_img = pcv.erode(tr_es_img, kern2, 1, device, args.debug) device, e3_img = pcv.erode(tr_es_img, kern3, 1, device, args.debug) device, e4_img = pcv.erode(tr_es_img, kern4, 1, device, args.debug) # Combine eroded images device, c12_img = pcv.logical_or(e1_img, e2_img, device, args.debug) device, c123_img = pcv.logical_or(c12_img, e3_img, device, args.debug) device, c1234_img = pcv.logical_or(c123_img, e4_img, device, args.debug) # Perform dilation # device, dil_img = pcv.dilate(c1234_img, kern, 1, device, args.debug) device, comb_img = pcv.logical_or(c1234_img, bkg_sub_thres_img, device, args.debug) # Get masked image # The dilated image may contain some pixels which are not plant device, masked_erd = pcv.apply_mask(img, comb_img, 'black', device, args.debug) # device, masked_erd_dil = pcv.apply_mask(img, dil_img, 'black', device, args.debug) # Need to remove the edges of the image, we did that by generating a set of rectangles to mask the edges # img is (254 X 320) # mask for the bottom of the image device, box1_img, rect_contour1, hierarchy1 = pcv.rectangle_mask( img, (75, 212), (250, 252), device, args.debug) # mask for the left side of the image device, box2_img, rect_contour2, hierarchy2 = pcv.rectangle_mask( img, (1, 1), (75, 252), device, args.debug) # mask for the right side of the image device, box3_img, rect_contour3, hierarchy3 = pcv.rectangle_mask( img, (245, 1), (318, 252), device, args.debug) # mask the edges device, box4_img, rect_contour4, hierarchy4 = pcv.border_mask( img, (1, 1), (318, 252), device, args.debug) # combine boxes to filter the edges and car out of the photo device, bx12_img = pcv.logical_or(box1_img, box2_img, device, args.debug) device, bx123_img = pcv.logical_or(bx12_img, box3_img, device, args.debug) device, bx1234_img = pcv.logical_or(bx123_img, box4_img, device, args.debug) device, inv_bx1234_img = pcv.invert(bx1234_img, device, args.debug) # Make a ROI around the plant, include connected objects # Apply the box mask to the image # device, masked_img = pcv.apply_mask(masked_erd_dil, inv_bx1234_img, 'black', device, args.debug) device, edge_masked_img = pcv.apply_mask(masked_erd, inv_bx1234_img, 'black', device, args.debug) device, roi_img, roi_contour, roi_hierarchy = pcv.rectangle_mask( img, (50, 50), (280, 215), device, args.debug) plant_objects, plant_hierarchy = cv2.findContours(edge_masked_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) device, roi_objects, hierarchy5, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi_contour, roi_hierarchy, plant_objects, plant_hierarchy, device, args.debug) # Apply the box mask to the image device, masked_img = pcv.apply_mask(kept_mask, inv_bx1234_img, 'black', device, args.debug) rgb = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) # Generate a binary to send to the analysis function device, mask = pcv.binary_threshold(masked_img, 1, 255, 'light', device, args.debug) mask3d = np.copy(mask) plant_objects_2, plant_hierarchy_2 = cv2.findContours( mask3d, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) device, o, m = pcv.object_composition(rgb, roi_objects, hierarchy5, device, args.debug) ### Analysis ### device, hist_header, hist_data, h_norm = pcv.analyze_NIR_intensity( img, args.image, mask, 256, device, args.debug, args.outdir + '/' + img_name) device, shape_header, shape_data, ori_img = pcv.analyze_object( rgb, args.image, o, m, device, args.debug, args.outdir + '/' + img_name) pcv.print_results(args.image, hist_header, hist_data) pcv.print_results(args.image, shape_header, shape_data)
def process_tv_images(session, url, vis_id, nir_id, traits, debug=False): """Process top-view images. Inputs: session = requests session object url = Clowder URL vis_id = The Clowder ID of an RGB image nir_img = The Clowder ID of an NIR grayscale image traits = traits table (dictionary) debug = None, print, or plot. Print = save to file, Plot = print to screen. :param session: requests session object :param url: str :param vis_id: str :param nir_id: str :param traits: dict :param debug: str :return traits: dict """ # Read VIS image from Clowder vis_r = session.get(posixpath.join(url, "api/files", vis_id), stream=True) img_array = np.asarray(bytearray(vis_r.content), dtype="uint8") img = cv2.imdecode(img_array, -1) # Read the VIS top-view image mask for zoom = 1 from Clowder mask_r = session.get(posixpath.join(url, "api/files/57451b28e4b0efbe2dc3d4d5"), stream=True) mask_array = np.asarray(bytearray(mask_r.content), dtype="uint8") brass_mask = cv2.imdecode(mask_array, -1) device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 75, 255, 'light', device, debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 150, device, debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 100, device, debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, debug) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, 'v', device, debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, 'light', device, debug) device, brass_inv = pcv.invert(brass_thresh, device, debug) device, brass_masked = pcv.apply_mask(masked, brass_inv, 'white', device, debug) # Further mask soil and car device, masked_a = pcv.rgb2gray_lab(brass_masked, 'a', device, debug) device, soil_car1 = pcv.binary_threshold(masked_a, 128, 255, 'dark', device, debug) device, soil_car2 = pcv.binary_threshold(masked_a, 128, 255, 'light', device, debug) device, soil_car = pcv.logical_or(soil_car1, soil_car2, device, debug) device, soil_masked = pcv.apply_mask(brass_masked, soil_car, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, soil_a = pcv.rgb2gray_lab(soil_masked, 'a', device, debug) device, soil_b = pcv.rgb2gray_lab(soil_masked, 'b', device, debug) # Threshold the green-magenta and blue images device, soila_thresh = pcv.binary_threshold(soil_a, 124, 255, 'dark', device, debug) device, soilb_thresh = pcv.binary_threshold(soil_b, 148, 255, 'light', device, debug) # Join the thresholded saturation and blue-yellow images (OR) device, soil_ab = pcv.logical_or(soila_thresh, soilb_thresh, device, debug) device, soil_ab_cnt = pcv.logical_or(soila_thresh, soilb_thresh, device, debug) # Fill small objects device, soil_cnt = pcv.fill(soil_ab, soil_ab_cnt, 300, device, debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_masked, soil_cnt, 'white', device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, soil_cnt, device, debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(img, 'rectangle', device, None, 'default', debug, True, 600, 450, -600, -350) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, debug) # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object(img, vis_id, obj, mask, device, debug) # Determine color properties device, color_header, color_data, color_img = pcv.analyze_color(img, vis_id, mask, 256, device, debug, None, 'v', 'img', 300) # Output shape and color data vis_traits = {} for i in range(1, len(shape_header)): vis_traits[shape_header[i]] = shape_data[i] for i in range(2, len(color_header)): vis_traits[color_header[i]] = serialize_color_data(color_data[i]) #print(vis_traits) add_plantcv_metadata(session, url, vis_id, vis_traits) ############################# Use VIS image mask for NIR image######################### # Read NIR image from Clowder nir_r = session.get(posixpath.join(url, "api/files", nir_id), stream=True) nir_array = np.asarray(bytearray(nir_r.content), dtype="uint8") nir = cv2.imdecode(nir_array, -1) nir_rgb = cv2.cvtColor(nir, cv2.COLOR_GRAY2BGR) # Flip mask device, f_mask = pcv.flip(mask, "horizontal", device, debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.116148, 0.116148, device, debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir_rgb, nmask, device, 15, 5, "top", "right", debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(nir_rgb, newmask, device, debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition(nir_rgb, nir_objects, nir_hierarchy, device, debug) ####################################### Analysis ############################################# device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity(nir, nir_id, nir_combinedmask, 256, device, False, debug) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object(nir, nir_id, nir_combined, nir_combinedmask, device, debug) nir_traits = {} for i in range(1, len(nshape_header)): nir_traits[nshape_header[i]] = nshape_data[i] for i in range(2, len(nhist_header)): nir_traits[nhist_header[i]] = serialize_color_data(nhist_data[i]) #print(nir_traits) add_plantcv_metadata(session, url, nir_id, nir_traits) # Add data to traits table traits['tv_area'] = vis_traits['area'] return traits
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) brass_mask = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, "s", device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 49, 255, "light", device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 150, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, "b", device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, "light", device, args.debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, "light", device, args.debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 150, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, "white", device, args.debug) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, "v", device, args.debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, "light", device, args.debug) device, brass_inv = pcv.invert(brass_thresh, device, args.debug) device, brass_masked = pcv.apply_mask(masked, brass_inv, "white", device, args.debug) # Further mask soil and car device, masked_a = pcv.rgb2gray_lab(brass_masked, "a", device, args.debug) device, soil_car1 = pcv.binary_threshold(masked_a, 128, 255, "dark", device, args.debug) device, soil_car2 = pcv.binary_threshold(masked_a, 128, 255, "light", device, args.debug) device, soil_car = pcv.logical_or(soil_car1, soil_car2, device, args.debug) device, soil_masked = pcv.apply_mask(brass_masked, soil_car, "white", device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, soil_a = pcv.rgb2gray_lab(soil_masked, "a", device, args.debug) device, soil_b = pcv.rgb2gray_lab(soil_masked, "b", device, args.debug) # Threshold the green-magenta and blue images device, soila_thresh = pcv.binary_threshold(soil_a, 124, 255, "dark", device, args.debug) device, soilb_thresh = pcv.binary_threshold(soil_b, 148, 255, "light", device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, soil_ab = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) device, soil_ab_cnt = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) # Fill small objects device, soil_cnt = pcv.fill(soil_ab, soil_ab_cnt, 250, device, args.debug) # Median Filter # device, soil_mblur = pcv.median_blur(soil_fill, 5, device, args.debug) # device, soil_cnt = pcv.median_blur(soil_fill, 5, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_masked, soil_cnt, "white", device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, soil_cnt, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi( img, "rectangle", device, None, "default", args.debug, True, 600, 450, -600, -350 ) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, "partial", roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug ) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## VIS Analysis ################ outfile = False if args.writeimg == True: outfile = args.outdir + "/" + filename # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, outfile ) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( img, args.image, mask, 256, device, args.debug, None, "v", "img", 300, outfile ) # Output shape and color data result = open(args.result, "a") result.write("\t".join(map(str, shape_header))) result.write("\n") result.write("\t".join(map(str, shape_data))) result.write("\n") for row in shape_img: result.write("\t".join(map(str, row))) result.write("\n") result.write("\t".join(map(str, color_header))) result.write("\n") result.write("\t".join(map(str, color_data))) result.write("\n") for row in color_img: result.write("\t".join(map(str, row))) result.write("\n")
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) brass_mask = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 49, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 150, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 150, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, 'v', device, args.debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, 'light', device, args.debug) device, brass_inv = pcv.invert(brass_thresh, device, args.debug) device, brass_masked = pcv.apply_mask(masked, brass_inv, 'white', device, args.debug) # Further mask soil and car device, masked_a = pcv.rgb2gray_lab(brass_masked, 'a', device, args.debug) device, soil_car = pcv.binary_threshold(masked_a, 128, 255, 'dark', device, args.debug) device, soil_masked = pcv.apply_mask(brass_masked, soil_car, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, soil_a = pcv.rgb2gray_lab(soil_masked, 'a', device, args.debug) device, soil_b = pcv.rgb2gray_lab(soil_masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, soila_thresh = pcv.binary_threshold(soil_a, 118, 255, 'dark', device, args.debug) device, soilb_thresh = pcv.binary_threshold(soil_b, 150, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, soil_ab = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) device, soil_ab_cnt = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) # Fill small objects device, soil_cnt = pcv.fill(soil_ab, soil_ab_cnt, 75, device, args.debug) # Median Filter #device, soil_mblur = pcv.median_blur(soil_fill, 5, device, args.debug) #device, soil_cnt = pcv.median_blur(soil_fill, 5, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_masked, soil_cnt, 'white', device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( masked2, soil_cnt, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(img, 'circle', device, None, 'default', args.debug, True, 0, 0, -200, -200) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## VIS Analysis ################ outfile = False if args.writeimg == True: outfile = args.outdir + "/" + filename # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, outfile) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( img, args.image, mask, 256, device, args.debug, None, 'v', 'img', 300, outfile) # Output shape and color data result = open(args.result, "a") result.write('\t'.join(map(str, shape_header))) result.write("\n") result.write('\t'.join(map(str, shape_data))) result.write("\n") for row in shape_img: result.write('\t'.join(map(str, row))) result.write("\n") result.write('\t'.join(map(str, color_header))) result.write("\n") result.write('\t'.join(map(str, color_data))) result.write("\n") for row in color_img: result.write('\t'.join(map(str, row))) result.write("\n") result.close() ############################# Use VIS image mask for NIR image######################### # Find matching NIR image device, nirpath = pcv.get_nir(path, filename, device, args.debug) nir, path1, filename1 = pcv.readimage(nirpath) nir2 = cv2.imread(nirpath, -1) # Flip mask device, f_mask = pcv.flip(mask, "horizontal", device, args.debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.1304, 0.1304, device, args.debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir, nmask, device, 9, 12, "top", "left", args.debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects( nir, newmask, device, args.debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition( nir, nir_objects, nir_hierarchy, device, args.debug) ####################################### Analysis ############################################# outfile1 = False if args.writeimg == True: outfile1 = args.outdir + "/" + filename1 device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity( nir2, filename1, nir_combinedmask, 256, device, False, args.debug, outfile1) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object( nir2, filename1, nir_combined, nir_combinedmask, device, args.debug, outfile1) coresult = open(args.coresult, "a") coresult.write('\t'.join(map(str, nhist_header))) coresult.write("\n") coresult.write('\t'.join(map(str, nhist_data))) coresult.write("\n") for row in nir_imgs: coresult.write('\t'.join(map(str, row))) coresult.write("\n") coresult.write('\t'.join(map(str, nshape_header))) coresult.write("\n") coresult.write('\t'.join(map(str, nshape_data))) coresult.write("\n") coresult.write('\t'.join(map(str, nir_shape))) coresult.write("\n") coresult.close()
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) #roi = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 0, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 0, device, args.debug) # Fill small objects #device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) # Fill small objects #device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, args.debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, 'dark', device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small noise device, ab_fill1 = pcv.fill(ab, ab_cnt, 2, device, args.debug) # Dilate to join small objects with larger ones device, ab_cnt1 = pcv.dilate(ab_fill1, 3, 2, device, args.debug) device, ab_cnt2 = pcv.dilate(ab_fill1, 3, 2, device, args.debug) # Fill dilated image mask device, ab_cnt3 = pcv.fill(ab_cnt2, ab_cnt1, 150, device, args.debug) device, masked2 = pcv.apply_mask(masked, ab_cnt3, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked2_a = pcv.rgb2gray_lab(masked2, 'a', device, args.debug) device, masked2_b = pcv.rgb2gray_lab(masked2, 'b', device, args.debug) # Threshold the green-magenta and blue images device, masked2a_thresh = pcv.binary_threshold(masked2_a, 127, 255, 'dark', device, args.debug) device, masked2b_thresh = pcv.binary_threshold(masked2_b, 128, 255, 'light', device, args.debug) device, ab_fill = pcv.logical_or(masked2a_thresh, masked2b_thresh, device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( masked2, ab_fill, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(masked2, 'rectangle', device, None, 'default', args.debug, True, 550, 0, -600, -925) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############### Analysis ################ # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, args.outdir + '/' + filename) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound( img, args.image, obj, mask, 900, device, args.debug, args.outdir + '/' + filename) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( img, args.image, kept_mask, 256, device, args.debug, None, 'v', 'img', 300, args.outdir + '/' + filename) # Output shape and color data pcv.print_results(args.image, shape_header, shape_data) pcv.print_results(args.image, color_header, color_data) pcv.print_results(args.image, boundary_header, boundary_data)
def main(): # Get options args = options() if args.debug: print("Analyzing your image dude...") # Read image img = cv2.imread(args.image, flags=0) # if a region of interest is specified read it in roi = cv2.imread(args.roi) # Pipeline step device = 0 # Start by examining the distribution of pixel intensity values if args.debug: pcv.plot_hist(img, 'hist_img') # Will intensity transformation enhance your ability to isolate object of interest by thesholding? device, he_img = pcv.HistEqualization(img, device, args.debug) if args.debug: pcv.plot_hist(he_img, 'hist_img_he') # Laplace filtering (identify edges based on 2nd derivative) device, lp_img = pcv.laplace_filter(img, 1, 1, device, args.debug) if args.debug: pcv.plot_hist(lp_img, 'hist_lp') # Lapacian image sharpening, this step will enhance the darkness of the edges detected device, lp_shrp_img = pcv.image_subtract(img, lp_img, device, args.debug) if args.debug: pcv.plot_hist(lp_shrp_img, 'hist_lp_shrp') # Sobel filtering # 1st derivative sobel filtering along horizontal axis, kernel = 1, unscaled) device, sbx_img = pcv.sobel_filter(img, 1, 0, 1, 1, device, args.debug) if args.debug: pcv.plot_hist(sbx_img, 'hist_sbx') # 1st derivative sobel filtering along vertical axis, kernel = 1, unscaled) device, sby_img = pcv.sobel_filter(img, 0, 1, 1, 1, device, args.debug) if args.debug: pcv.plot_hist(sby_img, 'hist_sby') # Combine the effects of both x and y filters through matrix addition # This will capture edges identified within each plane and emphesize edges found in both images device, sb_img = pcv.image_add(sbx_img, sby_img, device, args.debug) if args.debug: pcv.plot_hist(sb_img, 'hist_sb_comb_img') # Use a lowpass (blurring) filter to smooth sobel image device, mblur_img = pcv.median_blur(sb_img, 1, device, args.debug) device, mblur_invert_img = pcv.invert(mblur_img, device, args.debug) # combine the smoothed sobel image with the laplacian sharpened image # combines the best features of both methods as described in "Digital Image Processing" by Gonzalez and Woods pg. 169 device, edge_shrp_img = pcv.image_add(mblur_invert_img, lp_shrp_img, device, args.debug) if args.debug: pcv.plot_hist(edge_shrp_img, 'hist_edge_shrp_img') # Perform thresholding to generate a binary image device, tr_es_img = pcv.binary_threshold(edge_shrp_img, 145, 255, 'dark', device, args.debug) # Prepare a few small kernels for morphological filtering kern = np.zeros((3,3), dtype=np.uint8) kern1 = np.copy(kern) kern1[1,1:3]=1 kern2 = np.copy(kern) kern2[1,0:2]=1 kern3 = np.copy(kern) kern3[0:2,1]=1 kern4 = np.copy(kern) kern4[1:3,1]=1 # Prepare a larger kernel for dilation kern[1,0:3]=1 kern[0:3,1]=1 # Perform erosion with 4 small kernels device, e1_img = pcv.erode(tr_es_img, kern1, 1, device, args.debug) device, e2_img = pcv.erode(tr_es_img, kern2, 1, device, args.debug) device, e3_img = pcv.erode(tr_es_img, kern3, 1, device, args.debug) device, e4_img = pcv.erode(tr_es_img, kern4, 1, device, args.debug) # Combine eroded images device, c12_img = pcv.logical_or(e1_img, e2_img, device, args.debug) device, c123_img = pcv.logical_or(c12_img, e3_img, device, args.debug) device, c1234_img = pcv.logical_or(c123_img, e4_img, device, args.debug) # Perform dilation device, dil_img = pcv.dilate(c1234_img, kern, 1, device, args.debug) # Get masked image # The dilated image may contain some pixels which are not plant device, masked_erd = pcv.apply_mask(img, c1234_img, 'black', device, args.debug) device, masked_erd_dil = pcv.apply_mask(img, dil_img, 'black', device, args.debug) # Need to remove the edges of the image, we did that by generating a set of rectangles to mask the edges # img is (254 X 320) device, box1_img, rect_contour1, hierarchy1 = pcv.rectangle_mask(img, (1,1), (64,252), device, args.debug) device, box2_img, rect_contour2, hierarchy2 = pcv.rectangle_mask(img, (256,1), (318,252), device, args.debug) device, box3_img, rect_contour3, hierarchy3 = pcv.rectangle_mask(img, (1,184), (318,252), device, args.debug) device, box4_img, rect_contour4, hierarchy4 = pcv.border_mask(img, (1,1), (318,252), device, args.debug) # combine boxes to filter the edges and car out of the photo device, bx12_img = pcv.logical_or(box1_img, box2_img, device, args.debug) device, bx123_img = pcv.logical_or(bx12_img, box3_img, device, args.debug) device, bx1234_img = pcv.logical_or(bx123_img, box4_img, device, args.debug) device, inv_bx1234_img = pcv.invert(bx1234_img, device, args.debug) # Apply the box mask to the image device, masked_img = pcv.apply_mask(masked_erd_dil, inv_bx1234_img, 'black', device, args.debug) # Generate a binary to send to the analysis function device, mask = pcv.binary_threshold(masked_img, 1, 255, 'light', device, args.debug) pcv.analyze_NIR_intensity(img, args.image, mask, 256, device, args.debug, 'example')
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) # roi = cv2.imread(args.roi) device = 0 device, mask = pcv.naive_bayes_classifier(img, "naive_bayes.pdf.txt", device, args.debug) mask1 = np.uint8(mask) mask_copy = np.copy(mask1) # Fill small objects device, soil_fill = pcv.fill(mask1, mask_copy, 200, device, args.debug) # Median Filter device, soil_mblur = pcv.median_blur(soil_fill, 5, device, args.debug) device, soil_cnt = pcv.median_blur(soil_fill, 5, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(img, soil_cnt, 'white', device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( masked2, soil_cnt, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(img, 'rectangle', device, None, 'default', args.debug, True, 0, 0, 0, -900) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) # ############# Analysis ################ # output mask device, maskpath, mask_images = pcv.output_mask(device, img, mask, filename, args.outdir, True, args.debug) # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound( img, args.image, obj, mask, 830, device) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, # output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( img, args.image, mask, 256, device, args.debug, None, 'v', 'img', 300) result = open(args.result, "a") result.write('\t'.join(map(str, shape_header))) result.write("\n") result.write('\t'.join(map(str, shape_data))) result.write("\n") for row in mask_images: result.write('\t'.join(map(str, row))) result.write("\n") result.write('\t'.join(map(str, color_header))) result.write("\n") result.write('\t'.join(map(str, color_data))) result.write("\n") result.write('\t'.join(map(str, boundary_header))) result.write("\n") result.write('\t'.join(map(str, boundary_data))) result.write("\n") result.close()
def test_plantcv_apply_mask(): img = cv2.imread(os.path.join(TEST_DATA, TEST_INPUT_COLOR)) mask = cv2.imread(os.path.join(TEST_DATA, TEST_INPUT_BINARY), -1) device, masked_img = pcv.apply_mask(img=img, mask=mask, mask_color="white", device=0, debug=None) assert all([i == j] for i, j in zip(np.shape(masked_img), TEST_COLOR_DIM))
def main(): # Get options args = options() path_mask = '/home/mfeldman/tester/mask/mask_brass_tv_z3000_L2.png' # Pipeline step device = 0 # Read image img, path, filename = pcv.readimage(args.image) brass_mask = cv2.imread(path_mask) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, 'v', device, args.debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, 'light', device, args.debug) device, brass_inv = pcv.invert(brass_thresh, device, args.debug) device, masked_image = pcv.apply_mask(img, brass_inv, 'white', device, args.debug) # Looks like we can detect very bright soil particles with the h channel device, h = pcv.rgb2gray_hsv(masked_image, 'h', device, args.debug) h_soil = cv2.inRange(h, 100, 255) # Make an image mask to cover these points h_soil_inv = cv2.bitwise_not(h_soil) # We can remove the outer ring of the pot using the s channel device, s = pcv.rgb2gray_hsv(masked_image, 's', device, args.debug) s_ring = cv2.inRange(s, 0, 40) s_ring_inv = cv2.bitwise_not(s_ring) # We can do a pretty good job of identifying the plant from the a channel device, a = pcv.rgb2gray_lab(masked_image, 'a', device, args.debug) a_thresh = cv2.inRange(a, 100, 117) # Lets blur the result a bit to get rid of unwanted noise blur = cv2.medianBlur(a_thresh, 5) # Get cart to remove from b channel device, b = pcv.rgb2gray_lab(masked_image, 'b', device, args.debug) b_cart = cv2.inRange(b, 0, 110) b_cart_inv = cv2.bitwise_not(b_cart) # Now lets set of a series of filters to remove unwanted background filter1 = cv2.bitwise_and(blur, b_cart_inv) filter2 = cv2.bitwise_and(filter1, h_soil_inv) plant_shape = cv2.bitwise_and(filter2, s_ring_inv) # Now remove all remaining small points using erosion with a 3 x 3 kernel kernel = np.ones((3, 3), np.uint8) erosion = cv2.erode(plant_shape, kernel, iterations=1) # Now dilate to fill in small holes kernel = np.ones((3, 3), np.uint8) dilation = cv2.dilate(erosion, kernel, iterations=1) # Apply mask to the background image device, masked = pcv.apply_mask(img, plant_shape, 'white', device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( img, erosion, device, args.debug) # Get ROI contours device, roi, roi_hierarchy = pcv.define_roi(masked_image, 'circle', device, None, 'default', args.debug, True, x_adj=0, y_adj=0, w_adj=0, h_adj=-1200) # ROI device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( masked_image, 'partial', roi, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug) # Get object contour and masked object device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## Landmarks ################ device, points = pcv.acute_vertex(obj, 20, 10, 40, img, device, args.debug) boundary_line = 'NA' # Use acute fxn to estimate tips device, points_r, centroid_r, bline_r = pcv.scale_features( obj, mask, points, boundary_line, device, args.debug) # Get number of points tips = len(points_r) # Use turgor_proxy fxn to get distances device, vert_ave_c, hori_ave_c, euc_ave_c, ang_ave_c, vert_ave_b, hori_ave_b, euc_ave_b, ang_ave_b = pcv.turgor_proxy( points_r, centroid_r, bline_r, device, args.debug) # Get pseudomarkers along the y-axis device, left, right, center_h = pcv.y_axis_pseudolandmarks( obj, mask, img, device, args.debug) # Re-scale the points device, left_r, left_cr, left_br = pcv.scale_features( obj, mask, left, boundary_line, device, args.debug) device, right_r, right_cr, right_br = pcv.scale_features( obj, mask, right, boundary_line, device, args.debug) device, center_hr, center_hcr, center_hbr = pcv.scale_features( obj, mask, center_h, boundary_line, device, args.debug) # Get pseudomarkers along the x-axis device, top, bottom, center_v = pcv.x_axis_pseudolandmarks( obj, mask, img, device, args.debug) # Re-scale the points device, top_r, top_cr, top_br = pcv.scale_features(obj, mask, top, boundary_line, device, args.debug) device, bottom_r, bottom_cr, bottom_br = pcv.scale_features( obj, mask, bottom, boundary_line, device, args.debug) device, center_vr, center_vcr, center_vbr = pcv.scale_features( obj, mask, center_v, boundary_line, device, args.debug) ## Need to convert the points into a list of tuples format to match the scaled points points = points.reshape(len(points), 2) points = points.tolist() temp_out = [] for p in points: p = tuple(p) temp_out.append(p) points = temp_out left = left.reshape(20, 2) left = left.tolist() temp_out = [] for l in left: l = tuple(l) temp_out.append(l) left = temp_out right = right.reshape(20, 2) right = right.tolist() temp_out = [] for r in right: r = tuple(r) temp_out.append(r) right = temp_out center_h = center_h.reshape(20, 2) center_h = center_h.tolist() temp_out = [] for ch in center_h: ch = tuple(ch) temp_out.append(ch) center_h = temp_out ## Need to convert the points into a list of tuples format to match the scaled points top = top.reshape(20, 2) top = top.tolist() temp_out = [] for t in top: t = tuple(t) temp_out.append(t) top = temp_out bottom = bottom.reshape(20, 2) bottom = bottom.tolist() temp_out = [] for b in bottom: b = tuple(b) temp_out.append(b) bottom = temp_out center_v = center_v.reshape(20, 2) center_v = center_v.tolist() temp_out = [] for cvr in center_v: cvr = tuple(cvr) temp_out.append(cvr) center_v = temp_out #Store Landmark Data landmark_header = ('HEADER_LANDMARK', 'tip_points', 'tip_points_r', 'centroid_r', 'baseline_r', 'tip_number', 'vert_ave_c', 'hori_ave_c', 'euc_ave_c', 'ang_ave_c', 'vert_ave_b', 'hori_ave_b', 'euc_ave_b', 'ang_ave_b', 'left_lmk', 'right_lmk', 'center_h_lmk', 'left_lmk_r', 'right_lmk_r', 'center_h_lmk_r', 'top_lmk', 'bottom_lmk', 'center_v_lmk', 'top_lmk_r', 'bottom_lmk_r', 'center_v_lmk_r') landmark_data = ('LANDMARK_DATA', points, points_r, centroid_r, bline_r, tips, vert_ave_c, hori_ave_c, euc_ave_c, ang_ave_c, vert_ave_b, hori_ave_b, euc_ave_b, ang_ave_b, left, right, center_h, left_r, right_r, center_hr, top, bottom, center_v, top_r, bottom_r, center_vr) ############## VIS Analysis ################ outfile = False #if args.writeimg==True: #outfile=args.outdir+"/"+filename # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, outfile) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound( img, args.image, obj, mask, 330, device, args.debug, outfile) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( img, args.image, mask, 256, device, args.debug, None, 'v', 'img', 300, outfile) # Output shape and color data result = open(args.result, "a") result.write('\t'.join(map(str, shape_header))) result.write("\n") result.write('\t'.join(map(str, shape_data))) result.write("\n") for row in shape_img: result.write('\t'.join(map(str, row))) result.write("\n") result.write('\t'.join(map(str, color_header))) result.write("\n") result.write('\t'.join(map(str, color_data))) result.write("\n") result.write('\t'.join(map(str, boundary_header))) result.write("\n") result.write('\t'.join(map(str, boundary_data))) result.write("\n") result.write('\t'.join(map(str, boundary_img1))) result.write("\n") for row in color_img: result.write('\t'.join(map(str, row))) result.write("\n") result.write('\t'.join(map(str, landmark_header))) result.write("\n") result.write('\t'.join(map(str, landmark_data))) result.write("\n") result.close()
def main(): # Parse command-line options args = options() device = 0 # Open output file out = open(args.outfile, "w") # Open the image file img, path, fname = pcv.readimage(filename=args.image, debug=args.debug) # Classify healthy and unhealthy plant pixels device, masks = pcv.naive_bayes_classifier(img=img, pdf_file=args.pdfs, device=device) # Use the identified blue mesh area to build a mask for the pot area # First errode the blue mesh region to remove background device, mesh_errode = pcv.erode(img=masks["Background_Blue"], kernel=9, i=3, device=device, debug=args.debug) # Define a region of interest for blue mesh contours device, pot_roi, pot_hierarchy = pcv.define_roi(img=img, shape='rectangle', device=device, roi=None, roi_input='default', debug=args.debug, adjust=True, x_adj=0, y_adj=500, w_adj=0, h_adj=-650) # Find blue mesh contours device, mesh_objects, mesh_hierarchy = pcv.find_objects(img=img, mask=mesh_errode, device=device, debug=args.debug) # Keep blue mesh contours in the region of interest device, kept_mesh_objs, kept_mesh_hierarchy, kept_mask_mesh, _ = pcv.roi_objects( img=img, roi_type='partial', roi_contour=pot_roi, roi_hierarchy=pot_hierarchy, object_contour=mesh_objects, obj_hierarchy=mesh_hierarchy, device=device, debug=args.debug) # Flatten the blue mesh contours into a single object device, mesh_flattened, mesh_mask = pcv.object_composition( img=img, contours=kept_mesh_objs, hierarchy=kept_mesh_hierarchy, device=device, debug=args.debug) # Initialize a pot mask pot_mask = np.zeros(np.shape(masks["Background_Blue"]), dtype=np.uint8) # Find the minimum bounding rectangle for the blue mesh region rect = cv2.minAreaRect(mesh_flattened) # Create a contour for the minimum bounding box box = cv2.boxPoints(rect) box = np.int0(box) # Create a mask from the bounding box contour cv2.drawContours(pot_mask, [box], 0, (255), -1) # If the bounding box area is too small then the plant has likely occluded too much of the pot for us to use this # as a marker for the pot area if np.sum(pot_mask) / 255 < 2900000: print(np.sum(pot_mask) / 255) # Create a new pot mask pot_mask = np.zeros(np.shape(masks["Background_Blue"]), dtype=np.uint8) # Set the mask area to the ROI area box = np.array([[0, 500], [0, 2806], [2304, 2806], [2304, 500]]) cv2.drawContours(pot_mask, [box], 0, (255), -1) # Dialate the blue mesh area to include the ridge of the pot device, pot_mask_dilated = pcv.dilate(img=pot_mask, kernel=3, i=60, device=device, debug=args.debug) # Mask the healthy mask device, healthy_masked = pcv.apply_mask(img=cv2.merge( [masks["Healthy"], masks["Healthy"], masks["Healthy"]]), mask=pot_mask_dilated, mask_color="black", device=device, debug=args.debug) # Mask the unhealthy mask device, unhealthy_masked = pcv.apply_mask(img=cv2.merge( [masks["Unhealthy"], masks["Unhealthy"], masks["Unhealthy"]]), mask=pot_mask_dilated, mask_color="black", device=device, debug=args.debug) # Convert the masks back to binary healthy_masked, _, _ = cv2.split(healthy_masked) unhealthy_masked, _, _ = cv2.split(unhealthy_masked) # Fill small objects device, fill_image_healthy = pcv.fill(img=np.copy(healthy_masked), mask=np.copy(healthy_masked), size=300, device=device, debug=args.debug) device, fill_image_unhealthy = pcv.fill(img=np.copy(unhealthy_masked), mask=np.copy(unhealthy_masked), size=1000, device=device, debug=args.debug) # Define a region of interest device, roi1, roi_hierarchy = pcv.define_roi(img=img, shape='rectangle', device=device, roi=None, roi_input='default', debug=args.debug, adjust=True, x_adj=450, y_adj=1000, w_adj=-400, h_adj=-1000) # Filter objects that overlap the ROI device, id_objects, obj_hierarchy_healthy = pcv.find_objects( img=img, mask=fill_image_healthy, device=device, debug=args.debug) device, _, _, kept_mask_healthy, _ = pcv.roi_objects( img=img, roi_type='partial', roi_contour=roi1, roi_hierarchy=roi_hierarchy, object_contour=id_objects, obj_hierarchy=obj_hierarchy_healthy, device=device, debug=args.debug) device, id_objects, obj_hierarchy_unhealthy = pcv.find_objects( img=img, mask=fill_image_unhealthy, device=device, debug=args.debug) device, _, _, kept_mask_unhealthy, _ = pcv.roi_objects( img=img, roi_type='partial', roi_contour=roi1, roi_hierarchy=roi_hierarchy, object_contour=id_objects, obj_hierarchy=obj_hierarchy_unhealthy, device=device, debug=args.debug) # Combine the healthy and unhealthy mask device, mask = pcv.logical_or(img1=kept_mask_healthy, img2=kept_mask_unhealthy, device=device, debug=args.debug) # Output a healthy/unhealthy image classified_img = cv2.merge([ np.zeros(np.shape(mask), dtype=np.uint8), kept_mask_healthy, kept_mask_unhealthy ]) pcv.print_image(img=classified_img, filename=os.path.join( args.outdir, os.path.basename(args.image)[:-4] + ".classified.png")) # Output a healthy/unhealthy image overlaid on the original image overlayed = cv2.addWeighted(src1=np.copy(classified_img), alpha=0.5, src2=np.copy(img), beta=0.5, gamma=0) pcv.print_image(img=overlayed, filename=os.path.join( args.outdir, os.path.basename(args.image)[:-4] + ".overlaid.png")) # Extract hue values from the image device, h = pcv.rgb2gray_hsv(img=img, channel="h", device=device, debug=args.debug) # Extract the plant hue values plant_hues = h[np.where(mask == 255)] # Initialize hue histogram hue_hist = {} for i in range(0, 180): hue_hist[i] = 0 # Store all hue values hue_values = [] # Populate histogram total_px = len(plant_hues) for hue in plant_hues: hue_hist[hue] += 1 hue_values.append(hue) # Parse the filename genotype, treatment, replicate, timepoint = os.path.basename( args.image)[:-4].split("_") replicate = replicate.replace("#", "") if timepoint[-3:] == "dbi": timepoint = -1 else: timepoint = timepoint.replace("dpi", "") # Output results for i in range(0, 180): out.write("\t".join( map(str, [ genotype, treatment, timepoint, replicate, total_px, i, hue_hist[i] ])) + "\n") out.close() # Calculate basic statistics healthy_sum = int(np.sum(kept_mask_healthy)) unhealthy_sum = int(np.sum(kept_mask_unhealthy)) healthy_total_ratio = healthy_sum / float(healthy_sum + unhealthy_sum) unhealthy_total_ratio = unhealthy_sum / float(healthy_sum + unhealthy_sum) stats = open(args.outfile[:-4] + ".stats.txt", "w") stats.write("%s, %f, %f, %f, %f" % (os.path.basename(args.image), healthy_sum, unhealthy_sum, healthy_total_ratio, unhealthy_total_ratio) + '\n') stats.close() # Fit a 3-component Gaussian Mixture Model gmm = mixture.GaussianMixture(n_components=3, covariance_type="full", tol=0.001) gmm.fit(np.expand_dims(hue_values, 1)) gmm3 = open(args.outfile[:-4] + ".gmm3.txt", "w") gmm3.write("%s, %f, %f, %f, %f, %f, %f, %f, %f, %f" % (os.path.basename(args.image), gmm.means_.ravel()[0], gmm.means_.ravel()[1], gmm.means_.ravel()[2], np.sqrt(gmm.covariances_.ravel()[0]), np.sqrt(gmm.covariances_.ravel()[1]), np.sqrt(gmm.covariances_.ravel()[2]), gmm.weights_.ravel()[0], gmm.weights_.ravel()[1], gmm.weights_.ravel()[2]) + '\n') gmm3.close() # Fit a 2-component Gaussian Mixture Model gmm = mixture.GaussianMixture(n_components=2, covariance_type="full", tol=0.001) gmm.fit(np.expand_dims(hue_values, 1)) gmm2 = open(args.outfile[:-4] + ".gmm2.txt", "w") gmm2.write("%s, %f, %f, %f, %f, %f, %f" % (os.path.basename(args.image), gmm.means_.ravel()[0], gmm.means_.ravel()[1], np.sqrt(gmm.covariances_.ravel()[0]), np.sqrt(gmm.covariances_.ravel()[1]), gmm.weights_.ravel()[0], gmm.weights_.ravel()[1]) + '\n') gmm2.close() # Fit a 1-component Gaussian Mixture Model gmm = mixture.GaussianMixture(n_components=1, covariance_type="full", tol=0.001) gmm.fit(np.expand_dims(hue_values, 1)) gmm1 = open(args.outfile[:-4] + ".gmm1.txt", "w") gmm1.write( "%s, %f, %f, %f" % (os.path.basename(args.image), gmm.means_.ravel()[0], np.sqrt(gmm.covariances_.ravel()[0]), gmm.weights_.ravel()[0]) + '\n') gmm1.close()
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) #roi = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 150, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, args.debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 122, 255, 'dark', device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 133, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small objects device, ab_fill = pcv.fill(ab, ab_cnt, 200, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(masked, ab_fill, 'white', device, args.debug) # Select area with black bars and find overlapping plant material device, roi1, roi_hierarchy1= pcv.define_roi(masked2,'rectangle', device, None, 'default', args.debug,True, 0, 0,-1900,0) device, id_objects1,obj_hierarchy1 = pcv.find_objects(masked2, ab_fill, device, args.debug) device,roi_objects1, hierarchy1, kept_mask1, obj_area1 = pcv.roi_objects(masked2,'cutto',roi1,roi_hierarchy1,id_objects1,obj_hierarchy1,device, args.debug) device, masked3 = pcv.apply_mask(masked2, kept_mask1, 'white', device, args.debug) device, masked_a1 = pcv.rgb2gray_lab(masked3, 'a', device, args.debug) device, masked_b1 = pcv.rgb2gray_lab(masked3, 'b', device, args.debug) device, maskeda_thresh1 = pcv.binary_threshold(masked_a1, 122, 255, 'dark', device, args.debug) device, maskedb_thresh1 = pcv.binary_threshold(masked_b1, 170, 255, 'light', device, args.debug) device, ab1 = pcv.logical_or(maskeda_thresh1, maskedb_thresh1, device, args.debug) device, ab_cnt1 = pcv.logical_or(maskeda_thresh1, maskedb_thresh1, device, args.debug) device, ab_fill1 = pcv.fill(ab1, ab_cnt1, 300, device, args.debug) device, roi2, roi_hierarchy2= pcv.define_roi(masked2,'rectangle', device, None, 'default', args.debug,True, 1900, 0,0,0) device, id_objects2,obj_hierarchy2 = pcv.find_objects(masked2, ab_fill, device, args.debug) device,roi_objects2, hierarchy2, kept_mask2, obj_area2 = pcv.roi_objects(masked2,'cutto',roi2,roi_hierarchy2,id_objects2,obj_hierarchy2,device, args.debug) device, masked4 = pcv.apply_mask(masked2, kept_mask2, 'white', device, args.debug) device, masked_a2 = pcv.rgb2gray_lab(masked4, 'a', device, args.debug) device, masked_b2 = pcv.rgb2gray_lab(masked4, 'b', device, args.debug) device, maskeda_thresh2 = pcv.binary_threshold(masked_a2, 122, 255, 'dark', device, args.debug) device, maskedb_thresh2 = pcv.binary_threshold(masked_b2, 170, 255, 'light', device, args.debug) device, ab2 = pcv.logical_or(maskeda_thresh2, maskedb_thresh2, device, args.debug) device, ab_cnt2 = pcv.logical_or(maskeda_thresh2, maskedb_thresh2, device, args.debug) device, ab_fill2 = pcv.fill(ab2, ab_cnt2, 200, device, args.debug) device, ab_cnt3 = pcv.logical_or(ab_fill1, ab_fill2, device, args.debug) device, masked3 = pcv.apply_mask(masked2, ab_cnt3, 'white', device, args.debug) # Identify objects device, id_objects3,obj_hierarchy3 = pcv.find_objects(masked2, ab_fill, device, args.debug) # Define ROI device, roi3, roi_hierarchy3= pcv.define_roi(masked2,'rectangle', device, None, 'default', args.debug,True, 500, 0,-450,-530) # Decide which objects to keep and combine with objects overlapping with black bars device,roi_objects3, hierarchy3, kept_mask3, obj_area1 = pcv.roi_objects(img,'cutto',roi3,roi_hierarchy3,id_objects3,obj_hierarchy3,device, args.debug) device, kept_mask4_1 = pcv.logical_or(ab_cnt3, kept_mask3, device, args.debug) device, kept_cnt = pcv.logical_or(ab_cnt3, kept_mask3, device, args.debug) device, kept_mask4 = pcv.fill(kept_mask4_1, kept_cnt, 200, device, args.debug) device, masked5 = pcv.apply_mask(masked2, kept_mask4, 'white', device, args.debug) device, id_objects4,obj_hierarchy4 = pcv.find_objects(masked5, kept_mask4, device, args.debug) device, roi4, roi_hierarchy4= pcv.define_roi(masked2,'rectangle', device, None, 'default', args.debug,False, 0, 0,0,0) device,roi_objects4, hierarchy4, kept_mask4, obj_area = pcv.roi_objects(img,'partial',roi4,roi_hierarchy4,id_objects4,obj_hierarchy4,device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects4, hierarchy4, device, args.debug) ############## Analysis ################ # Find shape properties, output shape image (optional) device, shape_header,shape_data,shape_img = pcv.analyze_object(img, args.image, obj, mask, device,args.debug,args.outdir+'/'+filename) # Shape properties relative to user boundary line (optional) device, boundary_header,boundary_data, boundary_img1= pcv.analyze_bound(img, args.image,obj, mask, 950, device,args.debug,args.outdir+'/'+filename) # Tiller Tool Test device, tillering_header, tillering_data, tillering_img= pcv.tiller_count(img, args.image,obj, mask, 965, device,args.debug,args.outdir+'/'+filename) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header,color_data,norm_slice= pcv.analyze_color(img, args.image, kept_mask4, 256, device, args.debug,'all','rgb','v',args.outdir+'/'+filename) # Output shape and color data pcv.print_results(args.image, shape_header, shape_data) pcv.print_results(args.image, color_header, color_data) pcv.print_results(args.image, boundary_header, boundary_data) pcv.print_results(args.image, tillering_header,tillering_data)
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 0, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 0, device, args.debug) # Fill small objects #device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) # Fill small objects #device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, args.debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, 'dark', device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small noise device, ab_fill1 = pcv.fill(ab, ab_cnt, 2, device, args.debug) # Dilate to join small objects with larger ones device, ab_cnt1=pcv.dilate(ab_fill1, 3, 2, device, args.debug) device, ab_cnt2=pcv.dilate(ab_fill1, 3, 2, device, args.debug) # Fill dilated image mask device, ab_cnt3=pcv.fill(ab_cnt2,ab_cnt1,150,device,args.debug) device, masked2 = pcv.apply_mask(masked, ab_cnt3, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked2_a = pcv.rgb2gray_lab(masked2, 'a', device, args.debug) device, masked2_b = pcv.rgb2gray_lab(masked2, 'b', device, args.debug) # Threshold the green-magenta and blue images device, masked2a_thresh = pcv.binary_threshold(masked2_a, 127, 255, 'dark', device, args.debug) device, masked2b_thresh = pcv.binary_threshold(masked2_b, 128, 255, 'light', device, args.debug) device, ab_fill = pcv.logical_or(masked2a_thresh, masked2b_thresh, device, args.debug) # Identify objects device, id_objects,obj_hierarchy = pcv.find_objects(masked2, ab_fill, device, args.debug) # Define ROI device, roi1, roi_hierarchy= pcv.define_roi(masked2,'rectangle', device, None, 'default', args.debug,True, 525, 0,-490,-150) # Decide which objects to keep device,roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img,'partial',roi1,roi_hierarchy,id_objects,obj_hierarchy,device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## VIS Analysis ################ outfile=False if args.writeimg==True: outfile=args.outdir+"/"+filename # Find shape properties, output shape image (optional) device, shape_header,shape_data,shape_img = pcv.analyze_object(img, args.image, obj, mask, device,args.debug,outfile) # Shape properties relative to user boundary line (optional) device, boundary_header,boundary_data, boundary_img1= pcv.analyze_bound(img, args.image,obj, mask, 325, device,args.debug,outfile) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header,color_data,color_img= pcv.analyze_color(img, args.image, mask, 256, device, args.debug,None,'v','img',300,outfile) # Output shape and color data result=open(args.result,"a") result.write('\t'.join(map(str,shape_header))) result.write("\n") result.write('\t'.join(map(str,shape_data))) result.write("\n") for row in shape_img: result.write('\t'.join(map(str,row))) result.write("\n") result.write('\t'.join(map(str,color_header))) result.write("\n") result.write('\t'.join(map(str,color_data))) result.write("\n") result.write('\t'.join(map(str,boundary_header))) result.write("\n") result.write('\t'.join(map(str,boundary_data))) result.write("\n") result.write('\t'.join(map(str,boundary_img1))) result.write("\n") for row in color_img: result.write('\t'.join(map(str,row))) result.write("\n") result.close()
def main(): # obtiene opciones de imagen args = options() #LINEA 22 if args.debug: print("Debug mode turned on...") # lee la imagen el flags=0 indica que se espera una imagen a escala de grises img = cv2.imread(args.image, flags=0) # cv2.imshow("imagen original",img) # Get directory path and image name from command line arguments path, img_name = os.path.split(args.image) #LINEA 30 # Read in image which is the pixelwise average of background images img_bkgrd = cv2.imread("background_average.jpg", flags=0) #cv2.imshow("ventana del fondo",img_bkgrd) # paso del procesamiento de imagenes device = 0 ######hasta qui bien #linea 37 # Restar la imagen de fondo de la imagen con la planta. device, bkg_sub_img = pcv.image_subtract(img, img_bkgrd, device, args.debug) #cv2.imshow("imagen resta",bkg_sub_img) # Threshold the image of interest using the two-sided cv2.inRange function (keep what is between 50-190) bkg_sub_thres_img = cv2.inRange(bkg_sub_img, 50, 190) if args.debug: cv2.imwrite('bkgrd_sub_thres.png', bkg_sub_thres_img) #hasta qui todo bien #linea 46 # Filtrado de Laplace (identificar bordes basados en la derivada 2) device, lp_img = pcv.laplace_filter(img, 1, 1, device, args.debug) #cv2.imshow("imagen de filtrado",lp_img) if args.debug: pcv.plot_hist(lp_img, 'histograma_lp') # Lapacian image sharpening, this step will enhance the darkness of the edges detected device, lp_shrp_img = pcv.image_subtract(img, lp_img, device, args.debug) #cv2.imshow("imagen de borde lapacian",lp_shrp_img) if args.debug: pcv.plot_hist(lp_shrp_img, 'histograma_lp_shrp') #hasta aqui todo bien linea 58 # Sobel filtering-filtrado de sobel # 1ª derivada filtrado sobel a lo largo del eje horizontal, núcleo = 1, sin escala) """ segun esta masl son siete,kito scale y me kedo con apertura k,chekar sobel en docs device, sbx_img = pcv.sobel_filter(img, 1, 0, 1, 1, device, args.debug) """ device, sbx_img = pcv.sobel_filter(img, 1, 0, 1, device, args.debug) #cv2.imshow("imagen sobel-eje horizontal",sbx_img) if args.debug: pcv.plot_hist(sbx_img, 'histograma_sbx') # Filtrado de la primera derivada sobel a lo largo del eje vertical, núcleo = 1, sin escala) device, sby_img = pcv.sobel_filter(img, 0, 1, 1, device, args.debug) #cv2.imshow("imagen sobel-ejevertical",sby_img) if args.debug: pcv.plot_hist(sby_img, 'histograma_sby') # Combina los efectos de ambos filtros x e y mediante la suma de matrizes # Esto captura los bordes identificados dentro de cada plano y enfatiza los bordes encontrados en ambas imágenes device, sb_img = pcv.image_add(sbx_img, sby_img, device, args.debug) #cv2.imshow("imagen suma de sobel",sb_img) if args.debug: pcv.plot_hist(sb_img, 'histograma_sb_comb_img') #hasta aqui todo bien linea 82 # usar filtro pasa bajo blur para suavizar la imagen de sobel device, mblur_img = pcv.median_blur(sb_img, 1, device, args.debug) #cv2.imshow("imagen blur",mblur_img) device, mblur_invert_img = pcv.invert(mblur_img, device, args.debug) #cv2.imshow("imagen blur-invertido",mblur_invert_img) # Combinar la imagen suavizada del sobel con la imagen afilada del laplaciano # combines the best features of both methods as described in "Digital Image Processing" by Gonzalez and Woods pg. 169 #Combina las mejores características de ambos métodos como se describe en "Digital Image Processing" por González y Woods pág. 169 device, edge_shrp_img = pcv.image_add(mblur_invert_img, lp_shrp_img, device, args.debug) #cv2.imshow("imagen-combinacion-sobel-laplacian",mblur_img) if args.debug: pcv.plot_hist(edge_shrp_img, 'hist_edge_shrp_img') # Realizar el umbral para generar una imagen binaria device, tr_es_img = pcv.binary_threshold(edge_shrp_img, 125, 255, 'dark', device, args.debug) #cv2.imshow("imagen binaria de combinacion",tr_es_img) #hasta aqui todo bien linea 99 # Prepare a few small kernels for morphological filtering #prepara nucleos pequeños para un filtrado moorfologico kern = np.zeros((3, 3), dtype=np.uint8) kern1 = np.copy(kern) kern1[1, 1:3] = 1 kern2 = np.copy(kern) kern2[1, 0:2] = 1 kern3 = np.copy(kern) kern3[0:2, 1] = 1 kern4 = np.copy(kern) kern4[1:3, 1] = 1 # prepara un nucleo grande para la dilatacion kern[1, 0:3] = 1 kern[0:3, 1] = 1 # Perform erosion with 4 small kernels device, e1_img = pcv.erode(tr_es_img, 1, 1, device, args.debug) #cv2.imshow("erosion 1",e1_img) device, e2_img = pcv.erode(tr_es_img, 1, 1, device, args.debug) #cv2.imshow("erosion 2",e2_img) device, e3_img = pcv.erode(tr_es_img, 1, 1, device, args.debug) #cv2.imshow("erosion 3",e3_img) device, e4_img = pcv.erode(tr_es_img, 1, 1, device, args.debug) #cv2.imshow("erosion 4",e4_img) # Combine eroded images device, c12_img = pcv.logical_or(e1_img, e2_img, device, args.debug) #cv2.imshow("c12",c12_img) device, c123_img = pcv.logical_or(c12_img, e3_img, device, args.debug) #cv2.imshow("c123",c123_img) device, c1234_img = pcv.logical_or(c123_img, e4_img, device, args.debug) #cv2.imshow("c1234",c1234_img) # Bring the two object identification approaches together. # Using a logical OR combine object identified by background subtraction and the object identified by derivative filter. device, comb_img = pcv.logical_or(c1234_img, bkg_sub_thres_img, device, args.debug) #cv2.imshow("comb_img",comb_img) # Get masked image, Essentially identify pixels corresponding to plant and keep those. device, masked_erd = pcv.apply_mask(img, comb_img, 'black', device, args.debug) #cv2.imshow("masked_erd",masked_erd) #cv2.imshow("imagen original chkar",img) # Need to remove the edges of the image, we did that by generating a set of rectangles to mask the edges # img is (254 X 320) # mask for the bottom of the image device, im2, box1_img, rect_contour1, hierarchy1 = pcv.rectangle_mask( img, (120, 184), (215, 252), device, args.debug, color='white') #cv2.imshow("im2",box1_img) # mask for the left side of the image device, im3, box2_img, rect_contour2, hierarchy2 = pcv.rectangle_mask( img, (1, 1), (85, 252), device, args.debug, color='white') #cv2.imshow("im3",box2_img) # mask for the right side of the image device, im4, box3_img, rect_contour3, hierarchy3 = pcv.rectangle_mask( img, (240, 1), (318, 252), device, args.debug, color='white') #cv2.imshow("im4",box3_img) # mask the edges device, im5, box4_img, rect_contour4, hierarchy4 = pcv.rectangle_mask( img, (1, 1), (318, 252), device, args.debug) #cv2.imshow("im5",box4_img) # combine boxes to filter the edges and car out of the photo device, bx12_img = pcv.logical_or(box1_img, box2_img, device, args.debug) device, bx123_img = pcv.logical_or(bx12_img, box3_img, device, args.debug) device, bx1234_img = pcv.logical_or(bx123_img, box4_img, device, args.debug) #cv2.imshow("combinacion logica or",bx1234_img) # invert this mask and then apply it the masked image. device, inv_bx1234_img = pcv.invert(bx1234_img, device, args.debug) # cv2.imshow("combinacion logica or invertida",inv_bx1234_img) device, edge_masked_img = pcv.apply_mask(masked_erd, inv_bx1234_img, 'black', device, args.debug) # cv2.imshow("edge_masked_img",edge_masked_img) # assign the coordinates of an area of interest (rectangle around the area you expect the plant to be in) device, im6, roi_img, roi_contour, roi_hierarchy = pcv.rectangle_mask( img, (120, 75), (200, 184), device, args.debug) #cv2.imshow("im6",roi_img) # get the coordinates of the plant from the masked object plant_objects, plant_hierarchy = cv2.findContours(edge_masked_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # Obtain the coordinates of the plant object which are partially within the area of interest device, roi_objects, hierarchy5, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi_contour, roi_hierarchy, plant_objects, plant_hierarchy, device, args.debug) # Apply the box mask to the image to ensure no background device, masked_img = pcv.apply_mask(kept_mask, inv_bx1234_img, 'black', device, args.debug) #cv2.imshow("mascara final",masked_img) #///////////////////////////////////////////////////////////// #device, masked_img = pcv.apply_mask(kept_mask, inv_bx1234_img, 'black', device, args.debug) rgb = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) #cv2.imshow("rgb",rgb) # Generate a binary to send to the analysis function device, mask = pcv.binary_threshold(masked_img, 1, 255, 'light', device, args.debug) #cv2.imshow("mask",mask) mask3d = np.copy(mask) plant_objects_2, plant_hierarchy_2 = cv2.findContours( mask3d, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) device, o, m = pcv.object_composition(rgb, roi_objects, hierarchy5, device, args.debug) # Get final masked image device, masked_img = pcv.apply_mask(kept_mask, inv_bx1234_img, 'black', device, args.debug) #cv2.imshow("maskara final2",masked_img) ################### copia lo de arriba esta mal el tutorial # Obtain a 3 dimensional representation of this grayscale image (for pseudocoloring) #rgb = cv2.cvtColor(img,cv2.COLOR_GRAY2RGB) # Generate a binary to send to the analysis function #device, mask = pcv.binary_threshold(masked_img, 1, 255, 'light', device, args.debug) # Make a copy of this mask for pseudocoloring #mask3d = np.copy(mask) # Extract coordinates of plant for pseudocoloring of plant #plant_objects_2, plant_hierarchy_2 = cv2.findContours(mask3d,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) #device, o, m = pcv.object_composition(rgb, roi_objects, hierarchy5, device, args.debug) # Extract coordinates of plant for pseudocoloring of plant #plant_objects_2, plant_hierarchy_2 = cv2.findContours(mask3d,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) #device, o, m = pcv.object_composition(rgb, roi_objects, hierarchy5, device, args.debug) #################################### ####################### ### Analysis ### # Perform signal analysis #################pruebas de que esta masl el tutorial"""""""""""""""" #ols=type(args.image) #print ols ##############pruebas de que no agarro device, hist_header, hist_data, h_norm = pcv.analyze_NIR_intensity(img, args.image, mask, 256, device, args.debug, args.outdir + '/' + img_name) #print(args.outdir+'/'+img_name) #print(args.debug) #al final si salio se agrego lo qyue esta debug= and filename= ##################################################### debug me marca True por ello puse pritn de mas #device, hist_header, hist_data, h_norm = pcv.analyze_NIR_intensity(img, rgb, mask, 256, device, debug='print', filename=False) device, hist_header, hist_data, h_norm = pcv.analyze_NIR_intensity( img, rgb, mask, 256, device, debug=args.debug, filename=args.outdir + '/' + img_name) # Perform shape analysis device, shape_header, shape_data, ori_img = pcv.analyze_object( rgb, args.image, o, m, device, debug=args.debug, filename=args.outdir + '/' + img_name) # Print the results to STDOUT pcv.print_results(args.image, hist_header, hist_data) pcv.print_results(args.image, shape_header, shape_data) cv2.waitKey() cv2.destroyAllWdindows()
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) # Pipeline step device = 0 debug = args.debug # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 85, 255, 'light', device, debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 160, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 160, 255, 'light', device, debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_or(s_mblur, b_cnt, device, debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 115, 255, 'dark', device, debug) device, maskeda_thresh1 = pcv.binary_threshold(masked_a, 135, 255, 'light', device, debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab1 = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) device, ab = pcv.logical_or(maskeda_thresh1, ab1, device, debug) device, ab_cnt = pcv.logical_or(maskeda_thresh1, ab1, device, debug) # Fill small objects device, ab_fill = pcv.fill(ab, ab_cnt, 200, device, debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(masked, ab_fill, 'white', device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( masked2, ab_fill, device, debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(masked2, 'rectangle', device, None, 'default', debug, True, 550, 0, -500, -1900) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, debug)
def main(): # Get options args = options() # Read image (converting fmax and track to 8 bit just to create a mask, use 16-bit for all the math) mask, path, filename = pcv.readimage(args.fmax) #mask = cv2.imread(args.fmax) track = cv2.imread(args.track) mask1, mask2, mask3 = cv2.split(mask) # Pipeline step device = 0 # Mask pesky track autofluor device, track1 = pcv.rgb2gray_hsv(track, 'v', device, args.debug) device, track_thresh = pcv.binary_threshold(track1, 0, 255, 'light', device, args.debug) device, track_inv = pcv.invert(track_thresh, device, args.debug) device, track_masked = pcv.apply_mask(mask1, track_inv, 'black', device, args.debug) # Threshold the Saturation image device, fmax_thresh = pcv.binary_threshold(track_masked, 20, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(fmax_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(fmax_thresh, 5, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 110, device, args.debug) device, sfill_cnt = pcv.fill(s_mblur, s_cnt, 110, device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( mask, sfill_cnt, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(mask, 'circle', device, None, 'default', args.debug, True, 0, 0, -50, -50) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( mask, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug) # Object combine kept objects device, obj, masked = pcv.object_composition(mask, roi_objects, hierarchy3, device, args.debug) ################ Analysis ################ # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( mask, args.fmax, obj, masked, device, args.debug, args.outdir + '/' + filename) # Fluorescence Measurement (read in 16-bit images) fdark = cv2.imread(args.fdark, -1) fmin = cv2.imread(args.fmin, -1) fmax = cv2.imread(args.fmax, -1) device, fvfm_header, fvfm_data = pcv.fluor_fvfm( fdark, fmin, fmax, kept_mask, device, args.outdir + '/' + filename, 1000, args.debug) # Output shape and color data pcv.print_results(args.fmax, shape_header, shape_data) pcv.print_results(args.fmax, fvfm_header, fvfm_data)
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) brass_mask = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 49, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 150, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 100, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, 'v', device, args.debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, 'light', device, args.debug) device, brass_inv = pcv.invert(brass_thresh, device, args.debug) device, brass_masked = pcv.apply_mask(masked, brass_inv, 'white', device, args.debug) # Further mask soil and car device, masked_a = pcv.rgb2gray_lab(brass_masked, 'a', device, args.debug) device, soil_car1 = pcv.binary_threshold(masked_a, 128, 255, 'dark', device, args.debug) device, soil_car2 = pcv.binary_threshold(masked_a, 128, 255, 'light', device, args.debug) device, soil_car = pcv.logical_or(soil_car1, soil_car2, device, args.debug) device, soil_masked = pcv.apply_mask(brass_masked, soil_car, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, soil_a = pcv.rgb2gray_lab(soil_masked, 'a', device, args.debug) device, soil_b = pcv.rgb2gray_lab(soil_masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, soila_thresh = pcv.binary_threshold(soil_a, 124, 255, 'dark', device, args.debug) device, soilb_thresh = pcv.binary_threshold(soil_b, 148, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, soil_ab = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) device, soil_ab_cnt = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) # Fill small objects device, soil_cnt = pcv.fill(soil_ab, soil_ab_cnt, 200, device, args.debug) # Median Filter #device, soil_mblur = pcv.median_blur(soil_fill, 5, device, args.debug) #device, soil_cnt = pcv.median_blur(soil_fill, 5, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_masked, soil_cnt, 'white', device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( masked2, soil_cnt, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(img, 'rectangle', device, None, 'default', args.debug, True, 600, 450, -600, -350) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## Analysis ################ # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, args.outdir + '/' + filename) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, norm_slice = pcv.analyze_color( img, args.image, kept_mask, 256, device, args.debug, 'all', 'rgb', 'v', 'img', 300, args.outdir + '/' + filename) # Output shape and color data pcv.print_results(args.image, shape_header, shape_data) pcv.print_results(args.image, color_header, color_data)
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 0, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 0, device, args.debug) # Fill small objects #device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) # Fill small objects #device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, args.debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, 'dark', device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small noise device, ab_fill1 = pcv.fill(ab, ab_cnt, 2, device, args.debug) # Dilate to join small objects with larger ones device, ab_cnt1=pcv.dilate(ab_fill1, 3, 2, device, args.debug) device, ab_cnt2=pcv.dilate(ab_fill1, 3, 2, device, args.debug) # Fill dilated image mask device, ab_cnt3=pcv.fill(ab_cnt2,ab_cnt1,150,device,args.debug) device, masked2 = pcv.apply_mask(masked, ab_cnt3, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked2_a = pcv.rgb2gray_lab(masked2, 'a', device, args.debug) device, masked2_b = pcv.rgb2gray_lab(masked2, 'b', device, args.debug) # Threshold the green-magenta and blue images device, masked2a_thresh = pcv.binary_threshold(masked2_a, 127, 255, 'dark', device, args.debug) device, masked2b_thresh = pcv.binary_threshold(masked2_b, 128, 255, 'light', device, args.debug) device, ab_fill = pcv.logical_or(masked2a_thresh, masked2b_thresh, device, args.debug) # Identify objects device, id_objects,obj_hierarchy = pcv.find_objects(masked2, ab_fill, device, args.debug) # Define ROI device, roi1, roi_hierarchy= pcv.define_roi(masked2,'rectangle', device, None, 'default', args.debug,True, 550, 0,-600,-925) # Decide which objects to keep device,roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img,'partial',roi1,roi_hierarchy,id_objects,obj_hierarchy,device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## VIS Analysis ################ outfile=False if args.writeimg==True: outfile=args.outdir+"/"+filename # Find shape properties, output shape image (optional) device, shape_header,shape_data,shape_img = pcv.analyze_object(img, args.image, obj, mask, device,args.debug,outfile) # Shape properties relative to user boundary line (optional) device, boundary_header,boundary_data, boundary_img1= pcv.analyze_bound(img, args.image,obj, mask, 900, device,args.debug,outfile) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header,color_data,color_img= pcv.analyze_color(img, args.image, mask, 256, device, args.debug,None,'v','img',300,outfile) # Output shape and color data result=open(args.result,"a") result.write('\t'.join(map(str,shape_header))) result.write("\n") result.write('\t'.join(map(str,shape_data))) result.write("\n") for row in shape_img: result.write('\t'.join(map(str,row))) result.write("\n") result.write('\t'.join(map(str,color_header))) result.write("\n") result.write('\t'.join(map(str,color_data))) result.write("\n") result.write('\t'.join(map(str,boundary_header))) result.write("\n") result.write('\t'.join(map(str,boundary_data))) result.write("\n") result.write('\t'.join(map(str,boundary_img1))) result.write("\n") for row in color_img: result.write('\t'.join(map(str,row))) result.write("\n") ############################# Use VIS image mask for NIR image######################### # Find matching NIR image device, nirpath=pcv.get_nir(path,filename,device,args.debug) nir, path1, filename1=pcv.readimage(nirpath) nir2=cv2.imread(nirpath,-1) # Flip mask device, f_mask= pcv.flip(mask,"vertical",device,args.debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.11532,0.11532, device, args.debug) # position, and crop mask device,newmask=pcv.crop_position_mask(nir,nmask,device,57,2,"top","right",args.debug) # Identify objects device, nir_objects,nir_hierarchy = pcv.find_objects(nir, newmask, device, args.debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition(nir, nir_objects, nir_hierarchy, device, args.debug) ####################################### Analysis ############################################# outfile1=False if args.writeimg==True: outfile1=args.outdir+"/"+filename1 device,nhist_header, nhist_data,nir_imgs= pcv.analyze_NIR_intensity(nir2, filename1, nir_combinedmask, 256, device,False, args.debug, outfile1) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object(nir2, filename1, nir_combined, nir_combinedmask, device, args.debug, outfile1) coresult=open(args.coresult,"a") coresult.write('\t'.join(map(str,nhist_header))) coresult.write("\n") coresult.write('\t'.join(map(str,nhist_data))) coresult.write("\n") for row in nir_imgs: coresult.write('\t'.join(map(str,row))) coresult.write("\n") coresult.write('\t'.join(map(str,nshape_header))) coresult.write("\n") coresult.write('\t'.join(map(str,nshape_data))) coresult.write("\n") coresult.write('\t'.join(map(str,nir_shape))) coresult.write("\n")
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) # roi = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 150, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, args.debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 122, 255, 'dark', device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 133, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small objects device, ab_fill = pcv.fill(ab, ab_cnt, 200, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(masked, ab_fill, 'white', device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( masked2, ab_fill, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(img, 'rectangle', device, None, 'default', args.debug, True, 0, 0, 0, -900) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) # ############# Analysis ################ # output mask device, maskpath, mask_images = pcv.output_mask(device, img, mask, filename, args.outdir, True, args.debug) # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound( img, args.image, obj, mask, 830, device) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, # output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( img, args.image, mask, 256, device, args.debug, None, 'v', 'img', 300) result = open(args.result, "a") result.write('\t'.join(map(str, shape_header))) result.write("\n") result.write('\t'.join(map(str, shape_data))) result.write("\n") for row in mask_images: result.write('\t'.join(map(str, row))) result.write("\n") result.write('\t'.join(map(str, color_header))) result.write("\n") result.write('\t'.join(map(str, color_data))) result.write("\n") result.write('\t'.join(map(str, boundary_header))) result.write("\n") result.write('\t'.join(map(str, boundary_data))) result.write("\n") result.close()
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, "s", device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, "light", device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 0, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 0, device, args.debug) # Fill small objects # device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, "b", device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, "light", device, args.debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, "light", device, args.debug) # Fill small objects # device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, "white", device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, "a", device, args.debug) device, masked_b = pcv.rgb2gray_lab(masked, "b", device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, "dark", device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, "light", device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small noise device, ab_fill1 = pcv.fill(ab, ab_cnt, 2, device, args.debug) # Dilate to join small objects with larger ones device, ab_cnt1 = pcv.dilate(ab_fill1, 3, 2, device, args.debug) device, ab_cnt2 = pcv.dilate(ab_fill1, 3, 2, device, args.debug) # Fill dilated image mask device, ab_cnt3 = pcv.fill(ab_cnt2, ab_cnt1, 150, device, args.debug) device, masked2 = pcv.apply_mask(masked, ab_cnt3, "white", device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked2_a = pcv.rgb2gray_lab(masked2, "a", device, args.debug) device, masked2_b = pcv.rgb2gray_lab(masked2, "b", device, args.debug) # Threshold the green-magenta and blue images device, masked2a_thresh = pcv.binary_threshold(masked2_a, 127, 255, "dark", device, args.debug) device, masked2b_thresh = pcv.binary_threshold(masked2_b, 128, 255, "light", device, args.debug) device, ab_fill = pcv.logical_or(masked2a_thresh, masked2b_thresh, device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, ab_fill, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi( masked2, "rectangle", device, None, "default", args.debug, True, 500, 0, -600, -885 ) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, "partial", roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug ) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## VIS Analysis ################ outfile = False if args.writeimg == True: outfile = args.outdir + "/" + filename # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, outfile ) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound( img, args.image, obj, mask, 845, device, args.debug, outfile ) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( img, args.image, mask, 256, device, args.debug, None, "v", "img", 300, outfile ) # Output shape and color data result = open(args.result, "a") result.write("\t".join(map(str, shape_header))) result.write("\n") result.write("\t".join(map(str, shape_data))) result.write("\n") for row in shape_img: result.write("\t".join(map(str, row))) result.write("\n") result.write("\t".join(map(str, color_header))) result.write("\n") result.write("\t".join(map(str, color_data))) result.write("\n") result.write("\t".join(map(str, boundary_header))) result.write("\n") result.write("\t".join(map(str, boundary_data))) result.write("\n") result.write("\t".join(map(str, boundary_img1))) result.write("\n") for row in color_img: result.write("\t".join(map(str, row))) result.write("\n") result.close() ############################# Use VIS image mask for NIR image######################### # Find matching NIR image device, nirpath = pcv.get_nir(path, filename, device, args.debug) nir, path1, filename1 = pcv.readimage(nirpath) nir2 = cv2.imread(nirpath, -1) # Flip mask device, f_mask = pcv.flip(mask, "vertical", device, args.debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.1304, 0.1304, device, args.debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir, nmask, device, 65, 0, "top", "left", args.debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(nir, newmask, device, args.debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition(nir, nir_objects, nir_hierarchy, device, args.debug) ####################################### Analysis ############################################# outfile1 = False if args.writeimg == True: outfile1 = args.outdir + "/" + filename1 device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity( nir2, filename1, nir_combinedmask, 256, device, False, args.debug, outfile1 ) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object( nir2, filename1, nir_combined, nir_combinedmask, device, args.debug, outfile1 ) coresult = open(args.coresult, "a") coresult.write("\t".join(map(str, nhist_header))) coresult.write("\n") coresult.write("\t".join(map(str, nhist_data))) coresult.write("\n") for row in nir_imgs: coresult.write("\t".join(map(str, row))) coresult.write("\n") coresult.write("\t".join(map(str, nshape_header))) coresult.write("\n") coresult.write("\t".join(map(str, nshape_data))) coresult.write("\n") coresult.write("\t".join(map(str, nir_shape))) coresult.write("\n") coresult.close()
def process_sv_images_core(vis_id, vis_img, nir_id, nir_rgb, nir_cv2, traits, debug=None): # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(vis_img, 's', device, debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # Fill small objects # device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(vis_img, 'b', device, debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, 'light', device, debug) # Fill small objects # device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(vis_img, bs, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, 'dark', device, debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) # Fill small noise device, ab_fill1 = pcv.fill(ab, ab_cnt, 200, device, debug) # Dilate to join small objects with larger ones device, ab_cnt1 = pcv.dilate(ab_fill1, 3, 2, device, debug) device, ab_cnt2 = pcv.dilate(ab_fill1, 3, 2, device, debug) # Fill dilated image mask device, ab_cnt3 = pcv.fill(ab_cnt2, ab_cnt1, 150, device, debug) device, masked2 = pcv.apply_mask(masked, ab_cnt3, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked2_a = pcv.rgb2gray_lab(masked2, 'a', device, debug) device, masked2_b = pcv.rgb2gray_lab(masked2, 'b', device, debug) # Threshold the green-magenta and blue images device, masked2a_thresh = pcv.binary_threshold(masked2_a, 127, 255, 'dark', device, debug) device, masked2b_thresh = pcv.binary_threshold(masked2_b, 128, 255, 'light', device, debug) device, masked2a_thresh_blur = pcv.median_blur(masked2a_thresh, 5, device, debug) device, masked2b_thresh_blur = pcv.median_blur(masked2b_thresh, 13, device, debug) device, ab_fill = pcv.logical_or(masked2a_thresh_blur, masked2b_thresh_blur, device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, ab_fill, device, debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(masked2, 'rectangle', device, None, 'default', debug, True, 700, 0, -600, -300) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(vis_img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects device, obj, mask = pcv.object_composition(vis_img, roi_objects, hierarchy3, device, debug) ############## VIS Analysis ################ # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object(vis_img, vis_id, obj, mask, device, debug) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound(vis_img, vis_id, obj, mask, 384, device, debug) # Determine color properties: Histograms, Color Slices and # Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color(vis_img, vis_id, mask, 256, device, debug, None, 'v', 'img', 300) # Output shape and color data vis_traits = {} for i in range(1, len(shape_header)): vis_traits[shape_header[i]] = shape_data[i] for i in range(1, len(boundary_header)): vis_traits[boundary_header[i]] = boundary_data[i] for i in range(2, len(color_header)): vis_traits[color_header[i]] = serialize_color_data(color_data[i]) ############################# Use VIS image mask for NIR image######################### # Flip mask device, f_mask = pcv.flip(mask, "vertical", device, debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.1154905775, 0.1154905775, device, debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir_rgb, nmask, device, 30, 4, "top", "right", debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(nir_rgb, newmask, device, debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition(nir_rgb, nir_objects, nir_hierarchy, device, debug) ####################################### Analysis ############################################# device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity(nir_cv2, nir_id, nir_combinedmask, 256, device, False, debug) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object(nir_cv2, nir_id, nir_combined, nir_combinedmask, device, debug) nir_traits = {} for i in range(1, len(nshape_header)): nir_traits[nshape_header[i]] = nshape_data[i] for i in range(2, len(nhist_header)): nir_traits[nhist_header[i]] = serialize_color_data(nhist_data[i]) # Add data to traits table traits['sv_area'].append(vis_traits['area']) traits['hull_area'].append(vis_traits['hull-area']) traits['solidity'].append(vis_traits['solidity']) traits['height'].append(vis_traits['height_above_bound']) traits['perimeter'].append(vis_traits['perimeter']) return [vis_traits, nir_traits]
def process_sv_images_core(vis_id, vis_img, nir_id, nir_rgb, nir_cv2, traits, debug=None): # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(vis_img, 's', device, debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # Fill small objects # device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(vis_img, 'b', device, debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, 'light', device, debug) # Fill small objects # device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(vis_img, bs, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, 'dark', device, debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) # Fill small noise device, ab_fill1 = pcv.fill(ab, ab_cnt, 200, device, debug) # Dilate to join small objects with larger ones device, ab_cnt1 = pcv.dilate(ab_fill1, 3, 2, device, debug) device, ab_cnt2 = pcv.dilate(ab_fill1, 3, 2, device, debug) # Fill dilated image mask device, ab_cnt3 = pcv.fill(ab_cnt2, ab_cnt1, 150, device, debug) device, masked2 = pcv.apply_mask(masked, ab_cnt3, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked2_a = pcv.rgb2gray_lab(masked2, 'a', device, debug) device, masked2_b = pcv.rgb2gray_lab(masked2, 'b', device, debug) # Threshold the green-magenta and blue images device, masked2a_thresh = pcv.binary_threshold(masked2_a, 127, 255, 'dark', device, debug) device, masked2b_thresh = pcv.binary_threshold(masked2_b, 128, 255, 'light', device, debug) device, masked2a_thresh_blur = pcv.median_blur(masked2a_thresh, 5, device, debug) device, masked2b_thresh_blur = pcv.median_blur(masked2b_thresh, 13, device, debug) device, ab_fill = pcv.logical_or(masked2a_thresh_blur, masked2b_thresh_blur, device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( masked2, ab_fill, device, debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(masked2, 'rectangle', device, None, 'default', debug, True, 700, 0, -600, -300) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( vis_img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects device, obj, mask = pcv.object_composition(vis_img, roi_objects, hierarchy3, device, debug) ############## VIS Analysis ################ # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( vis_img, vis_id, obj, mask, device, debug) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound( vis_img, vis_id, obj, mask, 384, device, debug) # Determine color properties: Histograms, Color Slices and # Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( vis_img, vis_id, mask, 256, device, debug, None, 'v', 'img', 300) # Output shape and color data vis_traits = {} for i in range(1, len(shape_header)): vis_traits[shape_header[i]] = shape_data[i] for i in range(1, len(boundary_header)): vis_traits[boundary_header[i]] = boundary_data[i] for i in range(2, len(color_header)): vis_traits[color_header[i]] = serialize_color_data(color_data[i]) ############################# Use VIS image mask for NIR image######################### # Flip mask device, f_mask = pcv.flip(mask, "vertical", device, debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.1154905775, 0.1154905775, device, debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir_rgb, nmask, device, 30, 4, "top", "right", debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects( nir_rgb, newmask, device, debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition( nir_rgb, nir_objects, nir_hierarchy, device, debug) ####################################### Analysis ############################################# device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity( nir_cv2, nir_id, nir_combinedmask, 256, device, False, debug) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object( nir_cv2, nir_id, nir_combined, nir_combinedmask, device, debug) nir_traits = {} for i in range(1, len(nshape_header)): nir_traits[nshape_header[i]] = nshape_data[i] for i in range(2, len(nhist_header)): nir_traits[nhist_header[i]] = serialize_color_data(nhist_data[i]) # Add data to traits table traits['sv_area'].append(vis_traits['area']) traits['hull_area'].append(vis_traits['hull-area']) traits['solidity'].append(vis_traits['solidity']) traits['height'].append(vis_traits['height_above_bound']) traits['perimeter'].append(vis_traits['perimeter']) return [vis_traits, nir_traits]
def analyze_object_MF(img,imgname,obj,mask,line_position,device,debug=False,filename=False): # Outputs numeric properties for an input object (contour or grouped contours) # Also color classification? # img = image object (most likely the original), color(RGB) # imgname= name of image # obj = single or grouped contour object # line_position = boundary line # device = device number. Used to count steps in the pipeline # debug= True/False. If True, print image # filename= False or image name. If defined print image device += 1 ori_img=np.copy(img) if len(np.shape(img))==3: ix,iy,iz=np.shape(img) else: ix,iy=np.shape(img) # Change line postion to coordinate location on image line_position=int(ix)-int(line_position) # size is black and white image # size1 is dimensions of the image size = ix,iy,3 size1 = ix,iy background = np.zeros(size, dtype=np.uint8) background1 = np.zeros(size1, dtype=np.uint8) background2 = np.zeros(size1, dtype=np.uint8) # Check is object is touching image boundaries (QC) frame_background = np.zeros(size1, dtype=np.uint8) frame=frame_background+1 frame_contour,frame_heirarchy=cv2.findContours(frame,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) ptest=[] vobj=np.vstack(obj) for i,c in enumerate(vobj): xy=tuple(c) pptest=cv2.pointPolygonTest(frame_contour[0],xy, measureDist=False) ptest.append(pptest) in_bounds=all(c==1 for c in ptest) # Convex Hull hull = cv2.convexHull(obj) hull_vertices = len(hull) # Moments # m = cv2.moments(obj) m = cv2.moments(mask, binaryImage=True) ## Properties # Area area = m['m00'] if area: # Convex Hull area hull_area = cv2.contourArea(hull) # Solidity solidity = 1 if int(hull_area) != 0: solidity = area / hull_area # Perimeter perimeter = cv2.arcLength(obj, closed=True) # x and y position (bottom left?) and extent x (width) and extent y (height) x,y,width,height = cv2.boundingRect(obj) # Centroid (center of mass x, center of mass y) cmx,cmy = (m['m10']/m['m00'], m['m01']/m['m00']) # Ellipse center, axes, angle = cv2.fitEllipse(obj) major_axis = np.argmax(axes) minor_axis = 1 - major_axis major_axis_length = axes[major_axis] minor_axis_length = axes[minor_axis] eccentricity = np.sqrt(1 - (axes[minor_axis]/axes[major_axis]) ** 2) #Longest Axis: line through center of mass and point on the convex hull that is furthest away cv2.circle(background, (int(cmx),int(cmy)), 4, (255,255,255),-1) center_p = cv2.cvtColor(background, cv2.COLOR_BGR2GRAY) ret,centerp_binary = cv2.threshold(center_p, 0, 255, cv2.THRESH_BINARY) centerpoint,cpoint_h = cv2.findContours(centerp_binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) dist=[] vhull=np.vstack(hull) for i,c in enumerate(vhull): xy=tuple(c) pptest=cv2.pointPolygonTest(centerpoint[0],xy, measureDist=True) dist.append(pptest) abs_dist=np.absolute(dist) max_i=np.argmax(abs_dist) caliper_max_x, caliper_max_y=list(tuple(vhull[max_i])) caliper_mid_x, caliper_mid_y=[int(cmx),int(cmy)] xdiff = float(caliper_max_x-caliper_mid_x) ydiff= float(caliper_max_y-caliper_mid_y) if xdiff!=0: slope=(float(ydiff/xdiff)) if xdiff==0: slope=1 b_line=caliper_mid_y-(slope*caliper_mid_x) if slope==0: xintercept=0 xintercept1=0 yintercept='none' yintercept1='none' cv2.line(background1,(iy,caliper_mid_y),(0,caliper_mid_y),(255),1) else: xintercept=int(-b_line/slope) xintercept1=int((ix-b_line)/slope) yintercept='none' yintercept1='none' if 0<=xintercept<=iy and 0<=xintercept1<=iy: cv2.line(background1,(xintercept1,ix),(xintercept,0),(255),1) elif xintercept<0 or xintercept>iy or xintercept1<0 or xintercept1>iy: if xintercept<0 and 0<=xintercept1<=iy: yintercept=int(b_line) cv2.line(background1,(0,yintercept),(xintercept1,ix),(255),1) elif xintercept>iy and 0<=xintercept1<=iy: yintercept1=int((slope*iy)+b_line) cv2.line(background1,(iy,yintercept1),(xintercept1,ix),(255),1) elif 0<=xintercept<=iy and xintercept1<0: yintercept=int(b_line) cv2.line(background1,(0,yintercept),(xintercept,0),(255),1) elif 0<=xintercept<=iy and xintercept1>iy: yintercept1=int((slope*iy)+b_line) cv2.line(background1,(iy,yintercept1),(xintercept,0),(255),1) else: yintercept=int(b_line) yintercept1=int((slope*iy)+b_line) cv2.line(background1,(0,yintercept),(iy,yintercept1),(255),1) ret1,line_binary = cv2.threshold(background1, 0, 255, cv2.THRESH_BINARY) #print_image(line_binary,(str(device)+'_caliperfit.png')) cv2.drawContours(background2, [hull], -1, (255), -1) ret2,hullp_binary = cv2.threshold(background2, 0, 255, cv2.THRESH_BINARY) #print_image(hullp_binary,(str(device)+'_hull.png')) caliper=cv2.multiply(line_binary,hullp_binary) #print_image(caliper,(str(device)+'_caliperlength.png')) caliper_y,caliper_x=np.array(caliper.nonzero()) caliper_matrix=np.vstack((caliper_x,caliper_y)) caliper_transpose=np.transpose(caliper_matrix) caliper_length=len(caliper_transpose) caliper_transpose1 = np.lexsort((caliper_y, caliper_x)) caliper_transpose2 = [(caliper_x[i],caliper_y[i]) for i in caliper_transpose1] caliper_transpose=np.array(caliper_transpose2) ##### Measure Canopy Height height_ab = line_position - y # If height is greater than 20 pixels make 20 increments (5% intervals) if height_ab >= 20: inc = height_ab /20 # Define variable for max points and min points pts_max = [] pts_min = [] # Get max and min points for each of the intervals for i in range(1,20): if (i == 1): pt_max = y pt_min = y + (inc * i) else: pt_max = y + (inc * (i-1)) pt_min = y + (inc * i) # Put these in an array pts_max.append(pt_max) pts_min.append(pt_min) # Combine max and min into a set of tuples point_range = list(zip(pts_max,pts_min)) # define some list variables to fill row_median=[] row_ave=[] max_width=[] # For each of the 20 intervals for pt in point_range: # Get the lower and upper bounds (lower and higher in terms of value; low point is actually towards top of photo, higher is lower of photo) low_point, high_point = pt # Get all rows within these two points rows=[] # Get a continuous list of the values between the top and the bottom of the interval save as vals vals = list(range(low_point, high_point)) # For each row... get all coordinates from object contour that match row for v in vals: # Value is all entries that match the row value = obj[v == obj[:,0,1]] if len(value) > 0: # Could potentially be more than two points in all contour in each pixel row # Grab largest x coordinate (column) largest = value[:,0,0].max() # Grab smallest x coordinate (column) smallest = value[:,0,0].min() # Take the difference between the two (this is how far across the object is on this plane) row_width = largest - smallest # Append this value to a list rows.append(row_width) if len(value) == 0: row_width = 1 rows.append(row_width) # For each of the points find the median and average width row_median.append(np.median(np.array(rows))) row_ave.append(np.mean(np.array(rows))) max_width.append(np.max(np.array(rows))) # Get the indicie of the largest median/average x-axis value (if there is a tie it takes largest index) indice_median = row_median.index(max(row_median)) indice_ave = row_ave.index(max(row_ave)) median_value = row_median[indice_median] ave_value = row_ave[indice_ave] max_value = max_width[indice_ave] # Canopy height as the height at which the average pixel width across a scoring window is maximized indice_reported = point_range[indice_ave] # Now you can get indice of point_range and make plots (lower and higher in terms of value; low point is actually towards top of photo, higher is lower of photo) lp, hp = indice_reported # Report Canopy height as the average of the upper and lower values of the scoring window (lower and higher in terms of value; low point is actually towards top of photo, higher is lower of photo) canopy_height = (lp + hp)/2 # Define canopy width as mean value across scoring window canopy_width = ave_value # Find the center of the window w_center = (x+(x+int(max_value)))/2 each_side = ave_value/2 lside = w_center - each_side rside = w_center + each_side # Make rectangle and draw line at canopy height img_copy=np.copy(img) ix,iy,iz=np.shape(img) size = ix,iy,3 size1 = ix,iy background = np.zeros(size, dtype=np.uint8) background_ch = np.zeros(size1, dtype=np.uint8) # Make a gray scale image with color area masked out gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY) gray_rgb = cv2.cvtColor(gray,cv2.COLOR_GRAY2RGB) # Fill the rectable to be totally black (-1) cv2.rectangle(gray_rgb, (x, lp), (x+int(max_value), hp), (0,0,0), -1) cv2.rectangle(background_ch, (x, lp), (x+int(max_value), hp), (255,255,255), -1) device, masked_img = pcv.apply_mask(img_copy, background_ch, 'black', device, debug) # LOGICAL OR statement to combine background (gray_rgb) and the scoring window of canopy height (masked_img) device, example = pcv.logical_or(gray_rgb, masked_img, device, debug) # Draw scoring window rectangle cv2.rectangle(example, (x, lp), (x+int(max_value), hp), (255,0,0), 5) # Draw lines for height and max width in rectangle cv2.line(example, (int(lside), int(canopy_height)), (int(rside), int(canopy_height)), (0,0,255), 3) cv2.line(example, (int(w_center), int(canopy_height)), (int(w_center), int(y+height)), (0,0,255), 3) # Print image #cv2.imwrite('example_img.png', example) # If height is < 20 pixels Get widest point and report if height_ab < 20: #rows=[] # Get a continuous list of the values between the top and the bottom of the interval save as vals #vals = list(range(y, y+height_ab)) # For each row... get all coordinates from object contour that match row #for v in vals: # Value is all entries that match the row #value = obj[v == obj[:,0,1]] # Could potentially be more than two points in all contour in each pixel row # Grab largest x coordinate (column) #largest = value[:,0,0].max() # Grab smallest x coordinate (column) #smallest = value[:,0,0].min() # Take the difference between the two (this is how far across the object is on this plane) #row_width = largest - smallest # Append this value to a list #rows.append(row_width) # For each of the points find the median and average width (if there is a tie it takes largest index) #max_width = np.max(np.array(rows)) #canopy_height = rows.index(max(rows)) #canopy_width = max_width max_width = width canopy_height = height #else: # hull_area, solidity, perimeter, width, height, cmx, cmy = 'ND', 'ND', 'ND', 'ND', 'ND', 'ND', 'ND' # Change the values to reflect actual measurments not just point coordinates canopy_height = line_position - canopy_height centroid_y = line_position - cmy ellipse_y = line_position - center[1] #Store Shape Data shape_header=( 'HEADER_SHAPES', 'area', 'hull-area', 'solidity', 'perimeter', 'width', 'height', 'longest_axis', 'center-of-mass-x', 'center-of-mass-y', 'hull_vertices', 'in_bounds', 'ellipse_center_x', 'ellipse_center_y', 'ellipse_major_axis', 'ellipse_minor_axis', 'ellipse_angle', 'ellipse_eccentricity', 'canopy_height', 'canopy_width' ) shape_data = ( 'SHAPES_DATA', area, hull_area, solidity, perimeter, width, height, caliper_length, cmx, centroid_y, hull_vertices, in_bounds, center[0], ellipse_y, major_axis_length, minor_axis_length, angle, eccentricity, canopy_height, canopy_width ) analysis_images = [] #Draw properties if area and filename: cv2.drawContours(ori_img, obj, -1, (255,0,0), 1) cv2.drawContours(ori_img, [hull], -1, (0,0,255), 1) cv2.line(ori_img, (x,y), (x+width,y), (0,0,255), 1) cv2.line(ori_img, (int(cmx),y), (int(cmx),y+height), (0,0,255), 1) cv2.line(ori_img,(tuple(caliper_transpose[caliper_length-1])),(tuple(caliper_transpose[0])),(0,0,255),1) cv2.circle(ori_img, (int(cmx),int(cmy)), 10, (0,0,255), 1) # Output images with convex hull, extent x and y extention = filename.split('.')[-1] #out_file = str(filename[0:-4]) + '_shapes.' + extention out_file = str(filename[0:-4]) + '_shapes.jpg' out_file1 = str(filename[0:-4]) + '_mask.jpg' print_image(ori_img, out_file) analysis_images.append(['IMAGE', 'shapes', out_file]) print_image(mask,out_file1) analysis_images.append(['IMAGE','mask',out_file1]) else: pass if debug: cv2.drawContours(ori_img, obj, -1, (255,0,0), 1) cv2.drawContours(ori_img, [hull], -1, (0,0,255), 1) cv2.line(ori_img, (x,y), (x+width,y), (0,0,255), 1) cv2.line(ori_img, (int(cmx),y), (int(cmx),y+height), (0,0,255), 1) cv2.circle(ori_img, (int(cmx),int(cmy)), 10, (0,0,255), 1) cv2.line(ori_img,(tuple(caliper_transpose[caliper_length-1])),(tuple(caliper_transpose[0])),(0,0,255),1) print_image(ori_img,(str(device)+'_shapes.jpg')) return device, shape_header, shape_data, analysis_images
def process_tv_images_core(vis_id, vis_img, nir_id, nir_rgb, nir_cv2, brass_mask, traits, debug=None): device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(vis_img, 's', device, debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 75, 255, 'light', device, debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 150, device, debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(vis_img, 'b', device, debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 100, device, debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(vis_img, bs, 'white', device, debug) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, 'v', device, debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, 'light', device, debug) device, brass_inv = pcv.invert(brass_thresh, device, debug) device, brass_masked = pcv.apply_mask(masked, brass_inv, 'white', device, debug) # Further mask soil and car device, masked_a = pcv.rgb2gray_lab(brass_masked, 'a', device, debug) device, soil_car1 = pcv.binary_threshold(masked_a, 128, 255, 'dark', device, debug) device, soil_car2 = pcv.binary_threshold(masked_a, 128, 255, 'light', device, debug) device, soil_car = pcv.logical_or(soil_car1, soil_car2, device, debug) device, soil_masked = pcv.apply_mask(brass_masked, soil_car, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, soil_a = pcv.rgb2gray_lab(soil_masked, 'a', device, debug) device, soil_b = pcv.rgb2gray_lab(soil_masked, 'b', device, debug) # Threshold the green-magenta and blue images device, soila_thresh = pcv.binary_threshold(soil_a, 124, 255, 'dark', device, debug) device, soilb_thresh = pcv.binary_threshold(soil_b, 148, 255, 'light', device, debug) # Join the thresholded saturation and blue-yellow images (OR) device, soil_ab = pcv.logical_or(soila_thresh, soilb_thresh, device, debug) device, soil_ab_cnt = pcv.logical_or(soila_thresh, soilb_thresh, device, debug) # Fill small objects device, soil_cnt = pcv.fill(soil_ab, soil_ab_cnt, 300, device, debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_masked, soil_cnt, 'white', device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( masked2, soil_cnt, device, debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(vis_img, 'rectangle', device, None, 'default', debug, True, 600, 450, -600, -350) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( vis_img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects device, obj, mask = pcv.object_composition(vis_img, roi_objects, hierarchy3, device, debug) # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( vis_img, vis_id, obj, mask, device, debug) # Determine color properties device, color_header, color_data, color_img = pcv.analyze_color( vis_img, vis_id, mask, 256, device, debug, None, 'v', 'img', 300) # Output shape and color data vis_traits = {} for i in range(1, len(shape_header)): vis_traits[shape_header[i]] = shape_data[i] for i in range(2, len(color_header)): vis_traits[color_header[i]] = serialize_color_data(color_data[i]) ############################# Use VIS image mask for NIR image######################### # Flip mask device, f_mask = pcv.flip(mask, "horizontal", device, debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.116148, 0.116148, device, debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir_rgb, nmask, device, 15, 5, "top", "right", debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects( nir_rgb, newmask, device, debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition( nir_rgb, nir_objects, nir_hierarchy, device, debug) ####################################### Analysis ############################################# device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity( nir_cv2, nir_id, nir_combinedmask, 256, device, False, debug) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object( nir_cv2, nir_id, nir_combined, nir_combinedmask, device, debug) nir_traits = {} for i in range(1, len(nshape_header)): nir_traits[nshape_header[i]] = nshape_data[i] for i in range(2, len(nhist_header)): nir_traits[nhist_header[i]] = serialize_color_data(nhist_data[i]) # Add data to traits table traits['tv_area'] = vis_traits['area'] return [vis_traits, nir_traits]
# Channel 'b' should make the plant brighter over background. Otherwise, use a different channel. # Gaussian blur device, g_blur = pcv.gaussian_blur(device, b, (5,5), 0, None, debug) # Threshold the blue image device, img_thresh = pcv.triangle_auto_threshold(device, g_blur, 255, 'light', 20, args.debug) device, img_cnt = pcv.triangle_auto_threshold(device, g_blur, 255, 'light', 20, args.debug) # Modify the number 20 in both lines to an appropriate threshold that best separates plant from background # Fill small objects device, img_fill = pcv.fill(img_thresh, img_cnt, 50, device, args.debug) # Modify the number 50 to what best fills holes in the plant (white) and background (black) # Mask white-balanced image (here, based on blue channel) device, masked = pcv.apply_mask(corr_img, b_fill, 'white', device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked, img_fill, device, args.debug) # Define region of interest device, roi1, roi_hierarchy = pcv.define_roi(masked, 'rectangle', device, None, 'default', debug, True, 1000, 10, -1000, -300) # Modify the 4 numbers in the parenthesis to draw a square that surrounds or overlaps the entire plant, # but does not surround or overlap background. # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(corr_img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug) # Object combine kept objects
def main(): # Get options 1 args = options() # lee imagen 2 img, path, filename = pcv.readimage(args.image) # cv2.imshow("imagen",img) # pasos del pipeline 3 device = 0 debug=args.debug # Convert RGB to HSV and extract the Saturation channel 4 #convertir RGB a HSV y extraer el canal de saturacion device, s = pcv.rgb2gray_hsv(img, 's', device, debug) # cv2.imshow("rgb a hsv y extraer saturacion 4",s) # Threshold the Saturation image 5 #sacar imagen binaria del canal de saturacion device, s_thresh = pcv.binary_threshold(s, 85, 255, 'light', device, debug) # cv2.imshow("imagen binaria de hsv",s_thresh) # Median Filter 6 #sacar un filtro median_blur device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # cv2.imshow("s_mblur",s_mblur) # cv2.imshow("s_cnt",s_cnt) # Convert RGB to LAB and extract the Blue channel 7 #convertir RGB(imagen original) a LAB Y extraer el canal azul device, b = pcv.rgb2gray_lab(img, 'b', device, debug) # cv2.imshow("convertir RGB a LAB",b) # Threshold the blue image 8 #sacar imagen binaria de LAB imagen blue device, b_thresh = pcv.binary_threshold(b, 160, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 160, 255, 'light', device, debug) # cv2.imshow("imagen binaria de LAB",b_thresh) # cv2.imshow("imagen binaria",b_cnt) # Fill small objects #device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, debug) # Join the thresholded saturation and blue-yellow images 9 # device, bs = pcv.logical_or(s_mblur, b_cnt, device, debug) # cv2.imshow("suma logica s_mblur and b_cnt",bs) # Apply Mask (for vis images, mask_color=white) 10 device, masked = pcv.apply_mask(img, bs, 'white', device, debug) # cv2.imshow("aplicar mascara masked",masked) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels 11 device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, debug) # cv2.imshow("canal verde-magenta",masked_a) # cv2.imshow("canal azul-amarillo",masked_b) # Threshold the green-magenta and blue images 12 device, maskeda_thresh = pcv.binary_threshold(masked_a, 115, 255, 'dark', device, debug) device, maskeda_thresh1 = pcv.binary_threshold(masked_a, 135, 255, 'light', device, debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, debug) # cv2.imshow("threshold de canal verde-magenta dark",maskeda_thresh) # cv2.imshow("threshold de canal verde-magenta light",maskeda_thresh1) # cv2.imshow("threshold de canal azul-amarillo",maskedb_thresh) # Join the thresholded saturation and blue-yellow images (OR) 13 device, ab1 = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) device, ab = pcv.logical_or(maskeda_thresh1, ab1, device, debug) device, ab_cnt = pcv.logical_or(maskeda_thresh1, ab1, device, debug) # cv2.imshow("suma logica or 1",ab1) # cv2.imshow("suma logica or 2 ab",ab) # cv2.imshow("suma logica or 3 ab_cnt",ab_cnt) # Fill small objects 14 device, ab_fill = pcv.fill(ab, ab_cnt, 200, device, debug) # cv2.imshow("ab_fill",ab_fill) # Apply mask (for vis images, mask_color=white) 15 device, masked2 = pcv.apply_mask(masked, ab_fill, 'white', device, debug) # cv2.imshow("aplicar maskara2 white",masked2) ####################entendible hasta aqui###################### # Identify objects 16 solo print Se utiliza para identificar objetos (material vegetal) en una imagen. #imprime la imagen si uso print o no si uso plot no almacena la imagen pero en pritn si la aguarda #usa b_thresh y observa device,id_objects,obj_hierarchy = pcv.find_objects(masked2,ab_fill, device, debug) # Define ROI 17 solo print encierra el objeto detectato pero aun es manual aun no automatico device, roi1, roi_hierarchy= pcv.define_roi(masked2, 'rectangle', device, None, 'default', debug, True, 92, 80, -127, -343) # Decide which objects to keep 18 device,roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects 19 device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, debug) ############### Analysis ################ outfile=False if args.writeimg==True: outfile=args.outdir+"/"+filename # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object(img,'image', obj, mask, device,args.outdir + '/' + filename) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound(img, args.image, obj, mask, 1680, device, debug, args.outdir + '/' + filename) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color(img, args.image, kept_mask, 256, device, debug, 'all', 'v', 'img', 300, args.outdir + '/' + filename) #Write shape and color data to results file result=open(args.result,"a") result.write('\t'.join(map(str,shape_header))) result.write("\n") result.write('\t'.join(map(str,shape_data))) result.write("\n") for row in shape_img: result.write('\t'.join(map(str,row))) result.write("\n") result.write('\t'.join(map(str,color_header))) result.write("\n") result.write('\t'.join(map(str,color_data))) result.write("\n") for row in color_img: result.write('\t'.join(map(str,row))) result.write("\n") result.close() cv2.waitKey() cv2.destroyAllWindows()
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) brass_mask = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, "s", device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 49, 255, "light", device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 150, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, "b", device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, "light", device, args.debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, "light", device, args.debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 150, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, "white", device, args.debug) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, "v", device, args.debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, "light", device, args.debug) device, brass_inv = pcv.invert(brass_thresh, device, args.debug) device, brass_masked = pcv.apply_mask(masked, brass_inv, "white", device, args.debug) # Further mask soil and car device, masked_a = pcv.rgb2gray_lab(brass_masked, "a", device, args.debug) device, soil_car = pcv.binary_threshold(masked_a, 128, 255, "dark", device, args.debug) device, soil_masked = pcv.apply_mask(brass_masked, soil_car, "white", device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, soil_a = pcv.rgb2gray_lab(soil_masked, "a", device, args.debug) device, soil_b = pcv.rgb2gray_lab(soil_masked, "b", device, args.debug) # Threshold the green-magenta and blue images device, soila_thresh = pcv.binary_threshold(soil_a, 118, 255, "dark", device, args.debug) device, soilb_thresh = pcv.binary_threshold(soil_b, 150, 255, "light", device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, soil_ab = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) device, soil_ab_cnt = pcv.logical_or(soila_thresh, soilb_thresh, device, args.debug) # Fill small objects device, soil_cnt = pcv.fill(soil_ab, soil_ab_cnt, 75, device, args.debug) # Median Filter # device, soil_mblur = pcv.median_blur(soil_fill, 5, device, args.debug) # device, soil_cnt = pcv.median_blur(soil_fill, 5, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_masked, soil_cnt, "white", device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, soil_cnt, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi( img, "circle", device, None, "default", args.debug, True, 0, 0, -200, -200 ) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, "partial", roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug ) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## VIS Analysis ################ outfile = False if args.writeimg == True: outfile = args.outdir + "/" + filename # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, outfile ) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( img, args.image, mask, 256, device, args.debug, None, "v", "img", 300, outfile ) # Output shape and color data result = open(args.result, "a") result.write("\t".join(map(str, shape_header))) result.write("\n") result.write("\t".join(map(str, shape_data))) result.write("\n") for row in shape_img: result.write("\t".join(map(str, row))) result.write("\n") result.write("\t".join(map(str, color_header))) result.write("\n") result.write("\t".join(map(str, color_data))) result.write("\n") for row in color_img: result.write("\t".join(map(str, row))) result.write("\n") result.close() ############################# Use VIS image mask for NIR image######################### # Find matching NIR image device, nirpath = pcv.get_nir(path, filename, device, args.debug) nir, path1, filename1 = pcv.readimage(nirpath) nir2 = cv2.imread(nirpath, -1) # Flip mask device, f_mask = pcv.flip(mask, "horizontal", device, args.debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.1304, 0.1304, device, args.debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir, nmask, device, 9, 12, "top", "left", args.debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(nir, newmask, device, args.debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition(nir, nir_objects, nir_hierarchy, device, args.debug) ####################################### Analysis ############################################# outfile1 = False if args.writeimg == True: outfile1 = args.outdir + "/" + filename1 device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity( nir2, filename1, nir_combinedmask, 256, device, False, args.debug, outfile1 ) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object( nir2, filename1, nir_combined, nir_combinedmask, device, args.debug, outfile1 ) coresult = open(args.coresult, "a") coresult.write("\t".join(map(str, nhist_header))) coresult.write("\n") coresult.write("\t".join(map(str, nhist_data))) coresult.write("\n") for row in nir_imgs: coresult.write("\t".join(map(str, row))) coresult.write("\n") coresult.write("\t".join(map(str, nshape_header))) coresult.write("\n") coresult.write("\t".join(map(str, nshape_data))) coresult.write("\n") coresult.write("\t".join(map(str, nir_shape))) coresult.write("\n") coresult.close()
def process_tv_images(vis_img, nir_img, debug=False): """Process top-view images. Inputs: vis_img = An RGB image. nir_img = An NIR grayscale image. debug = None, print, or plot. Print = save to file, Plot = print to screen. :param vis_img: str :param nir_img: str :param debug: str :return: """ # Read image img, path, filename = pcv.readimage(vis_img) brass_mask = cv2.imread('mask_brass_tv_z1_L1.png') device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 75, 255, 'light', device, debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 150, device, debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 100, device, debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, debug) # Mask pesky brass piece device, brass_mask1 = pcv.rgb2gray_hsv(brass_mask, 'v', device, debug) device, brass_thresh = pcv.binary_threshold(brass_mask1, 0, 255, 'light', device, debug) device, brass_inv = pcv.invert(brass_thresh, device, debug) device, brass_masked = pcv.apply_mask(masked, brass_inv, 'white', device, debug) # Further mask soil and car device, masked_a = pcv.rgb2gray_lab(brass_masked, 'a', device, debug) device, soil_car1 = pcv.binary_threshold(masked_a, 128, 255, 'dark', device, debug) device, soil_car2 = pcv.binary_threshold(masked_a, 128, 255, 'light', device, debug) device, soil_car = pcv.logical_or(soil_car1, soil_car2, device, debug) device, soil_masked = pcv.apply_mask(brass_masked, soil_car, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, soil_a = pcv.rgb2gray_lab(soil_masked, 'a', device, debug) device, soil_b = pcv.rgb2gray_lab(soil_masked, 'b', device, debug) # Threshold the green-magenta and blue images device, soila_thresh = pcv.binary_threshold(soil_a, 124, 255, 'dark', device, debug) device, soilb_thresh = pcv.binary_threshold(soil_b, 148, 255, 'light', device, debug) # Join the thresholded saturation and blue-yellow images (OR) device, soil_ab = pcv.logical_or(soila_thresh, soilb_thresh, device, debug) device, soil_ab_cnt = pcv.logical_or(soila_thresh, soilb_thresh, device, debug) # Fill small objects device, soil_cnt = pcv.fill(soil_ab, soil_ab_cnt, 300, device, debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(soil_masked, soil_cnt, 'white', device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, soil_cnt, device, debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(img, 'rectangle', device, None, 'default', debug, True, 600, 450, -600, -350) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, debug) # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object(img, vis_img, obj, mask, device, debug) # Determine color properties device, color_header, color_data, color_img = pcv.analyze_color(img, vis_img, mask, 256, device, debug, None, 'v', 'img', 300) print('\t'.join(map(str, shape_header)) + '\n') print('\t'.join(map(str, shape_data)) + '\n') for row in shape_img: print('\t'.join(map(str, row)) + '\n') print('\t'.join(map(str, color_header)) + '\n') print('\t'.join(map(str, color_data)) + '\n') for row in color_img: print('\t'.join(map(str, row)) + '\n') ############################# Use VIS image mask for NIR image######################### # Read NIR image nir, path1, filename1 = pcv.readimage(nir_img) nir2 = cv2.imread(nir_img, -1) # Flip mask device, f_mask = pcv.flip(mask, "horizontal", device, debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.116148, 0.116148, device, debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir, nmask, device, 15, 5, "top", "right", debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(nir, newmask, device, debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition(nir, nir_objects, nir_hierarchy, device, debug) ####################################### Analysis ############################################# device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity(nir2, filename1, nir_combinedmask, 256, device, False, debug) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object(nir2, filename1, nir_combined, nir_combinedmask, device, debug) print('\t'.join(map(str,nhist_header)) + '\n') print('\t'.join(map(str,nhist_data)) + '\n') for row in nir_imgs: print('\t'.join(map(str,row)) + '\n') print('\t'.join(map(str,nshape_header)) + '\n') print('\t'.join(map(str,nshape_data)) + '\n') print('\t'.join(map(str,nir_shape)) + '\n')
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) # roi = cv2.imread(args.roi) # Pipeline step device = 0 ## Convert RGB to HSV and extract the Saturation channel # device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # ## Threshold the Saturation image # device, s_thresh = pcv.binary_threshold(s, 90, 255, 'dark', device, args.debug) # ## Median Filter # device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) # device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # ## Fill small objects ##device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # ## Convert RGB to LAB and extract the Blue channel # device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # ## Threshold the blue image # device, b_thresh = pcv.binary_threshold(b, 135, 255, 'light', device, args.debug) # device, b_cnt = pcv.binary_threshold(b, 135, 255, 'light', device, args.debug) # ##Fill small objects # device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # ## Join the thresholded saturation and blue-yellow images # device, bs = pcv.logical_or(s_mblur, b_cnt, device, args.debug) # ## Apply Mask (for vis images, mask_color=white) # device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(img, "a", device, args.debug) device, masked_b = pcv.rgb2gray_lab(img, "b", device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 135, 255, "dark", device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 140, 255, "light", device, args.debug) # # # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small objects device, ab_fill = pcv.fill(ab, ab_cnt, 1000, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(img, ab_fill, "white", device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, ab_fill, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi( masked2, "rectangle", device, None, "default", args.debug, True, 550, 0, -500, -300 ) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, "partial", roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug ) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############### Analysis ################ # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, args.outdir + "/" + filename ) # Shape properties relative to user boundary line (optional) # device, boundary_header,boundary_data, boundary_img1= pcv.analyze_bound(img, args.image,obj, mask, 1680, device,args.debug,args.outdir+'/'+filename) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, norm_slice = pcv.analyze_color( img, args.image, kept_mask, 256, device, args.debug, "all", "rgb", "v", "img", 300, args.outdir + "/" + filename ) # Output shape and color data pcv.print_results(args.image, shape_header, shape_data) pcv.print_results(args.image, color_header, color_data)
def process_sv_images(vis_img, nir_img, debug=None): """Process side-view images. Inputs: vis_img = An RGB image. nir_img = An NIR grayscale image. debug = None, print, or plot. Print = save to file, Plot = print to screen. :param vis_img: str :param nir_img: str :param debug: str :return: """ # Read VIS image img, path, filename = pcv.readimage(vis_img) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # Fill small objects # device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, 'light', device, debug) # Fill small objects # device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, 'dark', device, debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) # Fill small noise device, ab_fill1 = pcv.fill(ab, ab_cnt, 200, device, debug) # Dilate to join small objects with larger ones device, ab_cnt1 = pcv.dilate(ab_fill1, 3, 2, device, debug) device, ab_cnt2 = pcv.dilate(ab_fill1, 3, 2, device, debug) # Fill dilated image mask device, ab_cnt3 = pcv.fill(ab_cnt2, ab_cnt1, 150, device, debug) device, masked2 = pcv.apply_mask(masked, ab_cnt3, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked2_a = pcv.rgb2gray_lab(masked2, 'a', device, debug) device, masked2_b = pcv.rgb2gray_lab(masked2, 'b', device, debug) # Threshold the green-magenta and blue images device, masked2a_thresh = pcv.binary_threshold(masked2_a, 127, 255, 'dark', device, debug) device, masked2b_thresh = pcv.binary_threshold(masked2_b, 128, 255, 'light', device, debug) device, masked2a_thresh_blur = pcv.median_blur(masked2a_thresh, 5, device, debug) device, masked2b_thresh_blur = pcv.median_blur(masked2b_thresh, 13, device, debug) device, ab_fill = pcv.logical_or(masked2a_thresh_blur, masked2b_thresh_blur, device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, ab_fill, device, debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(masked2, 'rectangle', device, None, 'default', debug, True, 700, 0, -600, -300) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, debug) ############## VIS Analysis ################ # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object(img, vis_img, obj, mask, device, debug) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound(img, vis_img, obj, mask, 384, device, debug) # Determine color properties: Histograms, Color Slices and # Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color(img, vis_img, mask, 256, device, debug, None, 'v', 'img', 300) # Output shape and color data print('\t'.join(map(str, shape_header)) + '\n') print('\t'.join(map(str, shape_data)) + '\n') for row in shape_img: print('\t'.join(map(str, row)) + '\n') print('\t'.join(map(str, color_header)) + '\n') print('\t'.join(map(str, color_data)) + '\n') print('\t'.join(map(str, boundary_header)) + '\n') print('\t'.join(map(str, boundary_data)) + '\n') print('\t'.join(map(str, boundary_img1)) + '\n') for row in color_img: print('\t'.join(map(str, row)) + '\n') ############################# Use VIS image mask for NIR image######################### # Read NIR image nir, path1, filename1 = pcv.readimage(nir_img) nir2 = cv2.imread(nir_img, -1) # Flip mask device, f_mask = pcv.flip(mask, "vertical", device, debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.1154905775, 0.1154905775, device, debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir, nmask, device, 30, 4, "top", "right", debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(nir, newmask, device, debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition(nir, nir_objects, nir_hierarchy, device, debug) ####################################### Analysis ############################################# device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity(nir2, filename1, nir_combinedmask, 256, device, False, debug) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object(nir2, filename1, nir_combined, nir_combinedmask, device, debug) print('\t'.join(map(str, nhist_header)) + '\n') print('\t'.join(map(str, nhist_data)) + '\n') for row in nir_imgs: print('\t'.join(map(str, row)) + '\n') print('\t'.join(map(str, nshape_header)) + '\n') print('\t'.join(map(str, nshape_data)) + '\n') print('\t'.join(map(str, nir_shape)) + '\n')
def main(): # Get options args = options() if args.debug: print("Analyzing your image dude...") # Read image device = 0 img = cv2.imread(args.image, flags=0) path, img_name = os.path.split(args.image) # Read in image which is average of average of backgrounds img_bkgrd = cv2.imread("bkgrd_ave_z2500.png", flags=0) # NIR images for burnin2 are up-side down. This may be fixed in later experiments img = ndimage.rotate(img, 180) img_bkgrd = ndimage.rotate(img_bkgrd, 180) # Subtract the image from the image background to make the plant more prominent device, bkg_sub_img = pcv.image_subtract(img, img_bkgrd, device, args.debug) if args.debug: pcv.plot_hist(bkg_sub_img, "bkg_sub_img") device, bkg_sub_thres_img = pcv.binary_threshold(bkg_sub_img, 145, 255, "dark", device, args.debug) bkg_sub_thres_img = cv2.inRange(bkg_sub_img, 30, 220) if args.debug: cv2.imwrite("bkgrd_sub_thres.png", bkg_sub_thres_img) # device, bkg_sub_thres_img = pcv.binary_threshold_2_sided(img_bkgrd, 50, 190, device, args.debug) # if a region of interest is specified read it in roi = cv2.imread(args.roi) # Start by examining the distribution of pixel intensity values if args.debug: pcv.plot_hist(img, "hist_img") # Will intensity transformation enhance your ability to isolate object of interest by thesholding? device, he_img = pcv.HistEqualization(img, device, args.debug) if args.debug: pcv.plot_hist(he_img, "hist_img_he") # Laplace filtering (identify edges based on 2nd derivative) device, lp_img = pcv.laplace_filter(img, 1, 1, device, args.debug) if args.debug: pcv.plot_hist(lp_img, "hist_lp") # Lapacian image sharpening, this step will enhance the darkness of the edges detected device, lp_shrp_img = pcv.image_subtract(img, lp_img, device, args.debug) if args.debug: pcv.plot_hist(lp_shrp_img, "hist_lp_shrp") # Sobel filtering # 1st derivative sobel filtering along horizontal axis, kernel = 1, unscaled) device, sbx_img = pcv.sobel_filter(img, 1, 0, 1, 1, device, args.debug) if args.debug: pcv.plot_hist(sbx_img, "hist_sbx") # 1st derivative sobel filtering along vertical axis, kernel = 1, unscaled) device, sby_img = pcv.sobel_filter(img, 0, 1, 1, 1, device, args.debug) if args.debug: pcv.plot_hist(sby_img, "hist_sby") # Combine the effects of both x and y filters through matrix addition # This will capture edges identified within each plane and emphesize edges found in both images device, sb_img = pcv.image_add(sbx_img, sby_img, device, args.debug) if args.debug: pcv.plot_hist(sb_img, "hist_sb_comb_img") # Use a lowpass (blurring) filter to smooth sobel image device, mblur_img = pcv.median_blur(sb_img, 1, device, args.debug) device, mblur_invert_img = pcv.invert(mblur_img, device, args.debug) # combine the smoothed sobel image with the laplacian sharpened image # combines the best features of both methods as described in "Digital Image Processing" by Gonzalez and Woods pg. 169 device, edge_shrp_img = pcv.image_add(mblur_invert_img, lp_shrp_img, device, args.debug) if args.debug: pcv.plot_hist(edge_shrp_img, "hist_edge_shrp_img") # Perform thresholding to generate a binary image device, tr_es_img = pcv.binary_threshold(edge_shrp_img, 145, 255, "dark", device, args.debug) # Prepare a few small kernels for morphological filtering kern = np.zeros((3, 3), dtype=np.uint8) kern1 = np.copy(kern) kern1[1, 1:3] = 1 kern2 = np.copy(kern) kern2[1, 0:2] = 1 kern3 = np.copy(kern) kern3[0:2, 1] = 1 kern4 = np.copy(kern) kern4[1:3, 1] = 1 # Prepare a larger kernel for dilation kern[1, 0:3] = 1 kern[0:3, 1] = 1 # Perform erosion with 4 small kernels device, e1_img = pcv.erode(tr_es_img, kern1, 1, device, args.debug) device, e2_img = pcv.erode(tr_es_img, kern2, 1, device, args.debug) device, e3_img = pcv.erode(tr_es_img, kern3, 1, device, args.debug) device, e4_img = pcv.erode(tr_es_img, kern4, 1, device, args.debug) # Combine eroded images device, c12_img = pcv.logical_or(e1_img, e2_img, device, args.debug) device, c123_img = pcv.logical_or(c12_img, e3_img, device, args.debug) device, c1234_img = pcv.logical_or(c123_img, e4_img, device, args.debug) # Perform dilation # device, dil_img = pcv.dilate(c1234_img, kern, 1, device, args.debug) device, comb_img = pcv.logical_or(c1234_img, bkg_sub_thres_img, device, args.debug) # Get masked image # The dilated image may contain some pixels which are not plant device, masked_erd = pcv.apply_mask(img, comb_img, "black", device, args.debug) # device, masked_erd_dil = pcv.apply_mask(img, dil_img, 'black', device, args.debug) # Need to remove the edges of the image, we did that by generating a set of rectangles to mask the edges # img is (254 X 320) # mask for the bottom of the image device, box1_img, rect_contour1, hierarchy1 = pcv.rectangle_mask(img, (120, 184), (215, 252), device, args.debug) # mask for the left side of the image device, box2_img, rect_contour2, hierarchy2 = pcv.rectangle_mask(img, (1, 1), (85, 252), device, args.debug) # mask for the right side of the image device, box3_img, rect_contour3, hierarchy3 = pcv.rectangle_mask(img, (240, 1), (318, 252), device, args.debug) # mask the edges device, box4_img, rect_contour4, hierarchy4 = pcv.border_mask(img, (1, 1), (318, 252), device, args.debug) # combine boxes to filter the edges and car out of the photo device, bx12_img = pcv.logical_or(box1_img, box2_img, device, args.debug) device, bx123_img = pcv.logical_or(bx12_img, box3_img, device, args.debug) device, bx1234_img = pcv.logical_or(bx123_img, box4_img, device, args.debug) device, inv_bx1234_img = pcv.invert(bx1234_img, device, args.debug) # Make a ROI around the plant, include connected objects # Apply the box mask to the image # device, masked_img = pcv.apply_mask(masked_erd_dil, inv_bx1234_img, 'black', device, args.debug) device, edge_masked_img = pcv.apply_mask(masked_erd, inv_bx1234_img, "black", device, args.debug) device, roi_img, roi_contour, roi_hierarchy = pcv.rectangle_mask(img, (120, 75), (200, 184), device, args.debug) plant_objects, plant_hierarchy = cv2.findContours(edge_masked_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) device, roi_objects, hierarchy5, kept_mask, obj_area = pcv.roi_objects( img, "partial", roi_contour, roi_hierarchy, plant_objects, plant_hierarchy, device, args.debug ) # Apply the box mask to the image # device, masked_img = pcv.apply_mask(masked_erd_dil, inv_bx1234_img, 'black', device, args.debug) device, masked_img = pcv.apply_mask(kept_mask, inv_bx1234_img, "black", device, args.debug) rgb = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) # Generate a binary to send to the analysis function device, mask = pcv.binary_threshold(masked_img, 1, 255, "light", device, args.debug) mask3d = np.copy(mask) plant_objects_2, plant_hierarchy_2 = cv2.findContours(mask3d, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) device, o, m = pcv.object_composition(rgb, roi_objects, hierarchy5, device, args.debug) ### Analysis ### device, hist_header, hist_data, h_norm = pcv.analyze_NIR_intensity( img, args.image, mask, 256, device, args.debug, args.outdir + "/" + img_name ) device, shape_header, shape_data, ori_img = pcv.analyze_object( rgb, args.image, o, m, device, args.debug, args.outdir + "/" + img_name ) pcv.print_results(args.image, hist_header, hist_data) pcv.print_results(args.image, shape_header, shape_data)
def process_sv_images(session, url, vis_id, nir_id, traits, debug=None): """Process side-view images from Clowder. Inputs: session = requests session object url = Clowder URL vis_id = The Clowder ID of an RGB image nir_img = The Clowder ID of an NIR grayscale image traits = traits table (dictionary) debug = None, print, or plot. Print = save to file, Plot = print to screen :param session: requests session object :param url: str :param vis_id: str :param nir_id: str :param traits: dict :param debug: str :return traits: dict """ # Read VIS image from Clowder vis_r = session.get(posixpath.join(url, "api/files", vis_id), stream=True) img_array = np.asarray(bytearray(vis_r.content), dtype="uint8") img = cv2.imdecode(img_array, -1) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, debug) # Fill small objects # device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, 'light', device, debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, 'light', device, debug) # Fill small objects # device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, 'dark', device, debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, debug) # Fill small noise device, ab_fill1 = pcv.fill(ab, ab_cnt, 200, device, debug) # Dilate to join small objects with larger ones device, ab_cnt1 = pcv.dilate(ab_fill1, 3, 2, device, debug) device, ab_cnt2 = pcv.dilate(ab_fill1, 3, 2, device, debug) # Fill dilated image mask device, ab_cnt3 = pcv.fill(ab_cnt2, ab_cnt1, 150, device, debug) device, masked2 = pcv.apply_mask(masked, ab_cnt3, 'white', device, debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked2_a = pcv.rgb2gray_lab(masked2, 'a', device, debug) device, masked2_b = pcv.rgb2gray_lab(masked2, 'b', device, debug) # Threshold the green-magenta and blue images device, masked2a_thresh = pcv.binary_threshold(masked2_a, 127, 255, 'dark', device, debug) device, masked2b_thresh = pcv.binary_threshold(masked2_b, 128, 255, 'light', device, debug) device, masked2a_thresh_blur = pcv.median_blur(masked2a_thresh, 5, device, debug) device, masked2b_thresh_blur = pcv.median_blur(masked2b_thresh, 13, device, debug) device, ab_fill = pcv.logical_or(masked2a_thresh_blur, masked2b_thresh_blur, device, debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects(masked2, ab_fill, device, debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(masked2, 'rectangle', device, None, 'default', debug, True, 700, 0, -600, -300) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, debug) ############## VIS Analysis ################ # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object(img, vis_id, obj, mask, device, debug) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound(img, vis_id, obj, mask, 384, device, debug) # Determine color properties: Histograms, Color Slices and # Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color(img, vis_id, mask, 256, device, debug, None, 'v', 'img', 300) # Output shape and color data vis_traits = {} for i in range(1, len(shape_header)): vis_traits[shape_header[i]] = shape_data[i] for i in range(1, len(boundary_header)): vis_traits[boundary_header[i]] = boundary_data[i] for i in range(2, len(color_header)): vis_traits[color_header[i]] = serialize_color_data(color_data[i]) #print(vis_traits) add_plantcv_metadata(session, url, vis_id, vis_traits) ############################# Use VIS image mask for NIR image######################### # Read NIR image from Clowder nir_r = session.get(posixpath.join(url, "api/files", nir_id), stream=True) nir_array = np.asarray(bytearray(nir_r.content), dtype="uint8") nir = cv2.imdecode(nir_array, -1) nir_rgb = cv2.cvtColor(nir, cv2.COLOR_GRAY2BGR) # Flip mask device, f_mask = pcv.flip(mask, "vertical", device, debug) # Reize mask device, nmask = pcv.resize(f_mask, 0.1154905775, 0.1154905775, device, debug) # position, and crop mask device, newmask = pcv.crop_position_mask(nir_rgb, nmask, device, 30, 4, "top", "right", debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(nir_rgb, newmask, device, debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition(nir_rgb, nir_objects, nir_hierarchy, device, debug) ####################################### Analysis ############################################# device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity(nir, nir_id, nir_combinedmask, 256, device, False, debug) device, nshape_header, nshape_data, nir_shape = pcv.analyze_object(nir, nir_id, nir_combined, nir_combinedmask, device, debug) nir_traits = {} for i in range(1, len(nshape_header)): nir_traits[nshape_header[i]] = nshape_data[i] for i in range(2, len(nhist_header)): nir_traits[nhist_header[i]] = serialize_color_data(nhist_data[i]) #print(nir_traits) add_plantcv_metadata(session, url, nir_id, nir_traits) # Add data to traits table traits['sv_area'].append(vis_traits['area']) traits['hull_area'].append(vis_traits['hull-area']) traits['solidity'].append(vis_traits['solidity']) traits['height'].append(vis_traits['height_above_bound']) traits['perimeter'].append(vis_traits['perimeter']) return traits
def main(): # Get options args = options() # Read image img = cv2.imread(args.image) roi = cv2.imread(args.roi) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 5, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 5, device, args.debug) # Fill small objects device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 138, 255, 'light', device, args.debug) # Fill small objects device, b_fill = pcv.fill(b_thresh, b_cnt, 150, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_fill, b_fill, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, args.debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 122, 255, 'dark', device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 133, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small objects device, ab_fill = pcv.fill(ab, ab_cnt, 200, device, args.debug) # Apply mask (for vis images, mask_color=white) device, masked2 = pcv.apply_mask(masked, ab_fill, 'white', device, args.debug) # Identify objects device, id_objects,obj_hierarchy = pcv.find_objects(masked2, ab_fill, device, args.debug) # Define ROI device, roi1, roi_hierarchy= pcv.define_roi(img,'rectangle', device, None, 'default', args.debug,False, 0, 0,0,0) # Decide which objects to keep device,roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img,'partial',roi1,roi_hierarchy,id_objects,obj_hierarchy,device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## Analysis ################ # Find shape properties, output shape image (optional) device, shape_header,shape_data,shape_img = pcv.analyze_object(img, args.image, obj, mask, device,args.debug,True) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header,color_data,norm_slice= pcv.analyze_color(img, args.image, kept_mask, 256, device, args.debug,'all','rgb','v') # Output shape and color data pcv.print_results(args.image, shape_header, shape_data) pcv.print_results(args.image, color_header, color_data)
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) # Pipeline step device = 0 # Convert RGB to HSV and extract the Saturation channel device, s = pcv.rgb2gray_hsv(img, 's', device, args.debug) # Threshold the Saturation image device, s_thresh = pcv.binary_threshold(s, 36, 255, 'light', device, args.debug) # Median Filter device, s_mblur = pcv.median_blur(s_thresh, 0, device, args.debug) device, s_cnt = pcv.median_blur(s_thresh, 0, device, args.debug) # Fill small objects #device, s_fill = pcv.fill(s_mblur, s_cnt, 0, device, args.debug) # Convert RGB to LAB and extract the Blue channel device, b = pcv.rgb2gray_lab(img, 'b', device, args.debug) # Threshold the blue image device, b_thresh = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) device, b_cnt = pcv.binary_threshold(b, 137, 255, 'light', device, args.debug) # Fill small objects #device, b_fill = pcv.fill(b_thresh, b_cnt, 10, device, args.debug) # Join the thresholded saturation and blue-yellow images device, bs = pcv.logical_and(s_mblur, b_cnt, device, args.debug) # Apply Mask (for vis images, mask_color=white) device, masked = pcv.apply_mask(img, bs, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked_a = pcv.rgb2gray_lab(masked, 'a', device, args.debug) device, masked_b = pcv.rgb2gray_lab(masked, 'b', device, args.debug) # Threshold the green-magenta and blue images device, maskeda_thresh = pcv.binary_threshold(masked_a, 127, 255, 'dark', device, args.debug) device, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', device, args.debug) # Join the thresholded saturation and blue-yellow images (OR) device, ab = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) device, ab_cnt = pcv.logical_or(maskeda_thresh, maskedb_thresh, device, args.debug) # Fill small noise device, ab_fill1 = pcv.fill(ab, ab_cnt, 2, device, args.debug) # Dilate to join small objects with larger ones device, ab_cnt1 = pcv.dilate(ab_fill1, 3, 2, device, args.debug) device, ab_cnt2 = pcv.dilate(ab_fill1, 3, 2, device, args.debug) # Fill dilated image mask device, ab_cnt3 = pcv.fill(ab_cnt2, ab_cnt1, 150, device, args.debug) img2 = np.copy(img) device, masked2 = pcv.apply_mask(img2, ab_cnt3, 'white', device, args.debug) # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels device, masked2_a = pcv.rgb2gray_lab(masked2, 'a', device, args.debug) device, masked2_b = pcv.rgb2gray_lab(masked2, 'b', device, args.debug) # Threshold the green-magenta and blue images device, masked2a_thresh = pcv.binary_threshold(masked2_a, 127, 255, 'dark', device, args.debug) device, masked2b_thresh = pcv.binary_threshold(masked2_b, 128, 255, 'light', device, args.debug) device, ab_fill = pcv.logical_or(masked2a_thresh, masked2b_thresh, device, args.debug) # Identify objects device, id_objects, obj_hierarchy = pcv.find_objects( masked2, ab_fill, device, args.debug) # Define ROI device, roi1, roi_hierarchy = pcv.define_roi(masked2, 'rectangle', device, None, 'default', args.debug, True, 650, 10, -600, -340) # Decide which objects to keep device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, args.debug) # Object combine kept objects device, obj, mask = pcv.object_composition(img, roi_objects, hierarchy3, device, args.debug) ############## Landmarks ################ device, points = pcv.acute_vertex(obj, 40, 30, 40, img, device, args.debug) boundary_line = 290 # Use acute fxn to estimate tips device, points_r, centroid_r, bline_r = pcv.scale_features( obj, mask, points, boundary_line, device, args.debug) # Get number of points tips = len(points_r) # Use turgor_proxy fxn to get distances device, vert_ave_c, hori_ave_c, euc_ave_c, ang_ave_c, vert_ave_b, hori_ave_b, euc_ave_b, ang_ave_b = pcv.turgor_proxy( points_r, centroid_r, bline_r, device, args.debug) # Get pseudomarkers along the y-axis device, left, right, center_h = pcv.y_axis_pseudolandmarks( obj, mask, img, device, args.debug) # Re-scale the points device, left_r, left_cr, left_br = pcv.scale_features( obj, mask, left, boundary_line, device, args.debug) device, right_r, right_cr, right_br = pcv.scale_features( obj, mask, right, boundary_line, device, args.debug) device, center_hr, center_hcr, center_hbr = pcv.scale_features( obj, mask, center_h, boundary_line, device, args.debug) # Get pseudomarkers along the x-axis device, top, bottom, center_v = pcv.x_axis_pseudolandmarks( obj, mask, img, device, args.debug) # Re-scale the points device, top_r, top_cr, top_br = pcv.scale_features(obj, mask, top, boundary_line, device, args.debug) device, bottom_r, bottom_cr, bottom_br = pcv.scale_features( obj, mask, bottom, boundary_line, device, args.debug) device, center_vr, center_vcr, center_vbr = pcv.scale_features( obj, mask, center_v, boundary_line, device, args.debug) ## Need to convert the points into a list of tuples format to match the scaled points points = points.reshape(len(points), 2) points = points.tolist() temp_out = [] for p in points: p = tuple(p) temp_out.append(p) points = temp_out left = left.reshape(20, 2) left = left.tolist() temp_out = [] for l in left: l = tuple(l) temp_out.append(l) left = temp_out right = right.reshape(20, 2) right = right.tolist() temp_out = [] for r in right: r = tuple(r) temp_out.append(r) right = temp_out center_h = center_h.reshape(20, 2) center_h = center_h.tolist() temp_out = [] for ch in center_h: ch = tuple(ch) temp_out.append(ch) center_h = temp_out ## Need to convert the points into a list of tuples format to match the scaled points top = top.reshape(20, 2) top = top.tolist() temp_out = [] for t in top: t = tuple(t) temp_out.append(t) top = temp_out bottom = bottom.reshape(20, 2) bottom = bottom.tolist() temp_out = [] for b in bottom: b = tuple(b) temp_out.append(b) bottom = temp_out center_v = center_v.reshape(20, 2) center_v = center_v.tolist() temp_out = [] for cvr in center_v: cvr = tuple(cvr) temp_out.append(cvr) center_v = temp_out #Store Landmark Data landmark_header = ('HEADER_LANDMARK', 'tip_points', 'tip_points_r', 'centroid_r', 'baseline_r', 'tip_number', 'vert_ave_c', 'hori_ave_c', 'euc_ave_c', 'ang_ave_c', 'vert_ave_b', 'hori_ave_b', 'euc_ave_b', 'ang_ave_b', 'left_lmk', 'right_lmk', 'center_h_lmk', 'left_lmk_r', 'right_lmk_r', 'center_h_lmk_r', 'top_lmk', 'bottom_lmk', 'center_v_lmk', 'top_lmk_r', 'bottom_lmk_r', 'center_v_lmk_r') landmark_data = ('LANDMARK_DATA', points, points_r, centroid_r, bline_r, tips, vert_ave_c, hori_ave_c, euc_ave_c, ang_ave_c, vert_ave_b, hori_ave_b, euc_ave_b, ang_ave_b, left, right, center_h, left_r, right_r, center_hr, top, bottom, center_v, top_r, bottom_r, center_vr) ############## VIS Analysis ################ outfile = False #if args.writeimg==True: #outfile=args.outdir+"/"+filename # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, args.image, obj, mask, device, args.debug, outfile) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img1 = pcv.analyze_bound( img, args.image, obj, mask, 290, device, args.debug, outfile) # Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional) device, color_header, color_data, color_img = pcv.analyze_color( img, args.image, mask, 256, device, args.debug, None, 'v', 'img', 300, outfile) # Output shape and color data result = open(args.result, "a") result.write('\t'.join(map(str, shape_header))) result.write("\n") result.write('\t'.join(map(str, shape_data))) result.write("\n") for row in shape_img: result.write('\t'.join(map(str, row))) result.write("\n") result.write('\t'.join(map(str, color_header))) result.write("\n") result.write('\t'.join(map(str, color_data))) result.write("\n") result.write('\t'.join(map(str, boundary_header))) result.write("\n") result.write('\t'.join(map(str, boundary_data))) result.write("\n") result.write('\t'.join(map(str, boundary_img1))) result.write("\n") for row in color_img: result.write('\t'.join(map(str, row))) result.write("\n") result.write('\t'.join(map(str, landmark_header))) result.write("\n") result.write('\t'.join(map(str, landmark_data))) result.write("\n") result.close()