def remove_countors_roi(mask, contours, hierarchy, roi, device, debug=None): clean_mask = np.copy(mask) # Loop over all contours in the image for n, contour in enumerate(contours): # This is the number of vertices in the contour contour_points = len(contour) - 1 # Generate a list of x, y coordinates stack = np.vstack(contour) tests = [] # Loop over the vertices for the contour and do a point polygon test for i in range(0, contour_points): # The point polygon test returns # 1 if the contour vertex is inside the ROI contour # 0 if the contour vertex is on the ROI contour # -1 if the contour vertex is outside the ROI contour pptest = cv2.pointPolygonTest(contour=roi[0], pt=(stack[i][0], stack[i][1]), measureDist=False) # Append the test result to the list of point polygon tests for this contour tests.append(pptest) # If all of the point polygon tests have a value of 1, then all the contour vertices are in the ROI if all(t == 1 for t in tests): # Fill in the contour as black cv2.drawContours(image=clean_mask, contours=contours, contourIdx=n, color=0, thickness=-1, lineType=8, hierarchy=hierarchy) if debug == "print": pcv.print_image(filename=str(device) + "_remove_contours.png", img=clean_mask) elif debug == "plot": pcv.plot_image(clean_mask, cmap='gray') return device, clean_mask
def crop_sides_equally(mask, nir, device, debug): device += 1 # NumPy refers to y first then x mask_shape = np.shape(mask) # type: tuple nir_shape = np.shape(nir) # type: tuple final_y = mask_shape[0] final_x = mask_shape[1] difference_x = final_x - nir_shape[1] difference_y = final_y - nir_shape[0] if difference_x % 2 == 0: x1 = difference_x / 2 x2 = difference_x / 2 else: x1 = difference_x / 2 x2 = (difference_x / 2) + 1 if difference_y % 2 == 0: y1 = difference_y / 2 y2 = difference_y / 2 else: y1 = difference_y / 2 y2 = (difference_y / 2) + 1 crop_img = mask[y1:final_y - y2, x1:final_x - x2] if debug == "print": pcv.print_image(crop_img, str(device) + "_crop_sides_equally.png") elif debug == "plot": pcv.plot_image(crop_img, cmap="gray") return device, crop_img
def test_plantcv_print_image(): img, path, img_name = pcv.readimage( filename=os.path.join(TEST_DATA, TEST_INPUT_COLOR)) filename = os.path.join(TEST_TMPDIR, 'plantcv_print_image.jpg') pcv.print_image(img=img, filename=filename) # Assert that the file was created assert os.path.exists(filename) is True
def average_all_img(directory, outdir): allfiles = os.listdir(directory) path = str(directory) allpaths = [] for files in allfiles: p = path + str(files) allpaths.append(p) img, path, filename = pcv.readimage(allpaths[0]) n = len(allpaths) if len(np.shape(img)) == 3: ix, iy, iz = np.shape(img) arr = np.zeros((ix, iy, iz), np.float) else: ix, iy = np.shape(img) arr = np.zeros((ix, iy), np.float) # Build up average pixel intensities, casting each image as an array of floats for i, paths in enumerate(allpaths): img, path, filename = pcv.readimage(allpaths[i]) imarr = np.array(img, dtype=np.float) arr = arr + imarr / n # Round values in array and cast as 8-bit integer arr = np.array(np.round(arr), dtype=np.uint8) pcv.print_image(arr, (str(outdir)+"average_"+str(allfiles[0])))
def distance_transform(bin_img, distance_type, mask_size): """Creates an image where for each object pixel, a number is assigned that corresponds to the distance to the nearest background pixel. Inputs: img = Binary image data distance_type = Type of distance. It can be CV_DIST_L1, CV_DIST_L2 , or CV_DIST_C which are 1, 2 and 3, respectively. mask_size = Size of the distance transform mask. It can be 3, 5, or CV_DIST_MASK_PRECISE (the latter option is only supported by the first function). In case of the CV_DIST_L1 or CV_DIST_C distance type, the parameter is forced to 3 because a 3 by 3 mask gives the same result as 5 by 5 or any larger aperture. Returns: norm_image = grayscale distance-transformed image normalized between [0, 1] :param bin_img: numpy.ndarray :param distance_type: int :param mask_size: int :return norm_image: numpy.ndarray """ params.device += 1 dist = cv2.distanceTransform(src=bin_img, distanceType=distance_type, maskSize=mask_size) norm_image = cv2.normalize(src=dist, dst=dist, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F) if params.debug == 'print': print_image(norm_image, os.path.join(params.debug, str(params.device) + '_distance_transform.png')) elif params.debug == 'plot': plot_image(norm_image, cmap='gray') return norm_image
def average_all_img(directory,outdir): allfiles=os.listdir(directory) path=str(directory) allpaths=[] for files in allfiles: p=path+str(files) allpaths.append(p) img, path, filename = pcv.readimage(allpaths[0]) n=len(allpaths) if len(np.shape(img))==3: ix,iy,iz=np.shape(img) arr=np.zeros((ix,iy,iz),np.float) else: ix,iy=np.shape(img) arr=np.zeros((ix,iy,iz),np.float) # Build up average pixel intensities, casting each image as an array of floats for i,paths in enumerate(allpaths): img,path,filename=pcv.readimage(allpaths[i]) imarr=np.array(img,dtype=np.float) arr=arr+imarr/n #Round values in array and cast as 8-bit integer arr=np.array(np.round(arr),dtype=np.uint8) pcv.print_image(arr, (str(outdir)+"average_"+str(allfiles[0])))
def _draw_roi(img, roi_contour): """Draw an ROI :param img: numpy.ndarray :param roi_contour: list """ # Make a copy of the reference image ref_img = np.copy(img) # If the reference image is grayscale convert it to color if len(np.shape(ref_img)) == 2: ref_img = cv2.cvtColor(ref_img, cv2.COLOR_GRAY2BGR) # Draw the contour on the reference image cv2.drawContours(ref_img, roi_contour, -1, (255, 0, 0), 5) if params.debug == "print": # If debug is print, save the image to a file print_image( ref_img, os.path.join(params.debug_outdir, str(params.device) + "_roi.png")) elif params.debug == "plot": # If debug is plot, print to the plotting device plot_image(ref_img)
def main(): # Sets variables from input arguments args = options() device = 0 # Workflow step counter debug = args.debug # Option to display debug images to the notebook rgb_img = args.image # Name of seed Image writeimg = args.writeimg outfile = str(args.result) outdir = str(args.outdir) # Reads in RGB image img, path, filename = pcv.readimage(rgb_img) if writeimg is True: pcv.print_image(img, outfile + "_original.jpg") # Converts RGB to HSV and extract the Saturation channel and inverts image device, img_gray_sat = pcv.rgb2gray_hsv(img, 's', device, debug) img_gray_sat = 255 - img_gray_sat # Corrects saturation image background brightness sat_img2 = 255 - correct_white_background(img_gray_sat) # Convert RGB to HSV and extract the Value channel device, img_gray_val = pcv.rgb2gray_hsv(img, 'v', device, debug) # Corrects value image background brightness val_img2 = 255 - correct_white_background(img_gray_val) # Convert RGB to HSV and extract the Hue channel device, img_hue = pcv.rgb2gray_hsv(img, 'h', device, debug) # Corrects Hue Image Based on standard mask = np.zeros(img.shape[:2], np.uint8) mask[1050: 1150, 3750: 3850] = 255 huehist = cv2.calcHist([img_hue], [0], mask, [256], [0, 256]) correction_factor = 155 - np.argmax(huehist) hue_channel = np.add(img_hue, correction_factor) if correction_factor > 0: hue_channel = np.where(hue_channel > 179, hue_channel - 180, hue_channel) elif correction_factor < 0: hue_channel = np.where(hue_channel < 0, 180 + hue_channel, hue_channel) # Thresholds the Saturation image device, sat_img_binary = pcv.binary_threshold(sat_img2, 35, 255, 'light', device, debug) # Threshold the Value image device, val_img_binary = pcv.binary_threshold(val_img2, 35, 255, 'light', device, debug) # Combines masks img_binary = np.where(sat_img_binary < 255, val_img_binary, sat_img_binary) # Fills in speckles smaller than 200 pixels mask = np.copy(img_binary) device, fill_image = pcv.fill(img_binary, mask, 200, device, debug) if writeimg is True: pcv.print_image(mask, outfile + "_mask.jpg") pcv.print_image(img_binary, outfile + "_binary.jpg") # Identifies objects using filled binary image as a mask device, id_objects, obj_hierarchy = pcv.find_objects(img, fill_image, device, debug) # Defines rectangular ROI device, roi, roi_hierarchy = \ pcv.define_roi(img, 'rectangle', device, None, 'default', debug, True, 300, 1000, -1250, -425) # Keeps only objects within or partially within ROI device, roi_objects, roi_obj_hierarchy, kept_mask, obj_area = \ pcv.roi_objects(img, 'partial', roi, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # Randomly colors the individual seeds img_copy = np.copy(img) for i in range(0, len(roi_objects)): rand_color = color_palette(1) cv2.drawContours(img_copy, roi_objects, i, rand_color[0], -1, lineType=8, hierarchy=roi_obj_hierarchy) if writeimg is True: pcv.print_image(img_copy, outfile + "_coloredseeds.jpg") # Gets the area of each seed, saved in shape_data shape_header = [] table = [] for i in range(0, len(roi_objects)): if roi_obj_hierarchy[0][i][3] == -1: # Checks if shape is a parent contour # Object combine kept objects device, obj, mask2 = pcv.object_composition(img, [roi_objects[i]], np.array([[roi_obj_hierarchy[0][i]]]), device, debug) if obj is not None: device, shape_header, shape_data, shape_img = \ pcv.analyze_object(img, rgb_img, obj, mask2, device, debug) if shape_header is not None: shape_header.append('hue') shape_header.append('saturation') if shape_data is not None: darkval = float(np.sum(np.multiply(sat_img2, mask2))) / np.sum(mask2) huehist = cv2.calcHist([hue_channel], [0], mask2, [256], [0, 256]) hueval = np.argmax(huehist) shape_data.append(hueval) shape_data.append(darkval) table.append(shape_data) # Finds the area of the size marker in pixels and saves to "marker data" device, marker_header, marker_data, analysis_images =\ pcv.report_size_marker_area(img, 'rectangle', device, debug, "detect", 3525, 850, -200, -1700, "black", "light", "h", 120) # shape_header.append("marker_area") # Saves seed and marker shape data results to file metadata = open(posixpath.join(outdir, outfile), 'r').read() os.remove(posixpath.join(outdir, outfile)) for seed, row in enumerate(table): prefix = posixpath.join(outdir, outfile[0:-4]) results = open(prefix + '_' + str(seed + 1) + '.txt', 'w') results.write(metadata) results.write('\t'.join(map(str, shape_header)) + '\n') # row.append(marker_data[1]) results.write('\t'.join(map(str, row)) + '\n') results.write('\t'.join(map(str, marker_header)) + '\n') results.write('\t'.join(map(str, marker_data)) + '\n') results.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 slice_stitch(sqlitedb, outdir, camera_label='vis_sv', spacer='on',makefig='yes'): #sqlitedb = sqlite database to query (path to db) #outdir = path to outdirectory #camera_label = either 'vis_tv','vis_sv',or 'fluor_tv' #spacer = either 'on' or 'off', adds a white line between day breaks #makefig = either 'yes' or 'no', adds labels to days and a title i=datetime.now() timenow=i.strftime('%m-%d-%Y_%H:%M:%S') newfolder="slice_analysis_"+(str(timenow)) os.mkdir((str(outdir)+newfolder)) connect=sq.connect(sqlitedb) connect.row_factory = dict_factory connect.text_factory=str c = connect.cursor() h = connect.cursor() m = connect.cursor() k = connect.cursor() id_array=[] path_array=[] unique_array=[] for date in c.execute('select min(datetime) as first from snapshots'): firstday=date['first'] for i, group in enumerate(m.execute('select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where type = "slice" order by plant_id asc')): plant_id=group['plant_id'] plantgeno=re.match('^([A-Z][a-zA-Z]\d*[A-Z]{2})',plant_id) if plantgeno==None: plantgeno_id=group['plant_id'] id_array.append(plantgeno_id,) else: span1,span2=plantgeno.span() plantgeno_id=group['plant_id'][span1:span2] id_array.append(plantgeno_id,) id_unique=np.unique(id_array) if spacer=='on': for group_label in id_unique: ch1=[] ch2=[] ch3=[] time_array=[] for i, data in enumerate(h.execute('select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where plant_id like ? and type = "slice" and camera=? order by datetime asc', ("%"+group_label+"%",camera_label,))): date_int=((data['datetime']-firstday)/86400) time_array.append(date_int) for i, data in enumerate(k.execute('select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where plant_id like ? and type = "slice" and camera=? order by datetime asc', ("%"+group_label+"%",camera_label,))): if i==0: line1=cv2.imread(data['image_path']) split1, split2, split3=np.dsplit(line1,3) split1_f=split1.flatten() split2_f=split2.flatten() split3_f=split3.flatten() stacked_1=np.column_stack((split1_f,split1_f, split1_f, split1_f, split1_f)) stacked_2=np.column_stack((split2_f,split2_f, split2_f, split2_f, split2_f)) stacked_3=np.column_stack((split3_f,split3_f, split3_f, split3_f, split3_f)) stacked_1t=np.transpose(stacked_1) stacked_2t=np.transpose(stacked_2) stacked_3t=np.transpose(stacked_3) ch1.extend(stacked_1t) ch2.extend(stacked_2t) ch3.extend(stacked_3t) elif time_array[i-1]==time_array[i]: line1=cv2.imread(data['image_path']) split1, split2, split3=np.dsplit(line1,3) split1_f=split1.flatten() split2_f=split2.flatten() split3_f=split3.flatten() stacked_1=np.column_stack((split1_f,split1_f, split1_f, split1_f, split1_f)) stacked_2=np.column_stack((split2_f,split2_f, split2_f, split2_f, split2_f)) stacked_3=np.column_stack((split3_f,split3_f, split3_f, split3_f, split3_f)) stacked_1t=np.transpose(stacked_1) stacked_2t=np.transpose(stacked_2) stacked_3t=np.transpose(stacked_3) ch1.extend(stacked_1t) ch2.extend(stacked_2t) ch3.extend(stacked_3t) else: line1=cv2.imread(data['image_path']) split1, split2, split3=np.dsplit(line1,3) split1_f=split1.flatten() split2_f=split2.flatten() split3_f=split3.flatten() spacer_size=np.shape(split1_f) spacer1=np.zeros(spacer_size) spacer_f=spacer1+255 stacked_1=np.column_stack((spacer_f, spacer_f, spacer_f, spacer_f, spacer_f,spacer_f, spacer_f, spacer_f, spacer_f, spacer_f)) stacked_2=np.column_stack((spacer_f, spacer_f, spacer_f, spacer_f, spacer_f,spacer_f, spacer_f, spacer_f, spacer_f, spacer_f)) stacked_3=np.column_stack((spacer_f, spacer_f, spacer_f, spacer_f, spacer_f,spacer_f, spacer_f, spacer_f, spacer_f, spacer_f)) stacked_1t=np.transpose(stacked_1) stacked_2t=np.transpose(stacked_2) stacked_3t=np.transpose(stacked_3) ch1.extend(stacked_1t) ch2.extend(stacked_2t) ch3.extend(stacked_3t) stacked_4=np.column_stack((split1_f,split1_f, split1_f, split1_f, split1_f)) stacked_5=np.column_stack((split2_f,split2_f, split2_f, split2_f, split2_f)) stacked_6=np.column_stack((split3_f,split3_f, split3_f, split3_f, split3_f)) stacked_4t=np.transpose(stacked_4) stacked_5t=np.transpose(stacked_5) stacked_6t=np.transpose(stacked_6) ch1.extend(stacked_4t) ch2.extend(stacked_5t) ch3.extend(stacked_6t) color_cat=np.dstack((ch1,ch2,ch3)) pcv.print_image(color_cat,(str(outdir)+str(newfolder)+"/"+str(group_label)+"_"+str(camera_label)+"_spacer_"+str(spacer)+"_slice_joined_img.png")) if spacer=='off': for group_label in id_unique: ch1=[] ch2=[] ch3=[] for i, data in enumerate(h.execute('select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where plant_id like ? and type = "slice" and camera=? order by datetime asc', ("%"+group_label+"%",camera_label,))): line1=cv2.imread(data['image_path']) split1, split2, split3=np.dsplit(line1,3) split1_f=split1.flatten() split2_f=split2.flatten() split3_f=split3.flatten() stacked_1=np.column_stack((split1_f,split1_f, split1_f, split1_f, split1_f)) stacked_2=np.column_stack((split2_f,split2_f, split2_f, split2_f, split2_f)) stacked_3=np.column_stack((split3_f,split3_f, split3_f, split3_f, split3_f)) stacked_1t=np.transpose(stacked_1) stacked_2t=np.transpose(stacked_2) stacked_3t=np.transpose(stacked_3) ch1.extend(stacked_1t) ch2.extend(stacked_2t) ch3.extend(stacked_3t) color_cat=np.dstack((ch1,ch2,ch3)) pcv.print_image(color_cat,(str(outdir)+newfolder+"/"+str(group_label)+"_"+str(camera_label)+"_spacer_"+str(spacer)+"_slice_joined_img.png")) folder_path=(str(outdir)+newfolder) if makefig=='yes': list_files=os.listdir(folder_path) sorted_list=sorted(list_files) for group_label in id_unique: time_array=[] length_time=[] ypos=[] ypos1=[] ypos2=[] unique_time1=[] for i, data in enumerate(h.execute('select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where plant_id like ? and type = "slice" and camera=? order by datetime asc', ("%"+group_label+"%",camera_label,))): date_int=((data['datetime']-firstday)/86400) time_array.append(date_int) unique_time=np.unique(time_array) for times in unique_time: length=[] for i,time in enumerate(time_array): if time_array[i]==times: tm=1 length.append(tm) else: tm=0 length.append(tm) sum_time=np.sum(length) length_time.append(sum_time) if spacer=='off': for i,length in enumerate(length_time): if i==0: yadd=length*5 ypos.append(yadd) else: yadd=(length*5) ypos.append(yadd) elif spacer=='on': for i,length in enumerate(length_time): if i==0: yadd=length*5 ypos.append(yadd) else: yadd=(length*5)+10 ypos.append(yadd) for i,y in enumerate(ypos): if i==0: y1=y ypos1.append(y1) else: y1=y+ypos1[i-1] ypos1.append(y1) for time in unique_time: time1=time+1 unique_time1.append(time1) file_name=str(group_label)+"_"+str(camera_label)+"_spacer_"+str(spacer)+"_slice_joined_img.png" img1=cv2.imread((str(folder_path)+"/"+str(file_name)), -1) if len(np.shape(img1))==3: ch1,ch2,ch3=np.dsplit(img1,3) img=np.dstack((ch3,ch2,ch1)) plt.imshow(img) ax = plt.subplot(111) ax.set_ylabel('Days on Bellwether Phenotyper', size=10) ax.set_yticks(ypos1) ax.set_yticklabels(unique_time1,size=5) ax.yaxis.tick_left() ax.set_xticks([0,255]) ax.set_xticklabels([0,255],size=5) for t in ax.yaxis.get_ticklines(): t.set_color('white') for t in ax.xaxis.get_ticklines(): t.set_color('white') for line in ax.get_xticklines() + ax.get_yticklines(): line.set_alpha(0) ax.spines['bottom'].set_color('none') ax.spines['top'].set_color('none') ax.spines['left'].set_color('none') ax.spines['right'].set_color('none') #ax.tick_params(axis='y',direction='out') plt.title(str(group_label)) fig_name=(str(folder_path)+"/"+str(group_label)+"_spacer_"+str(spacer)+"_slice_join_figure_img.png") plt.savefig(fig_name, dpi=300) plt.clf() return folder_path
def test_plantcv_print_image(): img, path, img_name = pcv.readimage(filename=os.path.join(TEST_DATA, TEST_INPUT_COLOR)) filename = os.path.join(TEST_TMPDIR, 'plantcv_print_image.jpg') pcv.print_image(img=img, filename=filename) # Assert that the file was created assert os.path.exists(filename) is True
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) # Apply a small median blur to break up pot edges device, med_blur = pcv.median_blur(img=np.copy(blue_fill_50), ksize=3, device=device, debug=args.debug) # Define an ROI for the barcode label device, label_roi, label_hierarchy = pcv.define_roi(img=img, shape="rectangle", device=device, roi=None, roi_input="default", debug=args.debug, adjust=True, x_adj=1100, y_adj=1350, w_adj=-1070, h_adj=-590) # Identify all remaining contours in the binary image device, contours, hierarchy = pcv.find_objects(img=img, mask=np.copy(med_blur), device=device, debug=args.debug) # Remove contours completely contained within the label region of interest device, remove_label_mask = remove_countors_roi(mask=med_blur, contours=contours, hierarchy=hierarchy, roi=label_roi, device=device, debug=args.debug) # Identify objects device, contours, contour_hierarchy = pcv.find_objects( img=img, mask=remove_label_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=0, w_adj=-490, h_adj=-600) # 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=690, 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()
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()
import plantcv as pcv #lee imagen img, path, img_filename = pcv.readimage( "/home/fitosmartplatform/plantCV/prueba/plan.jpg") #contador dl paso de procesamiento de imagen device = 0 # Create binary image from a gray image based on threshold values. Targeting light objects in the image. device, threshold_light = pcv.binary_threshold(img, 36, 255, 'dark', device, debug="print") device, h_channel = pcv.rgb2gray_hsv(img, 'h', device, debug="print") pcv.print_image(h_channel, "/home/fitosmartplatform/plantCV/prueba/image-gray.jpg") pcv.print_image(threshold_light, "/home/fitosmartplatform/plantCV/prueba/test-image.jpg") """notas""" #si uso plot :imprime datos de la imagen no aguarda #si uso print :imprime imagen y la aguarda con un nombre de la funcion #si uso el light es un entorno diferente #si uso dark es otro entorno de la imagen
def define_multi_roi(img, device, debug=False, roi_file=None, roi_input='default', rows=None, col=None, shape=None, rad=None, dist_x=None, dist_y=None, adjust_x=False, adjust_y=False): #If you have very irregularly spaced ROI (that stays consistent between images), it is likely easiest to provide a file with an ROI #But remember that the ROIs can capture objects outside of their borders as long as the object is connected (partially inside ROI) so some irregularities are fine # img= img to overlay roi # roi_file= default is None, else the user can input an ROI image, object area shoud be white and background area should be black. # roi_input= type of image that the roi_file is, either 'binary', 'rgb' or 'default' (no ROI inputted) # debug= True/False, if True, print image # rows= number of rows of rois # col= number of columns of rois # shape= None, 'circle', or 'square' # rad= radius or height/width of shape # dist_x= distance between edges on the x axis # dist_y= distance between edges on the y axis # adjust_x= distance to move set of roi in the x direction # adjust_y= distance to move set of roi in the y direction 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) #Allows user to use the default ROI or input their own RGB or binary image (made with imagej or some other program) as a base ROI (that can be adjusted below if necessary) if roi_input== 'rgb': hsv = cv2.cvtColor(roi_file, cv2.COLOR_BGR2HSV) h,s,v = cv2.split(hsv) ret,v_img = cv2.threshold(v, 0, 255, cv2.THRESH_BINARY) roi_contour,roi_hierarchy = cv2.findContours(v_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) if debug: print_image(roi_file, (str(device) + '_roi.png')) elif roi_input== 'binary': roi_contour,roi_hierarchy = cv2.findContours(roi_file,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) if debug: print_image(roi_file, (str(device) + '_roi.png')) elif roi_input=='default': size = ix,iy roi_background = np.zeros(size, dtype=np.uint8) roi_size=(ix-5),(iy-5) roi=np.zeros(roi_size, dtype=np.uint8) roi1=roi+1 roi_contour,roi_heirarchy=cv2.findContours(roi1,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) cv2.drawContours(roi_background,roi_contour[0],-1, (255,0,0),5) else: fatal_error('ROI Input' + str(roi_input) + ' is not "binary", "rgb" or "default roi"!') print roi_contour print v ##If the ROI is exactly in the 'correct' position #if adjust_x==False and adjust_y==False: # if roi_input=='rgb' or roi_input=='binary': # size = ix,iy,3 # background = np.zeros(size, dtype=np.uint8) # roi_contour1=roi_contour+background # roi_heirarchy1=roi_heirarchy # cv2.drawContours(ori_img,roi_contour1[0],-1,(255,0,0),5) # if debug: # print_image(ori_img,(str(device)+'ori_roi.png')) # #return device,roi_contour1,roi_heirarchy1 #for cnt in roi_contour: # size = ix,iy,3 # background = np.zeros(size, dtype=np.uint8) # if shape=='square': # x,y,w,h = cv2.boundingRect(cnt) # cv2.rectangle(background,(x,y),(x+w,y+h),(0,255,0),5) # rect = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # rect_contour,hierarchy = cv2.findContours(rect,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,rect_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, rect_contour, hierarchy # elif shape== 'circle': # x,y,w,h = cv2.boundingRect(cnt) # center = (int(w/2),int(h/2)) # if h>w: # radius = int(w/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # else: # radius = int(h/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # elif shape== 'ellipse': # x,y,w,h = cv2.boundingRect(cnt) # center = (int(w/2),int(h/2)) # if w>h: # cv2.ellipse(background,center,(w/2,h/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # cv2.ellipse(ori_img,center,(h/2,w/2),0,0,360, (0,255,0), 2) # cv2.ellipse(background,center,(h/2,w/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # fatal_error('Shape' + str(shape) + ' is not "rectangle", "circle", or "ellipse"!') #Adjust ROI moves the inputted or created ROI return device #def define_roi(img, shape, device, roi=None, roi_input='default', debug=False, adjust=False, x_adj=0, y_adj=0, w_adj=0, h_adj=0): # # img = img to overlay roi # # roi =default (None) or user input ROI image, object area should be white and background should be black, has not been optimized for more than one ROI # # roi_input = type of file roi_base is, either 'binary', 'rgb', or 'default' (no ROI inputted) # # shape = desired shape of final roi, either 'rectangle' or 'circle', if user inputs rectangular roi but chooses 'circle' for shape then a circle is fitted around rectangular roi (and vice versa) # # device = device number. Used to count steps in the pipeline # # debug = True/False. If True, print image # # adjust= either 'True' or 'False', if 'True' allows user to adjust ROI # # x_adj = adjust center along x axis # # y_adj = adjust center along y axis # # w_adj = adjust width # # h_adj = adjust height # # 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) # # #Allows user to use the default ROI or input their own RGB or binary image (made with imagej or some other program) as a base ROI (that can be adjusted below) # if roi_input== 'rgb': # hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) # h,s,v = cv2.split(hsv) # ret,v_img = cv2.threshold(v, 0, 255, cv2.THRESH_BINARY) # roi_contour,hierarchy = cv2.findContours(v_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # elif roi_input== 'binary': # roi_contour,hierarchy = cv2.findContours(rois,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # elif roi_input=='default': # size = ix,iy # roi_background = np.zeros(size, dtype=np.uint8) # roi_size=(ix-5),(iy-5) # roi=np.zeros(roi_size, dtype=np.uint8) # roi1=roi+1 # roi_contour,roi_heirarchy=cv2.findContours(roi1,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(roi_background,roi_contour[0],-1, (255,0,0),5) # if adjust==True: # if x_adj>0 and w_adj>0: # fatal_error('Adjusted ROI position is out of frame, this will cause problems in detecting objects') # elif y_adj>0 and h_adj>0: # fatal_error('Adjusted ROI position is out of frame, this will cause problems in detecting objects') # elif x_adj<0 or y_adj<0: # fatal_error('Adjusted ROI position is out of frame, this will cause problems in detecting objects') # else: # fatal_error('ROI Input' + str(roi_input) + ' is not "binary", "rgb" or "default roi"!') # # #If the ROI is exactly in the 'correct' position # if adjust==False: # for cnt in roi_contour: # size = ix,iy,3 # background = np.zeros(size, dtype=np.uint8) # if shape=='rectangle': # x,y,w,h = cv2.boundingRect(cnt) # cv2.rectangle(background,(x,y),(x+w,y+h),(0,255,0),5) # rect = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # rect_contour,hierarchy = cv2.findContours(rect,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,rect_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, rect_contour, hierarchy # elif shape== 'circle': # x,y,w,h = cv2.boundingRect(cnt) # center = (int(w/2),int(h/2)) # if h>w: # radius = int(w/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # else: # radius = int(h/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # elif shape== 'ellipse': # x,y,w,h = cv2.boundingRect(cnt) # center = (int(w/2),int(h/2)) # if w>h: # cv2.ellipse(background,center,(w/2,h/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # cv2.ellipse(ori_img,center,(h/2,w/2),0,0,360, (0,255,0), 2) # cv2.ellipse(background,center,(h/2,w/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # fatal_error('Shape' + str(shape) + ' is not "rectangle", "circle", or "ellipse"!') # # #If the user wants to change the size of the ROI or adjust ROI position # if adjust==True: # sys.stderr.write('WARNING: Make sure ROI is COMPLETELY in frame or object detection will not perform properly\n') # if x_adj==0 and y_adj==0 and w_adj==0 and h_adj==0: # fatal_error( 'If adjust is true then x_adj, y_adj, w_adj or h_adj must have a non-zero value') # else: # for cnt in roi_contour: # size = ix,iy, 3 # background = np.zeros(size, dtype=np.uint8) # if shape=='rectangle': # x,y,w,h = cv2.boundingRect(cnt) # x1=x+x_adj # y1=y+y_adj # w1=w+w_adj # h1=h+h_adj # cv2.rectangle(background,(x1,y1),(x+w1,y+h1),(0,255,0),1) # rect = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # rect_contour,hierarchy = cv2.findContours(rect,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,rect_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, rect_contour, hierarchy # elif shape== 'circle': # x,y,w,h = cv2.boundingRect(cnt) # x1=x+x_adj # y1=y+y_adj # w1=w+w_adj # h1=h+h_adj # center = (int((w+x1)/2),int((h+y1)/2)) # if h>w: # radius = int(w1/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # else: # radius = int(h1/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # elif shape== 'ellipse': # x,y,w,h = cv2.boundingRect(cnt) # x1=x+x_adj # y1=y+y_adj # w1=w+w_adj # h1=h+h_adj # center = (int((w+x1)/2),int((h+y1)/2)) # if w>h: # cv2.ellipse(background,center,(w1/2,h1/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # cv2.ellipse(background,center,(h1/2,w1/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # fatal_error('Shape' + str(shape) + ' is not "rectangle", "circle", or "ellipse"!')
def define_multi_roi(img, device, debug=False, roi_file=None, roi_input='default', rows=None, col=None, shape=None, rad=None, dist_x=None, dist_y=None, adjust_x=False, adjust_y=False): #If you have very irregularly spaced ROI (that stays consistent between images), it is likely easiest to provide a file with an ROI #But remember that the ROIs can capture objects outside of their borders as long as the object is connected (partially inside ROI) so some irregularities are fine # img= img to overlay roi # roi_file= default is None, else the user can input an ROI image, object area shoud be white and background area should be black. # roi_input= type of image that the roi_file is, either 'binary', 'rgb' or 'default' (no ROI inputted) # debug= True/False, if True, print image # rows= number of rows of rois # col= number of columns of rois # shape= None, 'circle', or 'square' # rad= radius or height/width of shape # dist_x= distance between edges on the x axis # dist_y= distance between edges on the y axis # adjust_x= distance to move set of roi in the x direction # adjust_y= distance to move set of roi in the y direction 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) #Allows user to use the default ROI or input their own RGB or binary image (made with imagej or some other program) as a base ROI (that can be adjusted below if necessary) if roi_input == 'rgb': hsv = cv2.cvtColor(roi_file, cv2.COLOR_BGR2HSV) h, s, v = cv2.split(hsv) ret, v_img = cv2.threshold(v, 0, 255, cv2.THRESH_BINARY) roi_contour, roi_hierarchy = cv2.findContours(v_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) if debug: print_image(roi_file, (str(device) + '_roi.png')) elif roi_input == 'binary': roi_contour, roi_hierarchy = cv2.findContours(roi_file, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) if debug: print_image(roi_file, (str(device) + '_roi.png')) elif roi_input == 'default': size = ix, iy roi_background = np.zeros(size, dtype=np.uint8) roi_size = (ix - 5), (iy - 5) roi = np.zeros(roi_size, dtype=np.uint8) roi1 = roi + 1 roi_contour, roi_heirarchy = cv2.findContours(roi1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) cv2.drawContours(roi_background, roi_contour[0], -1, (255, 0, 0), 5) else: fatal_error('ROI Input' + str(roi_input) + ' is not "binary", "rgb" or "default roi"!') print roi_contour print v ##If the ROI is exactly in the 'correct' position #if adjust_x==False and adjust_y==False: # if roi_input=='rgb' or roi_input=='binary': # size = ix,iy,3 # background = np.zeros(size, dtype=np.uint8) # roi_contour1=roi_contour+background # roi_heirarchy1=roi_heirarchy # cv2.drawContours(ori_img,roi_contour1[0],-1,(255,0,0),5) # if debug: # print_image(ori_img,(str(device)+'ori_roi.png')) # #return device,roi_contour1,roi_heirarchy1 #for cnt in roi_contour: # size = ix,iy,3 # background = np.zeros(size, dtype=np.uint8) # if shape=='square': # x,y,w,h = cv2.boundingRect(cnt) # cv2.rectangle(background,(x,y),(x+w,y+h),(0,255,0),5) # rect = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # rect_contour,hierarchy = cv2.findContours(rect,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,rect_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, rect_contour, hierarchy # elif shape== 'circle': # x,y,w,h = cv2.boundingRect(cnt) # center = (int(w/2),int(h/2)) # if h>w: # radius = int(w/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # else: # radius = int(h/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # elif shape== 'ellipse': # x,y,w,h = cv2.boundingRect(cnt) # center = (int(w/2),int(h/2)) # if w>h: # cv2.ellipse(background,center,(w/2,h/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # cv2.ellipse(ori_img,center,(h/2,w/2),0,0,360, (0,255,0), 2) # cv2.ellipse(background,center,(h/2,w/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # fatal_error('Shape' + str(shape) + ' is not "rectangle", "circle", or "ellipse"!') #Adjust ROI moves the inputted or created ROI return device #def define_roi(img, shape, device, roi=None, roi_input='default', debug=False, adjust=False, x_adj=0, y_adj=0, w_adj=0, h_adj=0): # # img = img to overlay roi # # roi =default (None) or user input ROI image, object area should be white and background should be black, has not been optimized for more than one ROI # # roi_input = type of file roi_base is, either 'binary', 'rgb', or 'default' (no ROI inputted) # # shape = desired shape of final roi, either 'rectangle' or 'circle', if user inputs rectangular roi but chooses 'circle' for shape then a circle is fitted around rectangular roi (and vice versa) # # device = device number. Used to count steps in the pipeline # # debug = True/False. If True, print image # # adjust= either 'True' or 'False', if 'True' allows user to adjust ROI # # x_adj = adjust center along x axis # # y_adj = adjust center along y axis # # w_adj = adjust width # # h_adj = adjust height # # 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) # # #Allows user to use the default ROI or input their own RGB or binary image (made with imagej or some other program) as a base ROI (that can be adjusted below) # if roi_input== 'rgb': # hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) # h,s,v = cv2.split(hsv) # ret,v_img = cv2.threshold(v, 0, 255, cv2.THRESH_BINARY) # roi_contour,hierarchy = cv2.findContours(v_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # elif roi_input== 'binary': # roi_contour,hierarchy = cv2.findContours(rois,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # elif roi_input=='default': # size = ix,iy # roi_background = np.zeros(size, dtype=np.uint8) # roi_size=(ix-5),(iy-5) # roi=np.zeros(roi_size, dtype=np.uint8) # roi1=roi+1 # roi_contour,roi_heirarchy=cv2.findContours(roi1,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(roi_background,roi_contour[0],-1, (255,0,0),5) # if adjust==True: # if x_adj>0 and w_adj>0: # fatal_error('Adjusted ROI position is out of frame, this will cause problems in detecting objects') # elif y_adj>0 and h_adj>0: # fatal_error('Adjusted ROI position is out of frame, this will cause problems in detecting objects') # elif x_adj<0 or y_adj<0: # fatal_error('Adjusted ROI position is out of frame, this will cause problems in detecting objects') # else: # fatal_error('ROI Input' + str(roi_input) + ' is not "binary", "rgb" or "default roi"!') # # #If the ROI is exactly in the 'correct' position # if adjust==False: # for cnt in roi_contour: # size = ix,iy,3 # background = np.zeros(size, dtype=np.uint8) # if shape=='rectangle': # x,y,w,h = cv2.boundingRect(cnt) # cv2.rectangle(background,(x,y),(x+w,y+h),(0,255,0),5) # rect = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # rect_contour,hierarchy = cv2.findContours(rect,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,rect_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, rect_contour, hierarchy # elif shape== 'circle': # x,y,w,h = cv2.boundingRect(cnt) # center = (int(w/2),int(h/2)) # if h>w: # radius = int(w/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # else: # radius = int(h/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # elif shape== 'ellipse': # x,y,w,h = cv2.boundingRect(cnt) # center = (int(w/2),int(h/2)) # if w>h: # cv2.ellipse(background,center,(w/2,h/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # cv2.ellipse(ori_img,center,(h/2,w/2),0,0,360, (0,255,0), 2) # cv2.ellipse(background,center,(h/2,w/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # fatal_error('Shape' + str(shape) + ' is not "rectangle", "circle", or "ellipse"!') # # #If the user wants to change the size of the ROI or adjust ROI position # if adjust==True: # sys.stderr.write('WARNING: Make sure ROI is COMPLETELY in frame or object detection will not perform properly\n') # if x_adj==0 and y_adj==0 and w_adj==0 and h_adj==0: # fatal_error( 'If adjust is true then x_adj, y_adj, w_adj or h_adj must have a non-zero value') # else: # for cnt in roi_contour: # size = ix,iy, 3 # background = np.zeros(size, dtype=np.uint8) # if shape=='rectangle': # x,y,w,h = cv2.boundingRect(cnt) # x1=x+x_adj # y1=y+y_adj # w1=w+w_adj # h1=h+h_adj # cv2.rectangle(background,(x1,y1),(x+w1,y+h1),(0,255,0),1) # rect = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # rect_contour,hierarchy = cv2.findContours(rect,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,rect_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, rect_contour, hierarchy # elif shape== 'circle': # x,y,w,h = cv2.boundingRect(cnt) # x1=x+x_adj # y1=y+y_adj # w1=w+w_adj # h1=h+h_adj # center = (int((w+x1)/2),int((h+y1)/2)) # if h>w: # radius = int(w1/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # else: # radius = int(h1/2) # cv2.circle(background,center,radius,(255,255,255),-1) # circle = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # circle_contour,hierarchy = cv2.findContours(circle,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,circle_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, circle_contour, hierarchy # elif shape== 'ellipse': # x,y,w,h = cv2.boundingRect(cnt) # x1=x+x_adj # y1=y+y_adj # w1=w+w_adj # h1=h+h_adj # center = (int((w+x1)/2),int((h+y1)/2)) # if w>h: # cv2.ellipse(background,center,(w1/2,h1/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # cv2.ellipse(background,center,(h1/2,w1/2),0,0,360, (0,255,0), 2) # ellipse = cv2.cvtColor( background, cv2.COLOR_RGB2GRAY ) # ellipse_contour,hierarchy = cv2.findContours(ellipse,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # cv2.drawContours(ori_img,ellipse_contour[0],-1, (255,0,0),5) # if debug: # print_image(ori_img, (str(device) + '_roi.png')) # return device, ellipse_contour, hierarchy # else: # fatal_error('Shape' + str(shape) + ' is not "rectangle", "circle", or "ellipse"!')
def roi_objects(img,roi_type,roi_contour, roi_hierarchy,object_contour, obj_hierarchy, device, debug=False): # img = img to display kept objects # roi_type = 'cutto' or 'partial' (for partially inside) # roi_contour = contour of roi, output from "View and Ajust ROI" function # roi_hierarchy = contour of roi, output from "View and Ajust ROI" function # object_contour = contours of objects, output from "Identifying Objects" fuction # obj_hierarchy = hierarchy of objects, output from "Identifying Objects" fuction # device = device number. Used to count steps in the pipeline device +=1 if len(np.shape(img))==3: ix,iy,iz=np.shape(img) else: ix,iy=np.shape(img) size = ix,iy,3 background = np.zeros(size, dtype=np.uint8) ori_img=np.copy(img) w_back=background+255 background1 = np.zeros(size, dtype=np.uint8) background2 = np.zeros(size, dtype=np.uint8) # Allows user to find all objects that are completely inside or overlapping with ROI if roi_type=='partial': for c,cnt in enumerate(object_contour): length=(len(cnt)-1) stack=np.vstack(cnt) test=[] keep=False for i in range(0,length): pptest=cv2.pointPolygonTest(roi_contour[0], (stack[i][0],stack[i][1]), False) if int(pptest)!=-1: keep=True if keep==True: if obj_hierarchy[0][c][3]>-1: cv2.drawContours(w_back,object_contour,c, (255,255,255),-1, lineType=8,hierarchy=obj_hierarchy) else: cv2.drawContours(w_back,object_contour,c, (0,0,0),-1, lineType=8,hierarchy=obj_hierarchy) else: cv2.drawContours(w_back,object_contour,c, (255,255,255),-1, lineType=8,hierarchy=obj_hierarchy) kept=cv2.cvtColor(w_back, cv2.COLOR_RGB2GRAY ) kept_obj= cv2.bitwise_not(kept) mask=np.copy(kept_obj) obj_area=cv2.countNonZero(kept_obj) kept_cnt,hierarchy=cv2.findContours(kept_obj,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) cv2.drawContours(ori_img,kept_cnt,-1, (0,255,0),-1, lineType=8,hierarchy=hierarchy) cv2.drawContours(ori_img,roi_contour,-1, (255,0,0),5, lineType=8,hierarchy=roi_hierarchy) # Allows uer to cut objects to the ROI (all objects completely outside ROI will not be kept) elif roi_type=='cutto': cv2.drawContours(background1,object_contour,-1, (255,255,255),-1, lineType=8,hierarchy=obj_hierarchy) roi_points=np.vstack(roi_contour[0]) cv2.fillPoly(background2,[roi_points], (255,255,255)) obj_roi=cv2.multiply(background1,background2) kept_obj=cv2.cvtColor(obj_roi, cv2.COLOR_RGB2GRAY) mask=np.copy(kept_obj) obj_area=cv2.countNonZero(kept_obj) kept_cnt,hierarchy = cv2.findContours(kept_obj,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) cv2.drawContours(w_back,kept_cnt,-1, (0,0,0),-1) cv2.drawContours(ori_img,kept_cnt,-1, (0,255,0),-1, lineType=8,hierarchy=hierarchy) cv2.drawContours(ori_img,roi_contour,-1, (255,0,0),5, lineType=8,hierarchy=roi_hierarchy) else: fatal_error('ROI Type' + str(roi_type) + ' is not "cutto" or "partial"!') if debug: print_image(w_back, (str(device) + '_roi_objects.png')) print_image(ori_img, (str(device) + '_obj_on_img.png')) print_image(mask, (str(device) + '_roi_mask.png')) #print ('Object Area=', obj_area) return device, kept_cnt, hierarchy, mask, obj_area
#change image so that tiller number is written on the image. #read in image tiller_img=cv2.imread(str(img_path)) img=np.copy(tiller_img) ix,iy,iz=np.shape(img) x=ix/10 y=iy/10 y1=iy/7 text=('Raw Tiller Count='+str(raw_count)) text1=('Normalized Tiller Count='+str(tiller_count_total)) cv2.putText(img,text, (x,y), cv2.FONT_HERSHEY_SIMPLEX, 3,(0,0,255),4) cv2.putText(img,text1, (x,y1), cv2.FONT_HERSHEY_SIMPLEX, 3,(0,0,255),4) name_img=str(tillering_img_path)+str(barcode)+'_'+'Frame_'+str(frame)+'_day'+str(date_int)+'_'+str(datetime) + '_tillering_img.png' pcv.print_image(img,name_img) # Put the data for each barcode into the hash if frame==0: data_dict['raw_width_0']=int_raw_width_all data_dict['raw_count_0']=raw_count data_dict['normalized_width_0']=width_all data_dict['normalized_count_0']=tiller_count_total data_dict['img_path_0']=name_img elif frame==90: data_dict['raw_width_90']=int_raw_width_all data_dict['raw_count_90']=raw_count data_dict['normalized_width_90']=width_all data_dict['normalized_count_90']=tiller_count_total data_dict['img_path_90']=name_img
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 slice_stitch(sqlitedb, outdir, camera_label='vis_sv', spacer='on', makefig='yes'): #sqlitedb = sqlite database to query (path to db) #outdir = path to outdirectory #camera_label = either 'vis_tv','vis_sv',or 'fluor_tv' #spacer = either 'on' or 'off', adds a white line between day breaks #makefig = either 'yes' or 'no', adds labels to days and a title i = datetime.now() timenow = i.strftime('%m-%d-%Y_%H:%M:%S') newfolder = "slice_analysis_" + (str(timenow)) os.mkdir((str(outdir) + newfolder)) connect = sq.connect(sqlitedb) connect.row_factory = dict_factory connect.text_factory = str c = connect.cursor() h = connect.cursor() m = connect.cursor() k = connect.cursor() id_array = [] path_array = [] unique_array = [] for date in c.execute('select min(datetime) as first from snapshots'): firstday = date['first'] for i, group in enumerate( m.execute( 'select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where type = "slice" order by plant_id asc' )): plant_id = group['plant_id'] plantgeno = re.match('^([A-Z][a-zA-Z]\d*[A-Z]{2})', plant_id) if plantgeno == None: plantgeno_id = group['plant_id'] id_array.append(plantgeno_id, ) else: span1, span2 = plantgeno.span() plantgeno_id = group['plant_id'][span1:span2] id_array.append(plantgeno_id, ) id_unique = np.unique(id_array) if spacer == 'on': for group_label in id_unique: ch1 = [] ch2 = [] ch3 = [] time_array = [] for i, data in enumerate( h.execute( 'select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where plant_id like ? and type = "slice" and camera=? order by datetime asc', ( "%" + group_label + "%", camera_label, ))): date_int = ((data['datetime'] - firstday) / 86400) time_array.append(date_int) for i, data in enumerate( k.execute( 'select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where plant_id like ? and type = "slice" and camera=? order by datetime asc', ( "%" + group_label + "%", camera_label, ))): if i == 0: line1 = cv2.imread(data['image_path']) split1, split2, split3 = np.dsplit(line1, 3) split1_f = split1.flatten() split2_f = split2.flatten() split3_f = split3.flatten() stacked_1 = np.column_stack( (split1_f, split1_f, split1_f, split1_f, split1_f)) stacked_2 = np.column_stack( (split2_f, split2_f, split2_f, split2_f, split2_f)) stacked_3 = np.column_stack( (split3_f, split3_f, split3_f, split3_f, split3_f)) stacked_1t = np.transpose(stacked_1) stacked_2t = np.transpose(stacked_2) stacked_3t = np.transpose(stacked_3) ch1.extend(stacked_1t) ch2.extend(stacked_2t) ch3.extend(stacked_3t) elif time_array[i - 1] == time_array[i]: line1 = cv2.imread(data['image_path']) split1, split2, split3 = np.dsplit(line1, 3) split1_f = split1.flatten() split2_f = split2.flatten() split3_f = split3.flatten() stacked_1 = np.column_stack( (split1_f, split1_f, split1_f, split1_f, split1_f)) stacked_2 = np.column_stack( (split2_f, split2_f, split2_f, split2_f, split2_f)) stacked_3 = np.column_stack( (split3_f, split3_f, split3_f, split3_f, split3_f)) stacked_1t = np.transpose(stacked_1) stacked_2t = np.transpose(stacked_2) stacked_3t = np.transpose(stacked_3) ch1.extend(stacked_1t) ch2.extend(stacked_2t) ch3.extend(stacked_3t) else: line1 = cv2.imread(data['image_path']) split1, split2, split3 = np.dsplit(line1, 3) split1_f = split1.flatten() split2_f = split2.flatten() split3_f = split3.flatten() spacer_size = np.shape(split1_f) spacer1 = np.zeros(spacer_size) spacer_f = spacer1 + 255 stacked_1 = np.column_stack( (spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f)) stacked_2 = np.column_stack( (spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f)) stacked_3 = np.column_stack( (spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f, spacer_f)) stacked_1t = np.transpose(stacked_1) stacked_2t = np.transpose(stacked_2) stacked_3t = np.transpose(stacked_3) ch1.extend(stacked_1t) ch2.extend(stacked_2t) ch3.extend(stacked_3t) stacked_4 = np.column_stack( (split1_f, split1_f, split1_f, split1_f, split1_f)) stacked_5 = np.column_stack( (split2_f, split2_f, split2_f, split2_f, split2_f)) stacked_6 = np.column_stack( (split3_f, split3_f, split3_f, split3_f, split3_f)) stacked_4t = np.transpose(stacked_4) stacked_5t = np.transpose(stacked_5) stacked_6t = np.transpose(stacked_6) ch1.extend(stacked_4t) ch2.extend(stacked_5t) ch3.extend(stacked_6t) color_cat = np.dstack((ch1, ch2, ch3)) pcv.print_image( color_cat, (str(outdir) + str(newfolder) + "/" + str(group_label) + "_" + str(camera_label) + "_spacer_" + str(spacer) + "_slice_joined_img.png")) if spacer == 'off': for group_label in id_unique: ch1 = [] ch2 = [] ch3 = [] for i, data in enumerate( h.execute( 'select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where plant_id like ? and type = "slice" and camera=? order by datetime asc', ( "%" + group_label + "%", camera_label, ))): line1 = cv2.imread(data['image_path']) split1, split2, split3 = np.dsplit(line1, 3) split1_f = split1.flatten() split2_f = split2.flatten() split3_f = split3.flatten() stacked_1 = np.column_stack( (split1_f, split1_f, split1_f, split1_f, split1_f)) stacked_2 = np.column_stack( (split2_f, split2_f, split2_f, split2_f, split2_f)) stacked_3 = np.column_stack( (split3_f, split3_f, split3_f, split3_f, split3_f)) stacked_1t = np.transpose(stacked_1) stacked_2t = np.transpose(stacked_2) stacked_3t = np.transpose(stacked_3) ch1.extend(stacked_1t) ch2.extend(stacked_2t) ch3.extend(stacked_3t) color_cat = np.dstack((ch1, ch2, ch3)) pcv.print_image(color_cat, (str(outdir) + newfolder + "/" + str(group_label) + "_" + str(camera_label) + "_spacer_" + str(spacer) + "_slice_joined_img.png")) folder_path = (str(outdir) + newfolder) if makefig == 'yes': list_files = os.listdir(folder_path) sorted_list = sorted(list_files) for group_label in id_unique: time_array = [] length_time = [] ypos = [] ypos1 = [] ypos2 = [] unique_time1 = [] for i, data in enumerate( h.execute( 'select * from snapshots inner join analysis_images on snapshots.image_id = analysis_images.image_id where plant_id like ? and type = "slice" and camera=? order by datetime asc', ( "%" + group_label + "%", camera_label, ))): date_int = ((data['datetime'] - firstday) / 86400) time_array.append(date_int) unique_time = np.unique(time_array) for times in unique_time: length = [] for i, time in enumerate(time_array): if time_array[i] == times: tm = 1 length.append(tm) else: tm = 0 length.append(tm) sum_time = np.sum(length) length_time.append(sum_time) if spacer == 'off': for i, length in enumerate(length_time): if i == 0: yadd = length * 5 ypos.append(yadd) else: yadd = (length * 5) ypos.append(yadd) elif spacer == 'on': for i, length in enumerate(length_time): if i == 0: yadd = length * 5 ypos.append(yadd) else: yadd = (length * 5) + 10 ypos.append(yadd) for i, y in enumerate(ypos): if i == 0: y1 = y ypos1.append(y1) else: y1 = y + ypos1[i - 1] ypos1.append(y1) for time in unique_time: time1 = time + 1 unique_time1.append(time1) file_name = str(group_label) + "_" + str( camera_label) + "_spacer_" + str( spacer) + "_slice_joined_img.png" img1 = cv2.imread((str(folder_path) + "/" + str(file_name)), -1) if len(np.shape(img1)) == 3: ch1, ch2, ch3 = np.dsplit(img1, 3) img = np.dstack((ch3, ch2, ch1)) plt.imshow(img) ax = plt.subplot(111) ax.set_ylabel('Days on Bellwether Phenotyper', size=10) ax.set_yticks(ypos1) ax.set_yticklabels(unique_time1, size=5) ax.yaxis.tick_left() ax.set_xticks([0, 255]) ax.set_xticklabels([0, 255], size=5) for t in ax.yaxis.get_ticklines(): t.set_color('white') for t in ax.xaxis.get_ticklines(): t.set_color('white') for line in ax.get_xticklines() + ax.get_yticklines(): line.set_alpha(0) ax.spines['bottom'].set_color('none') ax.spines['top'].set_color('none') ax.spines['left'].set_color('none') ax.spines['right'].set_color('none') #ax.tick_params(axis='y',direction='out') plt.title(str(group_label)) fig_name = (str(folder_path) + "/" + str(group_label) + "_spacer_" + str(spacer) + "_slice_join_figure_img.png") plt.savefig(fig_name, dpi=300) plt.clf() return folder_path