def test_plantcv_dilate(): img = cv2.imread(os.path.join(TEST_DATA, TEST_INPUT_BINARY), -1) device, dilate_img = pcv.dilate(img=img, kernel=5, i=1, device=0, debug=None) # Assert that the output image has the dimensions of the input image if all([i == j] for i, j in zip(np.shape(dilate_img), TEST_BINARY_DIM)): # Assert that the image is binary if all([i == j] for i, j in zip(np.unique(dilate_img), [0, 255])): assert 1 else: assert 0 else: assert 0
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(): # 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, 550, 10, -600, -907) # 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, 40, 40, img, device, args.debug) boundary_line = 900 # 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, 935, 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(): # Initialize device device = 0 # Parse command-line options args = options() # Read image img, path, filename = pcv.readimage(filename=args.image, debug=args.debug) # Convert RGB to LAB and extract the Blue-Yellow channel device, blue_channel = pcv.rgb2gray_lab(img=img, channel="b", device=device, debug=args.debug) # Threshold the blue image using the triangle autothreshold method device, blue_tri = pcv.triangle_auto_threshold(device=device, img=blue_channel, maxvalue=255, object_type="light", xstep=1, debug=args.debug) # Extract core plant region from the image to preserve delicate plant features during filtering device += 1 plant_region = blue_tri[0:1750, 600:2080] if args.debug is not None: pcv.print_image(filename=str(device) + "_extract_plant_region.png", img=plant_region) # Use a Gaussian blur to disrupt the strong edge features in the cabinet device, blur_gaussian = pcv.gaussian_blur(device=device, img=blue_tri, ksize=(3, 3), sigmax=0, sigmay=None, debug=args.debug) # Threshold the blurred image to remove features that were blurred device, blur_thresholded = pcv.binary_threshold(img=blur_gaussian, threshold=250, maxValue=255, object_type="light", device=device, debug=args.debug) # Add the plant region back in to the filtered image device += 1 blur_thresholded[0:1750, 600:2080] = plant_region if args.debug is not None: pcv.print_image(filename=str(device) + "_replace_plant_region.png", img=blur_thresholded) # Fill small noise device, blue_fill_50 = pcv.fill(img=np.copy(blur_thresholded), mask=np.copy(blur_thresholded), size=50, device=device, debug=args.debug) # Identify objects device, contours, contour_hierarchy = pcv.find_objects(img=img, mask=blue_fill_50, device=device, debug=args.debug) # Define ROI device, roi, roi_hierarchy = pcv.define_roi(img=img, shape="rectangle", device=device, roi=None, roi_input="default", debug=args.debug, adjust=True, x_adj=565, y_adj=0, w_adj=-490, h_adj=-250) # Decide which objects to keep device, roi_contours, roi_contour_hierarchy, _, _ = pcv.roi_objects( img=img, roi_type="partial", roi_contour=roi, roi_hierarchy=roi_hierarchy, object_contour=contours, obj_hierarchy=contour_hierarchy, device=device, debug=args.debug) # If there are no contours left we cannot measure anything if len(roi_contours) > 0: # Object combine kept objects device, plant_contour, plant_mask = pcv.object_composition( img=img, contours=roi_contours, hierarchy=roi_contour_hierarchy, device=device, debug=args.debug) outfile = False if args.writeimg: outfile = args.outdir + "/" + filename # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img=img, imgname=args.image, obj=plant_contour, mask=plant_mask, device=device, debug=args.debug, filename=outfile) # Shape properties relative to user boundary line (optional) device, boundary_header, boundary_data, boundary_img = pcv.analyze_bound( img=img, imgname=args.image, obj=plant_contour, mask=plant_mask, line_position=440, device=device, debug=args.debug, filename=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=img, imgname=args.image, mask=plant_mask, bins=256, device=device, debug=args.debug, hist_plot_type=None, pseudo_channel="v", pseudo_bkg="img", resolution=300, filename=outfile) # Output shape and color data result = open(args.result, "a") result.write('\t'.join(map(str, shape_header)) + "\n") result.write('\t'.join(map(str, shape_data)) + "\n") for row in shape_img: result.write('\t'.join(map(str, row)) + "\n") result.write('\t'.join(map(str, color_header)) + "\n") result.write('\t'.join(map(str, color_data)) + "\n") result.write('\t'.join(map(str, boundary_header)) + "\n") result.write('\t'.join(map(str, boundary_data)) + "\n") result.write('\t'.join(map(str, boundary_img)) + "\n") for row in color_img: result.write('\t'.join(map(str, row)) + "\n") result.close() # Find matching NIR image device, nirpath = pcv.get_nir(path=path, filename=filename, device=device, debug=args.debug) nir_rgb, nir_path, nir_filename = pcv.readimage(nirpath) nir_img = cv2.imread(nirpath, 0) # Make mask glovelike in proportions via dilation device, d_mask = pcv.dilate(plant_mask, kernel=1, i=0, device=device, debug=args.debug) # Resize mask prop2, prop1 = conv_ratio() device, nmask = pcv.resize(img=d_mask, resize_x=prop1, resize_y=prop2, device=device, debug=args.debug) # Convert the resized mask to a binary mask device, bmask = pcv.binary_threshold(img=nmask, threshold=0, maxValue=255, object_type="light", device=device, debug=args.debug) device, crop_img = crop_sides_equally(mask=bmask, nir=nir_img, device=device, debug=args.debug) # position, and crop mask device, newmask = pcv.crop_position_mask(img=nir_img, mask=crop_img, device=device, x=34, y=9, v_pos="top", h_pos="right", debug=args.debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(img=nir_rgb, mask=newmask, device=device, debug=args.debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition( img=nir_rgb, contours=nir_objects, hierarchy=nir_hierarchy, device=device, debug=args.debug) if args.writeimg: outfile = args.outdir + "/" + nir_filename # Analyze NIR signal data device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity( img=nir_img, rgbimg=nir_rgb, mask=nir_combinedmask, bins=256, device=device, histplot=False, debug=args.debug, filename=outfile) # Analyze the shape of the plant contour from the NIR image device, nshape_header, nshape_data, nir_shape = pcv.analyze_object( img=nir_img, imgname=nir_filename, obj=nir_combined, mask=nir_combinedmask, device=device, debug=args.debug, filename=outfile) # Write NIR data to co-results file coresult = open(args.coresult, "a") coresult.write('\t'.join(map(str, nhist_header)) + "\n") coresult.write('\t'.join(map(str, nhist_data)) + "\n") for row in nir_imgs: coresult.write('\t'.join(map(str, row)) + "\n") coresult.write('\t'.join(map(str, nshape_header)) + "\n") coresult.write('\t'.join(map(str, nshape_data)) + "\n") coresult.write('\t'.join(map(str, nir_shape)) + "\n") coresult.close()
def main(): # Initialize device device = 0 # Parse command-line options args = options() # Read image img, path, filename = pcv.readimage(filename=args.image, debug=args.debug) # Convert RGB to LAB and extract the Green-Magenta channel device, green_channel = pcv.rgb2gray_lab(img=img, channel="a", device=device, debug=args.debug) # Invert the Green-Magenta image because the plant is dark green device, green_inv = pcv.invert(img=green_channel, device=device, debug=args.debug) # Threshold the inverted Green-Magenta image to mostly isolate green pixels device, green_thresh = pcv.binary_threshold(img=green_inv, threshold=134, maxValue=255, object_type="light", device=device, debug=args.debug) # Extract core plant region from the image to preserve delicate plant features during filtering device += 1 plant_region = green_thresh[100:2000, 250:2250] if args.debug is not None: pcv.print_image(filename=str(device) + "_extract_plant_region.png", img=plant_region) # Use a Gaussian blur to disrupt the strong edge features in the cabinet device, blur_gaussian = pcv.gaussian_blur(device=device, img=green_thresh, ksize=(7, 7), sigmax=0, sigmay=None, debug=args.debug) # Threshold the blurred image to remove features that were blurred device, blur_thresholded = pcv.binary_threshold(img=blur_gaussian, threshold=250, maxValue=255, object_type="light", device=device, debug=args.debug) # Add the plant region back in to the filtered image device += 1 blur_thresholded[100:2000, 250:2250] = plant_region if args.debug is not None: pcv.print_image(filename=str(device) + "_replace_plant_region.png", img=blur_thresholded) # Use a median blur to breakup the horizontal and vertical lines caused by shadows from the track edges device, med_blur = pcv.median_blur(img=blur_thresholded, ksize=5, device=device, debug=args.debug) # Fill in small contours device, green_fill_50 = pcv.fill(img=np.copy(med_blur), mask=np.copy(med_blur), size=50, device=device, debug=args.debug) # Define an ROI for the brass stopper device, stopper_roi, stopper_hierarchy = pcv.define_roi( img=img, shape="rectangle", device=device, roi=None, roi_input="default", debug=args.debug, adjust=True, x_adj=1420, y_adj=890, w_adj=-920, h_adj=-1040) # Identify all remaining contours in the binary image device, contours, hierarchy = pcv.find_objects(img=img, mask=np.copy(green_fill_50), device=device, debug=args.debug) # Remove contours completely contained within the stopper region of interest device, remove_stopper_mask = remove_countors_roi(mask=green_fill_50, contours=contours, hierarchy=hierarchy, roi=stopper_roi, device=device, debug=args.debug) # Define an ROI for a screw hole device, screw_roi, screw_hierarchy = pcv.define_roi(img=img, shape="rectangle", device=device, roi=None, roi_input="default", debug=args.debug, adjust=True, x_adj=1870, y_adj=1010, w_adj=-485, h_adj=-960) # Remove contours completely contained within the screw region of interest device, remove_screw_mask = remove_countors_roi(mask=remove_stopper_mask, contours=contours, hierarchy=hierarchy, roi=screw_roi, device=device, debug=args.debug) # Identify objects device, contours, contour_hierarchy = pcv.find_objects( img=img, mask=remove_screw_mask, device=device, debug=args.debug) # Define ROI device, roi, roi_hierarchy = pcv.define_roi(img=img, shape="rectangle", device=device, roi=None, roi_input="default", debug=args.debug, adjust=True, x_adj=565, y_adj=200, w_adj=-490, h_adj=-250) # Decide which objects to keep device, roi_contours, roi_contour_hierarchy, _, _ = pcv.roi_objects( img=img, roi_type="partial", roi_contour=roi, roi_hierarchy=roi_hierarchy, object_contour=contours, obj_hierarchy=contour_hierarchy, device=device, debug=args.debug) # If there are no contours left we cannot measure anything if len(roi_contours) > 0: # Object combine kept objects device, plant_contour, plant_mask = pcv.object_composition( img=img, contours=roi_contours, hierarchy=roi_contour_hierarchy, device=device, debug=args.debug) outfile = False if args.writeimg: outfile = args.outdir + "/" + filename # Find shape properties, output shape image (optional) device, shape_header, shape_data, shape_img = pcv.analyze_object( img=img, imgname=args.image, obj=plant_contour, mask=plant_mask, device=device, debug=args.debug, filename=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=img, imgname=args.image, mask=plant_mask, bins=256, device=device, debug=args.debug, hist_plot_type=None, pseudo_channel="v", pseudo_bkg="img", resolution=300, filename=outfile) # Output shape and color data result = open(args.result, "a") result.write('\t'.join(map(str, shape_header)) + "\n") result.write('\t'.join(map(str, shape_data)) + "\n") for row in shape_img: result.write('\t'.join(map(str, row)) + "\n") result.write('\t'.join(map(str, color_header)) + "\n") result.write('\t'.join(map(str, color_data)) + "\n") for row in color_img: result.write('\t'.join(map(str, row)) + "\n") result.close() # Find matching NIR image device, nirpath = pcv.get_nir(path=path, filename=filename, device=device, debug=args.debug) nir_rgb, nir_path, nir_filename = pcv.readimage(nirpath) nir_img = cv2.imread(nirpath, 0) # Make mask glovelike in proportions via dilation device, d_mask = pcv.dilate(plant_mask, kernel=1, i=0, device=device, debug=args.debug) # Resize mask prop2, prop1 = conv_ratio() device, nmask = pcv.resize(img=d_mask, resize_x=prop1, resize_y=prop2, device=device, debug=args.debug) # Convert the resized mask to a binary mask device, bmask = pcv.binary_threshold(img=nmask, threshold=0, maxValue=255, object_type="light", device=device, debug=args.debug) device, crop_img = crop_sides_equally(mask=bmask, nir=nir_img, device=device, debug=args.debug) # position, and crop mask device, newmask = pcv.crop_position_mask(img=nir_img, mask=crop_img, device=device, x=0, y=1, v_pos="bottom", h_pos="right", debug=args.debug) # Identify objects device, nir_objects, nir_hierarchy = pcv.find_objects(img=nir_rgb, mask=newmask, device=device, debug=args.debug) # Object combine kept objects device, nir_combined, nir_combinedmask = pcv.object_composition( img=nir_rgb, contours=nir_objects, hierarchy=nir_hierarchy, device=device, debug=args.debug) if args.writeimg: outfile = args.outdir + "/" + nir_filename # Analyze NIR signal data device, nhist_header, nhist_data, nir_imgs = pcv.analyze_NIR_intensity( img=nir_img, rgbimg=nir_rgb, mask=nir_combinedmask, bins=256, device=device, histplot=False, debug=args.debug, filename=outfile) # Analyze the shape of the plant contour from the NIR image device, nshape_header, nshape_data, nir_shape = pcv.analyze_object( img=nir_img, imgname=nir_filename, obj=nir_combined, mask=nir_combinedmask, device=device, debug=args.debug, filename=outfile) # Write NIR data to co-results file coresult = open(args.coresult, "a") coresult.write('\t'.join(map(str, nhist_header)) + "\n") coresult.write('\t'.join(map(str, nhist_data)) + "\n") for row in nir_imgs: coresult.write('\t'.join(map(str, row)) + "\n") coresult.write('\t'.join(map(str, nshape_header)) + "\n") coresult.write('\t'.join(map(str, nshape_data)) + "\n") coresult.write('\t'.join(map(str, nir_shape)) + "\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 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 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 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 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 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 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(): # 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()