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)
Exemple #4
0
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)
Exemple #5
0
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),