def segment_image(img, template_img, heat_map, mask, anomaly_loc_and_label, original_img_shape, save_image_dir, class_name, image_name): height, width = original_img_shape[:2] img = cv2.resize(img, (height, width)) template_img = template_img.numpy().astype("uint8") template_img = template_img.transpose(1, 2, 0) template_img = cv2.resize(template_img, (height, width)) heat_map = cv2.resize(heat_map, (height, width)) mask = cv2.resize(mask, (height, width)) image_label_for_classifiation = [] mask = mask.astype("uint8") mask, mask_contour, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # loop over the contours for i, cnt in enumerate(mask_contour): # image segment from predicted mask mask_predicted = cv2.fillPoly(np.zeros_like(img), [cnt], (255, 255, 255)) for point, label in anomaly_loc_and_label.items(): shape = np.array(decode_labelme_shape(point)) shape = shape.astype("uint8") x1, y1, x2, y2 = shape[:, 0].min(), shape[:, 1].min( ), shape[:, 0].max(), shape[:, 1].max() mask_annotation, binary, contours_annotation, hierarchy = pcv.rectangle_mask( img=img, p1=(x1, y1), p2=(x2, y2), color="black") mask_combined = cv2.bitwise_and(mask_annotation, mask_predicted) mask_combined = cv2.cvtColor(mask_combined, cv2.COLOR_BGR2GRAY) rect, binary_mask_combined = cv2.threshold(mask_combined, 5, 255, cv2.THRESH_BINARY) binary_mask_combined, contour_combined, obj_hierarchy = cv2.findContours( binary_mask_combined, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contour_area_threshold = 2 if len(contour_combined) > 0: contour_area_comblined = cv2.contourArea( contour_combined[0]) * contour_area_threshold else: continue if contours_annotation == []: continue if contour_area_comblined >= cv2.contourArea( contours_annotation[0] ) or contour_area_comblined >= cv2.contourArea(cnt): foreground = cv2.bitwise_and(img, mask_predicted) bounding_box = cv2.boundingRect(cnt) x, y, w, h = bounding_box #croped_region_pure_foreground = foreground[y:y+h,x:x+w] # only fore groud #get maskfrom heat map small_mask = get_mask_from_heat_map(heat_map) small_mask_pure_foreground = crop_image( small_mask, bounding_box) croped_region_pure_foreground = crop_image(img, bounding_box) croped_template_img = crop_image(template_img, bounding_box) if w > 7 and h > 7: if small_mask_pure_foreground.size != 0 and small_mask_pure_foreground.max( ) != 0: croped_region_pure_foreground = grabcut_image_segment( croped_region_pure_foreground, small_mask_pure_foreground) #print(croped_region_pure_foreground.shape,croped_template_img.shape) flag, diff_mask, bounding_box_diff = get_mask_from_backgroud_subtraction( croped_region_pure_foreground, croped_template_img) if flag == 1: croped_region_pure_foreground = crop_image( croped_region_pure_foreground, bounding_box_diff) croped_diff_mask = crop_image(diff_mask, bounding_box_diff) croped_region_pure_foreground = cv2.bitwise_and( croped_region_pure_foreground, croped_diff_mask) if croped_region_pure_foreground.size > 0: plt.imshow(croped_region_pure_foreground[:, :, ::-1]) plt.axis("off") save_file_name = os.path.join(save_image_dir, image_name) save_file_dir, save_image_name = os.path.split( save_file_name) save_file_name_without_ext = os.path.splitext( save_image_name)[0] if not os.path.exists(save_file_dir): os.makedirs(save_file_dir) save_image_name_new = os.path.join( save_file_dir, save_file_name_without_ext + "_" + str(i) + ".jpg") plt.imsave(save_image_name_new, croped_region_pure_foreground) image_name_label_list = [save_image_name_new, label] if image_name_label_list not in image_label_for_classifiation: image_label_for_classifiation.append( image_name_label_list) with open( os.path.join( save_image_dir, "Padim_segment_image_name_label_for_classification.txt"), "a+") as fid: fid.writelines([ save_image_name_new + " " + str(i[1]) + "\n" for i in image_label_for_classifiation ])
def main_side(): # Setting "args" # Get options pcv.params.debug = args.debug #set debug mode pcv.params.debug_outdir = args.outdir #set output directory # Read image (readimage mode defaults to native but if image is RGBA then specify mode='rgb') # Inputs: # filename - Image file to be read in # mode - Return mode of image; either 'native' (default), 'rgb', 'gray', or 'csv' filename = args.image img = cv2.imread(args.image, flags=0) #img = pcv.invert(img) path, img_name = os.path.split(args.image) img_bkgrd = cv2.imread("background.png", flags=0) #print(img) #print(img_bkgrd) bkg_sub_img = pcv.image_subtract(img_bkgrd, img) bkg_sub_thres_img, masked_img = pcv.threshold.custom_range( rgb_img=bkg_sub_img, lower_thresh=[50], upper_thresh=[255], channel='gray') # Laplace filtering (identify edges based on 2nd derivative) # Inputs: # gray_img - Grayscale image data # ksize - Aperture size used to calculate the second derivative filter, # specifies the size of the kernel (must be an odd integer) # scale - Scaling factor applied (multiplied) to computed Laplacian values # (scale = 1 is unscaled) lp_img = pcv.laplace_filter(gray_img=img, ksize=1, scale=1) # Plot histogram of grayscale values pcv.visualize.histogram(gray_img=lp_img) # Lapacian image sharpening, this step will enhance the darkness of the edges detected lp_shrp_img = pcv.image_subtract(gray_img1=img, gray_img2=lp_img) # Plot histogram of grayscale values, this helps to determine thresholding value pcv.visualize.histogram(gray_img=lp_shrp_img) # Sobel filtering # 1st derivative sobel filtering along horizontal axis, kernel = 1) # Inputs: # gray_img - Grayscale image data # dx - Derivative of x to analyze # dy - Derivative of y to analyze # ksize - Aperture size used to calculate 2nd derivative, specifies the size of the kernel and must be an odd integer # NOTE: Aperture size must be greater than the largest derivative (ksize > dx & ksize > dy) sbx_img = pcv.sobel_filter(gray_img=img, dx=1, dy=0, ksize=1) # 1st derivative sobel filtering along vertical axis, kernel = 1) sby_img = pcv.sobel_filter(gray_img=img, dx=0, dy=1, ksize=1) # Combine the effects of both x and y filters through matrix addition # This will capture edges identified within each plane and emphasize edges found in both images # Inputs: # gray_img1 - Grayscale image data to be added to gray_img2 # gray_img2 - Grayscale image data to be added to gray_img1 sb_img = pcv.image_add(gray_img1=sbx_img, gray_img2=sby_img) # Use a lowpass (blurring) filter to smooth sobel image # Inputs: # gray_img - Grayscale image data # ksize - Kernel size (integer or tuple), (ksize, ksize) box if integer input, # (n, m) box if tuple input mblur_img = pcv.median_blur(gray_img=sb_img, ksize=1) # Inputs: # gray_img - Grayscale image data mblur_invert_img = pcv.invert(gray_img=mblur_img) # 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 edge_shrp_img = pcv.image_add(gray_img1=mblur_invert_img, gray_img2=lp_shrp_img) # Perform thresholding to generate a binary image tr_es_img = pcv.threshold.binary(gray_img=edge_shrp_img, threshold=145, max_value=255, object_type='dark') # Do erosion with a 3x3 kernel (ksize=3) # Inputs: # gray_img - Grayscale (usually binary) image data # ksize - The size used to build a ksize x ksize # matrix using np.ones. Must be greater than 1 to have an effect # i - An integer for the number of iterations e1_img = pcv.erode(gray_img=tr_es_img, ksize=3, i=1) # Bring the two object identification approaches together. # Using a logical OR combine object identified by background subtraction and the object identified by derivative filter. # Inputs: # bin_img1 - Binary image data to be compared in bin_img2 # bin_img2 - Binary image data to be compared in bin_img1 comb_img = pcv.logical_or(bin_img1=e1_img, bin_img2=bkg_sub_thres_img) # Get masked image, Essentially identify pixels corresponding to plant and keep those. # Inputs: # rgb_img - RGB image data # mask - Binary mask image data # mask_color - 'black' or 'white' masked_erd = pcv.apply_mask(rgb_img=img, mask=comb_img, mask_color='black') # Need to remove the edges of the image, we did that by generating a set of rectangles to mask the edges # img is (1280 X 960) # mask for the bottom of the image # Inputs: # img - RGB or grayscale image data # p1 - Point at the top left corner of the rectangle (tuple) # p2 - Point at the bottom right corner of the rectangle (tuple) # color 'black' (default), 'gray', or 'white' # masked1, box1_img, rect_contour1, hierarchy1 = pcv.rectangle_mask(img=img, p1=(500, 875), p2=(720, 960)) # mask the edges masked2, box2_img, rect_contour2, hierarchy2 = pcv.rectangle_mask(img=img, p1=(1, 1), p2=(1279, 959)) bx12_img = pcv.logical_or(bin_img1=box1_img, bin_img2=box2_img) inv_bx1234_img = bx12_img # we dont invert inv_bx1234_img = bx12_img #inv_bx1234_img = pcv.invert(gray_img=bx12_img) edge_masked_img = pcv.apply_mask(rgb_img=masked_erd, mask=inv_bx1234_img, mask_color='black') #print("here we create a mask") mask, masked = pcv.threshold.custom_range(rgb_img=edge_masked_img, lower_thresh=[25], upper_thresh=[175], channel='gray') masked = pcv.apply_mask(rgb_img=masked, mask=mask, mask_color='white') #print("end") # Identify objects # Inputs: # img - RGB or grayscale image data for plotting # mask - Binary mask used for detecting contours id_objects, obj_hierarchy = pcv.find_objects(img=edge_masked_img, mask=mask) # Define ROI # Inputs: # img - RGB or grayscale image to plot the ROI on # x - The x-coordinate of the upper left corner of the rectangle # y - The y-coordinate of the upper left corner of the rectangle # h - The height of the rectangle # w - The width of the rectangle roi1, roi_hierarchy = pcv.roi.rectangle(img=edge_masked_img, x=100, y=100, h=800, w=1000) # Decide which objects to keep # Inputs: # img = img to display kept objects # roi_contour = contour of roi, output from any ROI function # roi_hierarchy = contour of roi, output from any ROI function # object_contour = contours of objects, output from pcv.find_objects function # obj_hierarchy = hierarchy of objects, output from pcv.find_objects function # roi_type = 'partial' (default, for partially inside), 'cutto', or # 'largest' (keep only largest contour) with HiddenPrints(): roi_objects, hierarchy5, kept_mask, obj_area = pcv.roi_objects( img=edge_masked_img, roi_contour=roi1, roi_hierarchy=roi_hierarchy, object_contour=id_objects, obj_hierarchy=obj_hierarchy, roi_type='largest') rgb_img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) # Inputs: # img - RGB or grayscale image data for plotting # contours - Contour list # hierarchy - Contour hierarchy array o, m = pcv.object_composition(img=rgb_img, contours=roi_objects, hierarchy=hierarchy5) ### Analysis ### outfile = False if args.writeimg == True: outfile = args.outdir + "/" + filename # Perform signal analysis # Inputs: # img - RGB or grayscale image data # obj- Single or grouped contour object # mask - Binary image mask to use as mask for moments analysis shape_img = pcv.analyze_object(img=img, obj=o, mask=m) new_im = Image.fromarray(shape_img) new_im.save("output//" + args.filename + "shape_img_side.png") # Inputs: # gray_img - 8 or 16-bit grayscale image data # mask - Binary mask made from selected contours # bins - Number of classes to divide the spectrum into # histplot - If True, plots the histogram of intensity values nir_hist = pcv.analyze_nir_intensity(gray_img=img, mask=kept_mask, bins=256, histplot=True) # Pseudocolor the grayscale image to a colormap # Inputs: # gray_img - Grayscale image data # obj - Single or grouped contour object (optional), if provided the pseudocolored image gets cropped down to the region of interest. # mask - Binary mask (optional) # background - Background color/type. Options are "image" (gray_img), "white", or "black". A mask must be supplied. # cmap - Colormap # min_value - Minimum value for range of interest # max_value - Maximum value for range of interest # dpi - Dots per inch for image if printed out (optional, if dpi=None then the default is set to 100 dpi). # axes - If False then the title, x-axis, and y-axis won't be displayed (default axes=True). # colorbar - If False then the colorbar won't be displayed (default colorbar=True) pseudocolored_img = pcv.visualize.pseudocolor(gray_img=img, mask=kept_mask, cmap='viridis') # Perform shape analysis # Inputs: # img - RGB or grayscale image data # obj- Single or grouped contour object # mask - Binary image mask to use as mask for moments analysis shape_imgs = pcv.analyze_object(img=rgb_img, obj=o, mask=m) # Write shape and nir data to results file pcv.print_results(filename=args.result)
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) pcv.params.debug = args.debug #set debug mode # STEP 1: white balance (for comparison across images) # inputs: # img = image object, RGB colorspace # roi = region for white reference (position of ColorChecker Passport) img1 = pcv.white_balance(img, roi=(910, 3555, 30, 30)) # STEP 2: Mask out color card and stake # inputs: # img = grayscale image ('a' channel) # p1 = (x,y) coordinates for top left corner of rectangle # p2 = (x,y) coordinates for bottom right corner of rectangle # color = color to make the mask (white here to match background) masked, binary, contours, hierarchy = pcv.rectangle_mask(img1, (0, 2000), (1300, 4000), color="white") masked2, binary, contours, hierarchy = pcv.rectangle_mask(masked, (0, 3600), (4000, 4000), color="white") # STEP 3: Convert from RGB colorspace to LAB colorspace # Keep green-magenta channel (a) # inputs: # img = image object, RGB colorspace # channel = color subchannel ('l' = lightness, 'a' = green-magenta, 'b' = blue-yellow) a = pcv.rgb2gray_lab(masked2, 'l') # STEP 4: Set a binary threshold on the saturation channel image # inputs: # img = img object, grayscale # threshold = treshold value (0-255) - need to adjust this # max_value = value to apply above treshold (255 = white) # object_type = light or dark img_binary = pcv.threshold.binary(a, 118, 255, object_type="dark") # STEP 5: Apply Gaussian blur to binary image (reduced noise) # inputs: # img = img object, binary # ksize = tuple of kernel dimensions, e.g. (5,5) blur_image = pcv.median_blur(img_binary, 10) # STEP 6: Fill small objects (speckles) # inputs: # img = img object, binary # size = minimum object area size in pixels fill_image1 = pcv.fill(blur_image, 150000) # STEP 7: Invert image to fill gaps # inputs: # img = img object, binary inv_image = pcv.invert(fill_image1) # rerun fill on inverted image inv_fill = pcv.fill(inv_image, 25000) # invert image again fill_image = pcv.invert(inv_fill) # STEP 8: Dilate to avoid losing detail # inputs: # img = img object, binary # ksize = kernel size # i = iterations (number of consecutive filtering passes) dilated = pcv.dilate(fill_image, 2, 1) # STEP 9: Find objects (contours: black-white boundaries) # inputs: # img = img object, RGB colorspace # mask = binary image used for object detection id_objects, obj_hierarchy = pcv.find_objects(img1, dilated) # STEP 10: Define region of interest (ROI) # inputs: # img = img object to overlay ROI # x = x-coordinate of upper left corner for rectangle # y = y-coordinate of upper left corner for rectangle # h = height of rectangle # w = width of rectangle roi_contour, roi_hierarchy = pcv.roi.rectangle(img=img1, x=20, y=10, h=3000, w=3000) # STEP 11: Keep objects that overlap with the ROI # inputs: # img = img where selected objects will be displayed # roi_type = options are 'cutto', 'partial' (objects are partially inside roi), or 'largest' (keep only the biggest boi) # roi_countour = contour of roi, output from 'view and adjust roi' function (STEP 10) # roi_hierarchy = contour of roi, output from 'view and adjust roi' function (STEP 10) # object_contour = contours of objects, output from 'identifying objects' function (STEP 9) # obj_hierarchy = hierarchy of objects, output from 'identifying objects' function (STEP 9) roi_objects, roi_obj_hierarchy, kept_mask, obj_area = pcv.roi_objects( img1, 'partial', roi_contour, roi_hierarchy, id_objects, obj_hierarchy) # STEP 12: Cluster multiple contours in an image based on user input of rows/columns # inputs: # img = img object (RGB colorspace) # roi_objects = object contours in an image that will be clustered (output from STEP 11) # roi_obj_hierarchy = object hierarchy (also from STEP 11) # nrow = number of rows for clustering (desired rows in image even if no leaf present in all) # ncol = number of columns to cluster (desired columns in image even if no leaf present in all) clusters_i, contours, hierarchies = pcv.cluster_contours( img1, roi_objects, roi_obj_hierarchy, 3, 3) # STEP 13: select and split clustered contours to export into multiple images # also checks if number of inputted filenames matches number of clustered contours # if no filenames, objects are numbered in order # inputs: # img = masked RGB image # grouped_contour_indexes = indexes of clustered contours, output of 'cluster_contours' (STEP 12) # contours = contours of cluster, output of 'cluster_contours' (STEP 12) # hierarchy = object hierarchy (from STEP 12) # outdir = directory to export output images # file = name of input image to use as basename (uses filename from 'readimage') # filenames = (optional) txt file with list of filenames ordered from top to bottom/left to right # Set global debug behavior to None (default), "print" (to file), or "plot" (Jupyter Notebooks or X11) pcv.params.debug = None out = args.outdir # names = args.namesout = "./" output_path, imgs, masks = pcv.cluster_contour_splitimg(img1, clusters_i, contours, hierarchies, out, file=filename, filenames=None)
def image_avg(fundf): global c, h, roi_c, roi_h fn_min = fundf.filename.iloc[0] fn_max = fundf.filename.iloc[1] param_name = fundf['parameter'].iloc[0] outfn = os.path.splitext(os.path.basename(fn_max))[0] outfn_split = outfn.split('-') basefn = "-".join(outfn_split[0:-1]) outfn_split[-1] = param_name outfn = "-".join(outfn_split) print(outfn) sampleid = outfn_split[2] fmaxdir = os.path.join(fluordir, sampleid) os.makedirs(fmaxdir, exist_ok=True) if pcv.params.debug == 'print': debug_outdir = os.path.join(debugdir, outfn) if not os.path.exists(debug_outdir): os.makedirs(debug_outdir) pcv.params.debug_outdir = debug_outdir # read images and create mask from max fluorescence # read image as is. only gray values in PSII images imgmin, _, _ = pcv.readimage(fn_min) img, _, _ = pcv.readimage(fn_max) fdark = np.zeros_like(img) out_flt = fdark.astype('float32') # <- needs to be float32 for imwrite if param_name == 'FvFm': # create mask mask = createmasks.psIImask(img) # find objects and setup roi c, h = pcv.find_objects(img, mask) roi_c, roi_h = pcv.roi.multi(img, coord=(240, 180), radius=30, spacing=(150, 150), ncols=2, nrows=2) #setup individual roi plant masks newmask = np.zeros_like(mask) # compute fvfm YII, hist_fvfm = pcv.photosynthesis.analyze_yii(fdark=fdark, fmin=imgmin, fmax=img, mask=mask, bins=128, parameter='Fv/Fm') cv2.imwrite(os.path.join(fmaxdir, outfn + '_fvfm.tif'), YII.astype('float32')) NPQ = np.zeros_like(YII) # print Fm cv2.imwrite(os.path.join(fmaxdir, outfn + '_fmax.tif'), img) # NPQ will always be an array of 0s else: #use cv2 to read image becase pcv.readimage will save as input_image.png overwriting img newmask = cv2.imread(os.path.join(maskdir, basefn + '-FvFm_mask.png'), -1) # compute YII YII, hist_yii = pcv.photosynthesis.analyze_yii(fdark=fdark, fmin=imgmin, fmax=img, mask=newmask, bins=64, parameter=param_name) cv2.imwrite(os.path.join(fmaxdir, outfn + '_yii.tif'), YII.astype('float32')) # compute NPQ Fm = cv2.imread(os.path.join(fmaxdir, basefn + '-FvFm_fmax.tif'), -1) NPQ, hist_npq = pcv.photosynthesis.analyze_npq(fm=Fm, fmax=img, mask=newmask, bins=64) cv2.imwrite(os.path.join(fmaxdir, outfn + '_npq.tif'), NPQ.astype('float32')) # Make as many copies of incoming dataframe as there are ROIs outdf = fundf.copy() for i in range(0, len(roi_c) - 1): outdf = outdf.append(fundf) outdf.imageid = outdf.imageid.astype('uint8') # Initialize lists to store variables for each ROI and iterate frame_avg = [] yii_avg = [] yii_std = [] npq_avg = [] npq_std = [] plantarea = [] ithroi = [] inbounds = [] i = 0 rc = roi_c[i] for i, rc in enumerate(roi_c): # Store iteration Number ithroi.append(int(i)) ithroi.append(int(i)) # append twice so each image has a value. # extract ith hierarchy rh = roi_h[i] # Filter objects based on being in the ROI try: roi_obj, hierarchy_obj, submask, obj_area = pcv.roi_objects( img, roi_contour=rc, roi_hierarchy=rh, object_contour=c, obj_hierarchy=h, roi_type='partial') except RuntimeError as err: print('!!!', err) frame_avg.append(np.nan) frame_avg.append(np.nan) yii_avg.append(np.nan) yii_avg.append(np.nan) yii_std.append(np.nan) yii_std.append(np.nan) npq_avg.append(np.nan) npq_avg.append(np.nan) npq_std.append(np.nan) npq_std.append(np.nan) inbounds.append(np.nan) inbounds.append(np.nan) plantarea.append(0) plantarea.append(0) else: # Combine multiple plant objects within an roi together plant_contour, plant_mask = pcv.object_composition( img=img, contours=roi_obj, hierarchy=hierarchy_obj) #combine plant masks after roi filter if param_name == 'FvFm': newmask = pcv.image_add(newmask, plant_mask) frame_avg.append(pcv.masked_stats.mean(imgmin, plant_mask)) frame_avg.append(pcv.masked_stats.mean(img, plant_mask)) # need double because there are two images per loop yii_avg.append(pcv.masked_stats.mean(YII, plant_mask)) yii_avg.append(pcv.masked_stats.mean(YII, plant_mask)) yii_std.append(pcv.masked_stats.std(YII, plant_mask)) yii_std.append(pcv.masked_stats.std(YII, plant_mask)) npq_avg.append(pcv.masked_stats.mean(NPQ, plant_mask)) npq_avg.append(pcv.masked_stats.mean(NPQ, plant_mask)) npq_std.append(pcv.masked_stats.std(NPQ, plant_mask)) npq_std.append(pcv.masked_stats.std(NPQ, plant_mask)) inbounds.append(pcv.within_frame(plant_mask)) inbounds.append(pcv.within_frame(plant_mask)) plantarea.append(obj_area * pixelresolution**2.) plantarea.append(obj_area * pixelresolution**2.) # with open(os.path.join(outdir, outfn + '_roi' + str(i) + '.txt'), 'w') as f: # for item in yii_avg: # f.write("%s\n" % item) #setup pseudocolor image size hgt, wdth = np.shape(newmask) figframe = 1 if len(roi_c) == 2: if i == 0: p1 = (int(0), int(0)) p2 = (int(hgt), int(hgt)) elif i == 1: p1 = (int(wdth - hgt), int(0)) p2 = (int(wdth), int(hgt)) elif len(roi_c) == 1: cutwidth = (wdth - hgt) / 2 p1 = (int(cutwidth), int(0)) p2 = (int(cutwidth + hgt), int(hgt)) else: figframe = None if figframe is not None: _, _, figframe, _ = pcv.rectangle_mask(plant_mask, p1, p2, color='white') figframe = figframe[0] # print pseduocolor imgdir = os.path.join(outdir, 'pseudocolor_images', sampleid, 'roi' + str(i)) if param_name == 'FvFm': imgdir = os.path.join(imgdir, 'fvfm') os.makedirs(imgdir, exist_ok=True) else: imgdir = os.path.join(imgdir, 'IndC') os.makedirs(imgdir, exist_ok=True) npq_img = pcv.visualize.pseudocolor(NPQ, obj=figframe, mask=plant_mask, cmap='inferno', axes=False, min_value=0, max_value=2.5, background='black', obj_padding=0) npq_img = add_scalebar.add_scalebar( npq_img, pixelresolution=pixelresolution, barwidth=20, barlocation='lower right') npq_img.savefig(os.path.join( imgdir, outfn + '_roi' + str(i) + '_NPQ.png'), bbox_inches='tight') npq_img.clf() yii_img = pcv.visualize.pseudocolor( YII, obj=figframe, mask=plant_mask, cmap=custom_colormaps.get_cmap('imagingwin'), axes=False, min_value=0, max_value=1, background='black', obj_padding=0) yii_img = add_scalebar.add_scalebar( yii_img, pixelresolution=pixelresolution, barwidth=20, barlocation='lower right') yii_img.savefig(os.path.join(imgdir, outfn + '_roi' + str(i) + '_YII.png'), bbox_inches='tight') yii_img.clf() # end try-except-else # end roi loop # save mask of all plants to file after roi filter if param_name == 'FvFm': pcv.print_image(newmask, os.path.join(maskdir, outfn + '_mask.png')) # save pseudocolor of all plants in image imgdir = os.path.join(outdir, 'pseudocolor_images', sampleid) npq_img = pcv.visualize.pseudocolor(NPQ, obj=None, mask=newmask, cmap='inferno', axes=False, min_value=0, max_value=2.5, background='black', obj_padding=0) npq_img = add_scalebar.add_scalebar(npq_img, pixelresolution=pixelresolution, barwidth=20, barlocation='lower right') npq_img.savefig(os.path.join(imgdir, outfn + '_NPQ.png'), bbox_inches='tight') npq_img.clf() yii_img = pcv.visualize.pseudocolor( YII, obj=None, mask=newmask, cmap=custom_colormaps.get_cmap('imagingwin'), axes=False, min_value=0, max_value=1, background='black', obj_padding=0) yii_img = add_scalebar.add_scalebar(yii_img, pixelresolution=pixelresolution, barwidth=20, barlocation='lower right') yii_img.savefig(os.path.join(imgdir, outfn + '_YII.png'), bbox_inches='tight') yii_img.clf() # check yii values for uniqueness # a single value isn't always robust. I think because there ae small independent objects that fall in one roi but not the other that change the object within the roi slightly. rounded_avg = [round(n, 3) for n in yii_avg] rounded_std = [round(n, 3) for n in yii_std] isunique = not (rounded_avg.count(rounded_avg[0]) == len(yii_avg) and rounded_std.count(rounded_std[0]) == len(yii_std)) # save all values to outgoing dataframe outdf['roi'] = ithroi outdf['frame_avg'] = frame_avg outdf['yii_avg'] = yii_avg outdf['npq_avg'] = npq_avg outdf['yii_std'] = yii_std outdf['npq_std'] = npq_std outdf['plantarea'] = plantarea outdf['obj_in_frame'] = inbounds outdf['unique_roi'] = isunique return (outdf)
pcv.params.debug=None for i,g in enumerate(grps): print(i,g) # read fluor data imgfns = get_filenames(basepath,g) Fo, Fm, FsLss, FmpLss = get_fluor(imgfns, os.path.join(basepath,g)) # make mask # filters.try_all_threshold(Fm_gray) ty = filters.threshold_otsu(Fm) print(ty) mask = pcv.threshold.binary(Fm, ty, 255, 'light') mask = pcv.fill(mask, 100) _,rect,_,_ = pcv.rectangle_mask(mask,(300,180),(750,600),'white') mask = pcv.logical_and(mask,rect) # compute apply mask and compute paramters out_flt = np.zeros_like(Fm, dtype='float') # fv/fm Fv = np.subtract(Fm,Fo, out=out_flt.copy(), where=mask>0) FvFm = np.divide(Fv,Fm, out=out_flt.copy(), where=np.logical_and(mask>0, Fo>0)) fvfm_fig = pcv.visualize.pseudocolor(FvFm, mask=mask, cmap='viridis', max_value=1) outfn = g+'_fvfm.png' fvfm_fig.set_size_inches(6, 6, forward=False) fvfm_fig.savefig(os.path.join(outdir,outfn),