Exemplo n.º 1
0
def generate_plant_mask_new(input_image):
    '''
    Generate a mask which segments the plant out in the input image

    Ref: https://plantcv.readthedocs.io/en/latest/vis_tutorial/

    Args:
        input_image: the input image
    Returns:
        mask: boolean numpy array as the same size of the input image which segments the plant
    '''

    # Get the saturation channel
    # hsv_image = rgb2hsv(input_image)
    # s = hsv_image[:,:,1]
    s = pcv.rgb2gray_hsv(rgb_img=input_image, channel='s')

    # threshold the saturation image
    s_thresh = s > 130

    # perform blur on the thresholding
    # s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)
    s_cnt = pcv.median_blur(gray_img=s_thresh, ksize=15)

    # extract the LAb channels and theshold them
    b = pcv.rgb2gray_lab(rgb_img=input_image, channel='b')
    a = pcv.rgb2gray_lab(rgb_img=input_image, channel='a')

    a_thresh = a <= 120
    b_thresh = b >= 105

    lab_mask = np.logical_and(a_thresh, b_thresh)

    lab_cnt = pcv.median_blur(gray_img=lab_mask, ksize=15)

    # join the two thresholdes mask
    bs = np.logical_and(s_cnt, lab_cnt)

    # filling small holes
    res = np.ones(bs.shape, dtype=np.uint8) * 255
    res[bs] = 0
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15))
    res = cv2.morphologyEx(res, cv2.MORPH_OPEN, kernel)

    res = res == 0

    return res
Exemplo n.º 2
0
def plant_cv(img):
    counter = 0
    debug = None

    counter, s = pcv.rgb2gray_hsv(img, 's', counter, debug)
    counter, s_thresh = pcv.binary_threshold(s, 145, 255, 'light', counter,
                                             debug)
    counter, s_mblur = pcv.median_blur(s_thresh, 5, counter, debug)

    # Convert RGB to LAB and extract the Blue channel
    counter, b = pcv.rgb2gray_lab(img, 'b', counter, debug)

    # Threshold the blue image
    counter, b_thresh = pcv.binary_threshold(b, 145, 255, 'light', counter,
                                             debug)
    counter, b_cnt = pcv.binary_threshold(b, 145, 255, 'light', counter, debug)
    # Join the thresholded saturation and blue-yellow images
    counter, bs = pcv.logical_or(s_mblur, b_cnt, counter, debug)
    counter, masked = pcv.apply_mask(img, bs, 'white', counter, debug)

    #----------------------------------------
    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    counter, masked_a = pcv.rgb2gray_lab(masked, 'a', counter, debug)
    counter, masked_b = pcv.rgb2gray_lab(masked, 'b', counter, debug)

    # Threshold the green-magenta and blue images
    counter, maskeda_thresh = pcv.binary_threshold(masked_a, 115, 255, 'dark',
                                                   counter, debug)
    counter, maskeda_thresh1 = pcv.binary_threshold(masked_a, 135, 255,
                                                    'light', counter, debug)
    counter, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light',
                                                   counter, debug)

    # Join the thresholded saturation and blue-yellow images (OR)
    counter, ab1 = pcv.logical_or(maskeda_thresh, maskedb_thresh, counter,
                                  debug)
    counter, ab = pcv.logical_or(maskeda_thresh1, ab1, counter, debug)
    counter, ab_cnt = pcv.logical_or(maskeda_thresh1, ab1, counter, debug)

    # Fill small objects
    counter, ab_fill = pcv.fill(ab, ab_cnt, 200, counter, debug)

    # Apply mask (for vis images, mask_color=white)
    counter, masked2 = pcv.apply_mask(masked, ab_fill, 'white', counter, debug)

    zeros = np.zeros(masked2.shape[:2], dtype="uint8")
    merged = cv2.merge([zeros, ab_fill, zeros])

    return merged, masked2
Exemplo n.º 3
0
def plot_hotspots(directory, filename):

    # Read image
    in_full_path = os.path.join(directory, filename)
    outfile = 'Hotspot' + filename
    out_full_path = os.path.join(directory, outfile)

    img, path, filename = pcv.readimage(in_full_path, mode="rgb")

    # Convert RGB to HSV and extract the saturation channel
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')

    # Threshold the saturation image
    s_thresh = pcv.threshold.binary(gray_img=s,
                                    threshold=85,
                                    max_value=255,
                                    object_type='light')

    # Median Blur
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)

    edge = cv2.Canny(s_mblur, 60, 180)
    fig, ax = plt.subplots(1, figsize=(12, 8))
    plt.imshow(edge, cmap='Greys')

    contours, hierarchy = cv2.findContours(edge.copy(), cv2.RETR_TREE,
                                           cv2.CHAIN_APPROX_NONE)[-2:]
    centroids = []
    contours = sorted(contours, key=cv2.contourArea, reverse=True)
    for i, cnt in enumerate(contours):
        if (cv2.contourArea(cnt) > 10):
            moment = cv2.moments(contours[i])
            Cx = int(moment["m10"] / moment["m00"])
            Cy = int(moment["m01"] / moment["m00"])
            center = (Cx, Cy)
            centroids.append((contours, center, moment["m00"], 0))
            cv2.circle(img, (Cx, Cy), 5, (255, 255, 255), -1)
            coordinate = '(' + str(Cx) + ',' + str(Cy) + ')'
            cv2.putText(img, coordinate, (Cx, Cy), cv2.FONT_HERSHEY_SIMPLEX,
                        0.5, RED, 1, cv2.LINE_AA)
            print(cv2.contourArea(cnt), Cx, Cy)
    cv2.imwrite(out_full_path, img)
    #cv2.imshow('canvasOutput', img);
    #cv2.waitKey(0)

    return
Exemplo n.º 4
0
def create_mask(grayscale):

    ndvi_mask = np.zeros(shape=[img.shape[0], img.shape[1]], dtype=np.uint8)

    for x in range(img.shape[1]):
        for y in range(img.shape[0]):

            # We keep pixels if they are within a certain range in terms of
            # grayscale intensity
            if X <= gray[y, x] <= 255:
                ndvi_mask[y, x] = gray[y, x]

    pcv.plot_image(ndvi_mask)

    # We use an opening function which removes noise from the image.
    opened = pcv.opening(ndvi_mask)
    # We blur pixels together, which removes more noise, and cleans up our mask.
    clean = pcv.median_blur(opened, X)

    return clean
Exemplo n.º 5
0
def main():
    # Get options
    args = options()

    pcv.params.debug = args.debug  # set debug mode
    pcv.params.debug_outdir = args.outdir  # set output directory

    # Read image
    img, path, filename = pcv.readimage(filename=args.image)

    # Convert RGB to HSV and extract the saturation channel
    h = pcv.rgb2gray_hsv(rgb_img=img, channel='h')

    # Threshold the saturation image
    h_thresh = pcv.threshold.binary(gray_img=h,
                                    threshold=85,
                                    max_value=255,
                                    object_type='dark')

    # Median Blur
    h_mblur = pcv.median_blur(gray_img=h_thresh, ksize=20)
Exemplo n.º 6
0
def segmentation(imgW, imgNIR, shape):
    # VIS example from PlantCV with few modifications

    # Higher value = more strict selection
    s_threshold = 165
    b_threshold = 200

    # Read image
    img = imread(imgW)
    #img = cvtColor(img, COLOR_BGR2RGB)
    imgNIR = imread(imgNIR)
    #imgNIR = cvtColor(imgNIR, COLOR_BGR2RGB)
    #img, path, img_filename = pcv.readimage(filename=imgW, mode="native")
    #imgNIR, pathNIR, imgNIR_filename = pcv.readimage(filename=imgNIR, mode="native")

    # Convert RGB to HSV and extract the saturation channel
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')

    # Threshold the saturation image
    s_thresh = pcv.threshold.binary(gray_img=s, threshold=s_threshold, max_value=255, object_type='light')

    # Median Blur
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)
    s_cnt = pcv.median_blur(gray_img=s_thresh, ksize=5)

    # Convert RGB to LAB and extract the Blue channel
    b = pcv.rgb2gray_lab(rgb_img=img, channel='b')

    # Threshold the blue image ORIGINAL 160
    b_thresh = pcv.threshold.binary(gray_img=b, threshold=b_threshold, max_value=255, object_type='light')
    b_cnt = pcv.threshold.binary(gray_img=b, threshold=b_threshold, max_value=255, object_type='light')

    # Join the thresholded saturation and blue-yellow images
    bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_cnt)

    # Apply Mask (for VIS images, mask_color=white)
    masked = pcv.apply_mask(img=img, mask=bs, mask_color='white')

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')

    # Threshold the green-magenta and blue images
    # 115
    # 135
    # 128
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a, threshold=115, max_value=255, object_type='dark')
    maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a, threshold=135, max_value=255, object_type='light')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b, threshold=128, max_value=255, object_type='light')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)

    # Fill small objects
    ab_fill = pcv.fill(bin_img=ab, size=200)

    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(img=masked, mask=ab_fill, mask_color='white')

    # Identify objects
    id_objects, obj_hierarchy = pcv.find_objects(img=masked2, mask=ab_fill)

    # Define ROI
    height = shape[0]
    width = shape[1]
    roi1, roi_hierarchy= pcv.roi.rectangle(img=masked2, x=0, y=0, h=height, w=width)

    # Decide which objects to keep
    roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img=img, roi_contour=roi1, 
                                                               roi_hierarchy=roi_hierarchy, 
                                                               object_contour=id_objects, 
                                                               obj_hierarchy=obj_hierarchy,
                                                               roi_type='partial')

    # Object combine kept objects
    obj, mask = pcv.object_composition(img=img, contours=roi_objects, hierarchy=hierarchy3)
    
    # Filling holes in the mask, works great for alive plants, not so good for dead plants
    filled_mask = pcv.fill_holes(mask)

    final = pcv.apply_mask(img=imgNIR, mask=mask, mask_color='white')
    pcv.print_image(final, "./segment/segment-temp.png")
Exemplo n.º 7
0
    # Collect the cropped image
    cropped_img = image[int(roi[1]):int(roi[1] + roi[3]),
                        int(roi[0]):int(roi[0] + roi[2])]

    # Convert RGB to HSV and extract saturation channel
    # The HSV value can be changed to be h, s, or v depending on the colour of the flower
    saturation_img = pcv.rgb2gray_hsv(cropped_img, 'h')

    # Threshold the saturation img
    # Depending on the output of the saturation image, the value can be light or dark
    # Light or dark is what defines what part of the image its to be removed
    saturation_thresh = pcv.threshold.binary(saturation_img, 85, 255, 'light')

    # Apply median blur
    saturation_mblur = pcv.median_blur(saturation_thresh, 5)

    # Convert RGB to LAB and extract blue channel
    # Like the HSV function this can be l, a, or b depending on the colour of the flower
    blue_channel_img = pcv.rgb2gray_lab(cropped_img, 'l')
    blue_channel_cnt = pcv.threshold.binary(blue_channel_img, 160, 255,
                                            'light')

    # Join thresholded saturated and blue channel imgs
    blue_saturated = pcv.logical_or(saturation_mblur, blue_channel_cnt)

    # Apply black colour mask
    masked = pcv.apply_mask(cropped_img, blue_saturated, 'black')

    # Save image
    cv2.imwrite('tmp/' + image, masked)
Exemplo n.º 8
0
        # cv2.imshow('aligned', ir_ir)

        # aligned_depth_color_frame = rs.colorizer().colorize(aligned_depth_frame)
        # aligned_depth_color_image = np.asanyarray(aligned_depth_color_frame.get_data())
        # cv2.imshow('aligned', aligned_depth_color_image)

        # Validate that both frames are valid
        if not aligned_depth_frame or not color_frame:
            continue

        depth_image = np.asanyarray(aligned_depth_frame.get_data())
        color_image = np.asanyarray(color_frame.get_data())

        s = pcv.rgb2gray_hsv(color_image, 's')  # plantcv
        s_thresh = pcv.threshold.binary(s, 85, 255, 'light')  # plantcv
        s_mblur = pcv.median_blur(s_thresh, 5)
        s_cnt = pcv.median_blur(s_thresh, 5)
        # cv2.imshow('color - depth3', s_mblur)
        # Convert RGB to LAB and extract the Blue channel
        b = pcv.rgb2gray_lab(color_image, 'b')

        # Threshold the blue image
        b_thresh = pcv.threshold.binary(b, 160, 255, 'light')
        b_cnt = pcv.threshold.binary(b, 160, 255, 'light')

        # Fill small objects
        # b_fill = pcv.fill(b_thresh, 10)
        mask = pcv.naive_bayes_classifier(color_image, "naive_bayes_pdfs.txt")
        #histogram_low = np.sum(mask["plant"][int(360/2):, :], axis=0)
        #histogram_up = np.sum(mask["plant"][:int(360/2), :], axis=0)
        histogram = np.sum(mask["plant"][int(360 / 2):, :], axis=0)
def test(true_positive_file, test_parameters):
    hue_lower_tresh = test_parameters[0]
    hue_higher_tresh = test_parameters[1]
    saturation_lower_tresh = test_parameters[2]
    saturation_higher_tresh = test_parameters[3]
    value_lower_tresh = test_parameters[4]
    value_higher_tresh = test_parameters[5]
    green_lower_tresh = test_parameters[6]
    green_higher_tresh = test_parameters[7]
    red_lower_tresh = test_parameters[8]
    red_higher_thresh = test_parameters[9]
    blue_lower_tresh = test_parameters[10]
    blue_higher_tresh = test_parameters[11]
    blur_k = test_parameters[12]
    fill_k = test_parameters[13]
    
    class args:
            #image = "C:\\Users\\RensD\\OneDrive\\studie\\Master\\The_big_project\\top_perspective\\0214_2018-03-07 08.55 - 26_cam9.png"
            image = true_positive_file
            outdir = "C:\\Users\\RensD\\OneDrive\\studie\\Master\\The_big_project\\top_perspective\\output"
            debug = debug_setting
            result = "results.txt"
    # 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'
    img, path, filename = pcv.readimage(filename=args.image, mode='rgb')
    
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='h')
    mask, masked_image = pcv.threshold.custom_range(rgb_img=s, lower_thresh=[hue_lower_tresh], upper_thresh=[hue_higher_tresh], channel='gray')
    masked = pcv.apply_mask(rgb_img=img, mask = mask, mask_color = 'white')
    #print("filtered on hue")
    s = pcv.rgb2gray_hsv(rgb_img=masked, channel='s')
    mask, masked_image = pcv.threshold.custom_range(rgb_img=s, lower_thresh=[saturation_lower_tresh], upper_thresh=[saturation_higher_tresh], channel='gray')
    masked = pcv.apply_mask(rgb_img=masked, mask = mask, mask_color = 'white')
    #print("filtered on saturation")
    s = pcv.rgb2gray_hsv(rgb_img=masked, channel='v')
    mask, masked_image = pcv.threshold.custom_range(rgb_img=s, lower_thresh=[value_lower_tresh], upper_thresh=[value_higher_tresh], channel='gray')
    masked = pcv.apply_mask(rgb_img=masked, mask = mask, mask_color = 'white')
    #print("filtered on value")
    mask, masked = pcv.threshold.custom_range(rgb_img=masked, lower_thresh=[0,green_lower_tresh,0], upper_thresh=[255,green_higher_tresh,255], channel='RGB')
    masked = pcv.apply_mask(rgb_img=masked, mask = mask, mask_color = 'white')
    #print("filtered on green")
    mask, masked = pcv.threshold.custom_range(rgb_img=masked, lower_thresh=[red_lower_tresh,0,0], upper_thresh=[red_higher_thresh,255,255], channel='RGB')
    masked = pcv.apply_mask(rgb_img=masked, mask = mask, mask_color = 'white')
    #print("filtered on red")
    mask_old, masked_old = pcv.threshold.custom_range(rgb_img=masked, lower_thresh=[0,0,blue_lower_tresh], upper_thresh=[255,255,blue_higher_tresh], channel='RGB')
    masked = pcv.apply_mask(rgb_img=masked_old, mask = mask_old, mask_color = 'white')
    #print("filtered on blue")
    ###____________________________________ Blur to minimize 
    try:
        s_mblur = pcv.median_blur(gray_img = masked_old, ksize = blur_k)
        s = pcv.rgb2gray_hsv(rgb_img=s_mblur, channel='v')
        mask, masked_image = pcv.threshold.custom_range(rgb_img=s, lower_thresh=[0], upper_thresh=[254], channel='gray')
    except:
        print("failed blur step")
    try:
        mask = pcv.fill(mask, fill_k)
    except:
        pass
    masked = pcv.apply_mask(rgb_img=masked, mask = mask, mask_color = 'white')


    ###_____________________________________ Now to identify objects
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')
    
     # Threshold the green-magenta and blue images
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a, threshold=115, 
                                      max_value=255, object_type='dark')
    maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a, threshold=135, 
                                           max_value=255, object_type='light')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b, threshold=128, 
                                          max_value=255, object_type='light')
    
    ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)
    
    # Fill small objects
    # Inputs: 
    #   bin_img - Binary image data 
    #   size - Minimum object area size in pixels (must be an integer), and smaller objects will be filled
    ab_fill = pcv.fill(bin_img=ab, size=200)
    #print("filled")
    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(rgb_img=masked, mask=ab_fill, mask_color='white')
    
    id_objects, obj_hierarchy = pcv.find_objects(masked, ab_fill)
    # Let's just take the largest
    roi1, roi_hierarchy= pcv.roi.rectangle(img=masked, x=0, y=0, h=960, w=1280)  # Currently hardcoded
    with HiddenPrints():
        roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img=img, roi_contour=roi1, 
                                                                       roi_hierarchy=roi_hierarchy, 
                                                                       object_contour=id_objects, 
                                                                       obj_hierarchy=obj_hierarchy,
                                                                       roi_type=roi_type)
    obj, mask = pcv.object_composition(img=img, contours=roi_objects, hierarchy=hierarchy3)
    
    if use_mask == True:
        return(mask)
    else:
        masked2 = pcv.apply_mask(rgb_img=masked, mask=mask, mask_color='white')
        return(masked2)
    def initcrop(imagePath):
        dire = os.getcwd()
        path = dire + '/Classifyer_dump'
        try:
            os.makedirs(path)
        except OSError:
            pass
        image = cv2.imread(imagePath)
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        cv2.imwrite(os.path.join(path, "gray.png"), gray)

        ret, thres = cv2.threshold(gray, 127, 255,
                                   cv2.THRESH_BINARY)  # 127 137

        cv2.imwrite(os.path.join(path, 'Wholepic.png'), thres)

        fill = pcv.fill(thres, 100000)
        cv2.imwrite(os.path.join(path, "noiseReduced.png"), fill)

        im2, contours, hierarchy = cv2.findContours(fill, cv2.RETR_EXTERNAL,
                                                    cv2.CHAIN_APPROX_SIMPLE)

        test = []
        for c in contours:
            peri = cv2.arcLength(c, True)
            test.append(peri)

        index_max = np.argmax(test)
        x, y, w, h = cv2.boundingRect(contours[index_max])
        c = max(contours, key=cv2.contourArea)
        x, y, w, h = cv2.boundingRect(c)

        # draw the biggest contour (c) in green
        # cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),5)

        image = image[y:y + h, x:x + w]

        cv2.imwrite(os.path.join(path, "cropped.png"), image)
        L, a, b = cv2.split(image)  # can do l a or b
        thres = cv2.adaptiveThreshold(b, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                      cv2.THRESH_BINARY, 255,
                                      -1)  # For liz's pictures 241
        cv2.imwrite(os.path.join(path, "cropped_thres.png"), thres)

        fill = pcv.fill(thres, 1000)
        cv2.imwrite(os.path.join(path, "cropped_thres_filled.png"), fill)

        blur = cv2.blur(fill, (15, 15), 0)

        fill_hole = cv2.morphologyEx(fill,
                                     cv2.MORPH_CLOSE,
                                     cv2.getStructuringElement(
                                         cv2.MORPH_RECT, (21, 21)),
                                     iterations=2)
        cv2.imwrite(os.path.join(path, "cropped_thres_filled.png"), fill_hole)

        nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(
            fill_hole, connectivity=8)
        new_centroids = []
        sizes = stats[1:, -1]
        nb_components = nb_components - 1
        min_size = 20000
        img2 = np.zeros((output.shape))
        for i in range(0, nb_components):
            if sizes[i] <= min_size:
                img2[output == i + 1] = 255
                new_centroids.append(centroids[i])
        cv2.imwrite(os.path.join(path, "filter.png"), img2)
        # print(len(centroids))
        # print(len(new_centroids))
        # print(new_centroids[0])
        # print(new_centroids[0][1])

        y = []
        x = []
        for i in range(len(new_centroids)):
            y.append(new_centroids[i][1])
            x.append(new_centroids[i][0])
        # print(len(x))

        XARRAY = sorted(x)
        YARRAY = sorted(y)
        smallX = int(XARRAY[4]) - 80
        bigX = int(XARRAY[len(XARRAY) - 4]) + 80
        smallY = int(YARRAY[4]) - 80
        bigY = int(YARRAY[len(YARRAY) - 4]) + 80

        # print(smallX, smallY, bigX, bigY)

        image = cv2.imread(os.path.join(path, "cropped.png"))
        image = image[smallY:bigY, smallX:bigX]
        #print(image.shape)
        cv2.imwrite(os.path.join(path, "final.png"), image)
        L, a, b = cv2.split(image)  # can do l a or b
        blur_image = pcv.median_blur(a, 10)
        Gaussian_blue = cv2.adaptiveThreshold(a, 255,
                                              cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                              cv2.THRESH_BINARY, 281,
                                              -1)  # For liz's pictures 241
        heavy_fill_blue = pcv.fill(Gaussian_blue, 1000)  # value 400
        hole_fill = pcv.fill_holes(heavy_fill_blue)
        cv2.imwrite(os.path.join(path, "Cropped_Threshold.png"), hole_fill)
        # cv2.imwrite(os.path.join(test1, "Cropped_thres%d.png" % image_counter),hole_fill)
        image = cv2.resize(image, (800, 600))
        cv2.imwrite(os.path.join(path, "scaled.png"), image)
        image = os.path.join(path, "scaled.png")
        msg = "Does this crop look good"
        choices = ["Yes", "No"]
        reply = easygui.indexbox(msg, image=image, choices=choices)
        if reply == 0:
            df = pd.DataFrame([smallY, bigY, smallX, bigX])
            df.to_pickle('pickled_setup')
Exemplo n.º 11
0
def process_image(image_path, threshold):
    # Read image
    img, _, _ = pcv.readimage(filename=image_path)

    # If image is not in Portrait rotate to ensure center of mass splits the plant correctly
    if img.shape[0] < img.shape[1]:
        img = np.array(Image.fromarray(img).transpose(Image.ROTATE_270))

    # Convert RGB to HSV and extract the saturation channel
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')

    # Threshold the saturation image
    s_thresh = pcv.threshold.binary(gray_img=s,
                                    threshold=85,
                                    max_value=255,
                                    object_type='light')

    # Median Blur
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)

    # Convert RGB to LAB and extract the Blue channel
    b = pcv.rgb2gray_lab(rgb_img=img, channel='b')

    # Threshold the blue image
    b_cnt = pcv.threshold.binary(gray_img=b,
                                 threshold=160,
                                 max_value=255,
                                 object_type='light')

    # Join the thresholded saturation and blue-yellow images
    bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_cnt)

    # Apply Mask (for VIS images, mask_color=white)
    masked = pcv.apply_mask(img=img, mask=bs, mask_color='white')

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')

    # Threshold the green-magenta and blue images
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a,
                                          threshold=115,
                                          max_value=255,
                                          object_type='dark')
    maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a,
                                           threshold=135,
                                           max_value=255,
                                           object_type='light')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b,
                                          threshold=128,
                                          max_value=255,
                                          object_type='light')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)

    # Fill small objects
    ab_fill = pcv.fill(bin_img=ab, size=200)

    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(img=masked, mask=ab_fill, mask_color='white')

    # Identify objects
    id_objects, obj_hierarchy = pcv.find_objects(img=masked2, mask=ab_fill)

    # Define ROI
    roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                            x=300,
                                            y=300,
                                            h=img.shape[0] - 600,
                                            w=img.shape[1] - 600)

    # Decide which objects to keep
    roi_objects, hierarchy3, _, _ = pcv.roi_objects(
        img=img,
        roi_contour=roi1,
        roi_hierarchy=roi_hierarchy,
        object_contour=id_objects,
        obj_hierarchy=obj_hierarchy,
        roi_type='partial')

    # Object combine kept objects
    obj, mask = pcv.object_composition(img=img,
                                       contours=roi_objects,
                                       hierarchy=hierarchy3)

    # ---------------- Analysis ----------------

    # Find shape properties, output shape image (optional)
    _ = pcv.analyze_object(img=img, obj=obj, mask=mask, label="default")

    x, y = pcv.outputs.observations['default']['center_of_mass']['value']
    width = pcv.outputs.observations['default']['width']['value']
    height = pcv.outputs.observations['default']['height']['value']

    x = int(x)
    y = int(y)

    top = max(int(y - (height / 2)), 0)
    bottom = min(int(y + (height / 2)), img.shape[0])

    left = max(int(x - (width / 2)), 0)
    right = min(int(x + (width / 2)), img.shape[1])

    left_half = mask[top:bottom, left:x]
    right_half = mask[top:bottom, x:right]

    left_half_count = cv2.countNonZero(left_half)
    right_half_count = cv2.countNonZero(right_half)

    left_percent = (left_half_count / (left_half_count + right_half_count))
    right_percent = 1 - left_percent
    print('Left Percentage: {:.2%} Right Percentage: {:.2%}'.format(
        left_percent, right_percent))

    if abs(left_percent - right_percent) > threshold:
        print('Rotate plant')
    else:
        print('Do NOT rotate plant')
def main():
    # Get options
    args = options()

    pcv.params.debug = args.debug  # set debug mode
    pcv.params.debug_outdir = args.outdir  # set output directory

    # Read metadata
    with open(args.metadata, 'r', encoding='utf-8') as f:
        md = json.load(f)

    camera_label = md['camera_label']

    # Read image
    img, path, filename = pcv.readimage(filename=args.image)

    # Convert RGB to HSV and extract the value channel
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='v')

    # Threshold the saturation image removing highs and lows and join
    s_thresh_1 = pcv.threshold.binary(gray_img=s,
                                      threshold=10,
                                      max_value=255,
                                      object_type='light')
    s_thresh_2 = pcv.threshold.binary(gray_img=s,
                                      threshold=245,
                                      max_value=255,
                                      object_type='dark')
    s_thresh = pcv.logical_and(bin_img1=s_thresh_1, bin_img2=s_thresh_2)

    # Median Blur
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)

    # Convert RGB to LAB and extract the Blue channel
    b = pcv.rgb2gray_lab(rgb_img=img, channel='b')

    # Threshold the blue image
    b_cnt = pcv.threshold.binary(gray_img=b,
                                 threshold=128,
                                 max_value=255,
                                 object_type='light')

    # Fill small objects
    b_fill = pcv.fill(b_cnt, 10)

    # Join the thresholded saturation and blue-yellow images
    bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_fill)

    # Apply Mask (for VIS images, mask_color=white)
    masked = pcv.apply_mask(rgb_img=img, mask=bs, mask_color='white')

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    # Threshold the green-magenta and blue images

    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a,
                                          threshold=127,
                                          max_value=255,
                                          object_type='dark')

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    # Threshold the green-magenta and blue images
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b,
                                          threshold=128,
                                          max_value=255,
                                          object_type='light')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)

    # Fill small objects
    ab_fill = pcv.fill(bin_img=ab, size=200)

    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(rgb_img=masked, mask=ab_fill, mask_color='white')

    # Identify objects
    id_objects, obj_hierarchy = pcv.find_objects(img=masked2, mask=ab_fill)

    # Define ROI

    W = 2472
    H = 3296

    if "far" in camera_label:
        # SIDE FAR
        w = 1600
        h = 1200
        pot = 230  #340
        roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                                x=(W - w) / 2,
                                                y=(H - h - pot),
                                                h=h,
                                                w=w)
    elif "lower" in camera_label:
        # SIDE LOWER
        w = 800
        h = 2400
        pot = 340
        roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                                x=1000 - w / 2,
                                                y=(H - h - pot),
                                                h=h,
                                                w=w)
    elif "upper" in camera_label:
        # SIDE UPPER
        w = 600
        h = 800
        pot = 550
        roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                                x=1400 - w / 2,
                                                y=(H - h - pot),
                                                h=h,
                                                w=w)
    elif "top" in camera_label:
        # TOP
        w = 450
        h = 450
        roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                                x=(H - h) / 2,
                                                y=(W - w) / 2,
                                                h=h,
                                                w=w)

    # Decide which objects to keep
    roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
        img=img,
        roi_contour=roi1,
        roi_hierarchy=roi_hierarchy,
        object_contour=id_objects,
        obj_hierarchy=obj_hierarchy,
        roi_type='partial')

    # Object combine kept objects
    obj, mask = pcv.object_composition(img=img,
                                       contours=roi_objects,
                                       hierarchy=hierarchy3)

    #TODO: Update for plantCV metadata import
    for key in md.keys():
        if str(md[key]).isdigit():
            pcv.outputs.add_observation(variable=key,
                                        trait=key,
                                        method='',
                                        scale='',
                                        datatype=int,
                                        value=md[key],
                                        label='')
        else:
            pcv.outputs.add_observation(variable=key,
                                        trait=key,
                                        method='',
                                        scale='',
                                        datatype=str,
                                        value=md[key],
                                        label='')

    if obj is not None:

        # Find shape properties, output shape image (optional)
        shape_imgs = pcv.analyze_object(img=img, obj=obj, mask=mask)

        # Shape properties relative to user boundary line (optional)
        #boundary_img1 = pcv.analyze_bound_horizontal(img=img, obj=obj, mask=mask, line_position=1680)

        # Determine color properties: Histograms, Color Slices, output color analyzed histogram (optional)
        color_histogram = pcv.analyze_color(rgb_img=img,
                                            mask=kept_mask,
                                            hist_plot_type='all')

        # Pseudocolor the grayscale image
        #pseudocolored_img = pcv.visualize.pseudocolor(gray_img=s, mask=kept_mask, cmap='jet')

        #print(pcv.outputs.images)
        if args.writeimg == True:
            for idx, item in enumerate(pcv.outputs.images[0]):
                pcv.print_image(item,
                                "{}_{}.png".format(args.result[:-5], idx))

    # Write shape and color data to results file
    pcv.print_results(filename=args.result)
            for frac in rm_fracs:
                if np.abs((frac[0] - 1) * 100) <= rm_perc:
                    if np.abs((frac[1] - 1) * 100) <= rm_perc:
                        if np.abs((frac[2] - 1) * 100) <= rm_perc:
                            rm_match = True
                            break

            if keep_match == False or rm_match == True:
                filtered[y, x] = (255, 255, 255)

pcv.plot_image(filtered)

# Threshold using the 'a' lab channel to pick out green leaves
channel_a = pcv.rgb2gray_lab(filtered, 'a')
thresh = pcv.threshold.binary(channel_a, 123, 255, 'dark')

# Clean up the noise from the mask by opening and blurring pixels together.
opened = pcv.opening(thresh)
mask2 = pcv.median_blur(opened, 3)

# Apply the new mask to the VIS image
masked = pcv.apply_mask(filtered, mask2, 'white')

#-------------------------------------------------------------------------------------------------------------------#
# It is very important to note that we want to avoid having extract the 'a' lab colour channel, as this is only
# effective if the plant is green. This step is included temporarily, as we search for an alternative that works
# universally, for plants of any colour. One suggestion is to find the average RGB values of the pixels in filtered,
# and remove pixels if their RGB values are not similar to this average. This should work, as by this point MOST of
# what is left should be the plant.
#-------------------------------------------------------------------------------------------------------------------#
Exemplo n.º 14
0
def main():
    # Get options
    args = options()

    pcv.params.debug = args.debug  # set debug mode
    pcv.params.debug_outdir = args.outdir  # set output directory

    # Read image
    img, path, filename = pcv.readimage(filename=args.image)

    # Convert RGB to HSV and extract the saturation channel
    h = pcv.rgb2gray_hsv(rgb_img=img, channel='h')

    # Threshold the saturation image
    h_thresh = pcv.threshold.binary(gray_img=h,
                                    threshold=85,
                                    max_value=255,
                                    object_type='dark')

    # Median Blur
    h_mblur = pcv.median_blur(gray_img=h_thresh, ksize=20)

    h_cnt = pcv.median_blur(gray_img=h_thresh, ksize=20)

    # Convert RGB to LAB and extract the Blue channel
    b = pcv.rgb2gray_lab(rgb_img=img, channel='b')

    # Threshold the blue image
    b_thresh = pcv.threshold.binary(gray_img=b,
                                    threshold=160,
                                    max_value=255,
                                    object_type='light')
    b_cnt = pcv.threshold.binary(gray_img=b,
                                 threshold=160,
                                 max_value=255,
                                 object_type='light')

    # Fill small objects
    # b_fill = pcv.fill(b_thresh, 10)

    # Join the thresholded saturation and blue-yellow images
    bs = pcv.logical_or(bin_img1=h_mblur, bin_img2=b_cnt)

    # Apply Mask (for VIS images, mask_color=white)
    masked = pcv.apply_mask(img=img, mask=bs, mask_color='white')

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')

    # Threshold the green-magenta and blue images
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a,
                                          threshold=115,
                                          max_value=255,
                                          object_type='dark')
    maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a,
                                           threshold=135,
                                           max_value=255,
                                           object_type='light')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b,
                                          threshold=128,
                                          max_value=255,
                                          object_type='light')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)

    # Fill small objects
    ab_fill = pcv.fill(bin_img=ab, size=200)

    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(img=masked, mask=ab_fill, mask_color='white')

    # Identify objects
    id_objects, obj_hierarchy = pcv.find_objects(img=masked2, mask=ab_fill)

    # Define ROI
    roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                            x=400,
                                            y=400,
                                            h=200,
                                            w=200)

    # Decide which objects to keep
    roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
        img=img,
        roi_contour=roi1,
        roi_hierarchy=roi_hierarchy,
        object_contour=id_objects,
        obj_hierarchy=obj_hierarchy,
        roi_type='partial')

    # Object combine kept objects
    obj, mask = pcv.object_composition(img=img,
                                       contours=roi_objects,
                                       hierarchy=hierarchy3)

    ############### Analysis ################

    outfile = False
    if args.writeimg == True:
        outfile = args.outdir + "/" + filename

    # Find shape properties, output shape image (optional)
    shape_imgs = pcv.analyze_object(img=img, obj=obj, mask=mask)

    # Shape properties relative to user boundary line (optional)
    boundary_img1 = pcv.analyze_bound_horizontal(img=img,
                                                 obj=obj,
                                                 mask=mask,
                                                 line_position=600)

    # Determine color properties: Histograms, Color Slices, output color analyzed histogram (optional)
    color_histogram = pcv.analyze_color(rgb_img=img,
                                        mask=kept_mask,
                                        hist_plot_type='all')

    # Pseudocolor the grayscale image
    pseudocolored_img = pcv.visualize.pseudocolor(gray_img=h,
                                                  mask=kept_mask,
                                                  cmap='jet')

    # Write shape and color data to results file
    pcv.print_results(filename=args.result)
Exemplo n.º 15
0
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)
mask_image_label, path, filename = pcv.readimage(
    '1_naive_bayes_labels_mask.jpg')
mask_image = mask_image_plant + mask_image_label
device, mask_image = pcv.rgb2gray_lab(mask_image, 'l', device)

#clean the mask up
device, img_binary = pcv.binary_threshold(mask_image, 50, 255, 'light', device)
pcv.print_image(img_binary, 'img_binary.tif')
device, blur_img = pcv.erode(
    img_binary, 3, 1, device, debug='print'
)  # Erode to remove soil and Dilate so that you don't lose leaves (just in case)

mask = np.copy(blur_img)
device, fill_image = pcv.fill(blur_img, mask, 100, device)
pcv.print_image(fill_image, 'fill_image.tif')
device, binary_image = pcv.median_blur(fill_image, 1, device)
pcv.print_image(binary_image, 'binary_image.tif')
device, masked_image = device, dilate_image = pcv.dilate(
    fill_image, 3, 3, device)

############################################
###########    Create Output   #############
############################################

#Print grid of images for QC
# from https://stackoverflow.com/questions/30227466/combine-several-images-horizontally-with-python

#Different steps created here
list_masked = [
    'mask_image.tif', 'img_binary.tif', 'blur_img.tif', 'fill_image.tif',
    'binary_image.tif', outfile
def plot_hotspots(directory, filename,convex_hull_flag):
 
    # Read image
    in_full_path  = os.path.join(directory, filename)     
    img, path, filename = pcv.readimage(in_full_path, mode="rgb")
    img_thermal = img.copy()    
      
    # Convert RGB to HSV and extract the saturation channel
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')
    # Threshold the saturation image
    s_thresh = pcv.threshold.binary(gray_img=s, threshold=85, max_value=255, object_type='light')

    # Median Blur
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)     
    edge = cv2.Canny(s_mblur, 60, 180) 
    
    outfile = 'Gray_' + filename 
    out_full_path = os.path.join(directory, outfile)
    cv2.imwrite(out_full_path, edge)      
    
   
    # Contours extraction       
    contours, hierarchy = cv2.findContours(edge.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
    #contours = sorted(contours, key=cv2.contourArea, reverse=True)
    
    hull_list = []
    if (convex_hull_flag == True):
        for i in range(len(contours)):
            hull = cv2.convexHull(contours[i])
            hull_list.append(hull)  
        contours = hull_list
    
    mask  = np.zeros(edge.shape, np.uint8)
    hiers = hierarchy[0]
    for i in range(len(contours)):  
            if hiers[i][3] != -1:
               continue
            cv2.drawContours(mask, contours, i,255, cv2.LINE_AA)   
            ## Find all inner contours and draw 
            ch = hiers[i][2]
            while ch != -1:
                cv2.drawContours(mask, contours, ch, (255,0,255), -1, cv2.LINE_AA)
                ch = hiers[ch][0]
           
    thermal = thermal_image(img_thermal, mask) 

    if (convex_hull_flag == True):
        outfile = 'Thermal_tree_CH_' + filename
    else:
        outfile = 'Thermal_tree_' + filename            
    out_full_path = os.path.join(directory, outfile)
    cv2.imwrite(out_full_path, thermal)  
            
    centroids = []    
    if (convex_hull_flag == True):
        area_threshold = 30
    else:
        area_threshold = 10    
 
    for i, cnt in enumerate(contours):  
           cv2.drawContours(mask, contours, i,255, cv2.FILLED)                      
           if (cv2.contourArea(cnt) > area_threshold ):
               moment = cv2.moments(contours[i]) 
               Cx = int(moment["m10"]/moment["m00"])
               Cy = int(moment["m01"]/moment["m00"])
               center = (Cx, Cy)
               centroids.append((contours, center, moment["m00"], 0))
               #cv2.circle(img, (Cx, Cy), 5, (255, 255, 255), -1)
               coordinate = '(' + str(Cx) + ',' + str(Cy) + ')'
               cv2.putText(img, coordinate, (Cx,Cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, RED, 1, cv2.LINE_AA)
               print(cv2.contourArea(cnt),Cx, Cy)     
    
    if Debug == True:
        fig, ax = plt.subplots(1, figsize=(12,8))    
        plt.imshow(mask, cmap='Greys') 
    
    if (convex_hull_flag == True):    
        outfile = 'Hotspots_CH_' + filename 
    else:
        outfile = 'Hotspots_' + filename 
    out_full_path = os.path.join(directory, outfile)
    cv2.imwrite(out_full_path, img) 
    return
Exemplo n.º 18
0
def main():
    # Get options
    args = options()

    pcv.params.debug = args.debug  # set debug mode
    pcv.params.debug_outdir = args.outdir  # set output directory

    # Read image
    img, path, filename = pcv.readimage(filename=args.image)

    # Convert RGB to HSV and extract the value channel
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='v')

    # Threshold the saturation image removing highs and lows and join
    s_thresh_1 = pcv.threshold.binary(gray_img=s,
                                      threshold=10,
                                      max_value=255,
                                      object_type='light')
    s_thresh_2 = pcv.threshold.binary(gray_img=s,
                                      threshold=245,
                                      max_value=255,
                                      object_type='dark')
    s_thresh = pcv.logical_and(bin_img1=s_thresh_1, bin_img2=s_thresh_2)

    # Median Blur
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)

    # Convert RGB to LAB and extract the Blue channel
    b = pcv.rgb2gray_lab(rgb_img=img, channel='b')

    # Threshold the blue image
    b_cnt = pcv.threshold.binary(gray_img=b,
                                 threshold=128,
                                 max_value=255,
                                 object_type='light')

    # Fill small objects
    b_fill = pcv.fill(b_cnt, 10)

    # Join the thresholded saturation and blue-yellow images
    bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_fill)

    # Apply Mask (for VIS images, mask_color=white)
    masked = pcv.apply_mask(rgb_img=img, mask=bs, mask_color='white')

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')

    # Threshold the green-magenta and blue images
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a,
                                          threshold=127,
                                          max_value=255,
                                          object_type='dark')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b,
                                          threshold=128,
                                          max_value=255,
                                          object_type='light')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)

    # Fill small objects
    ab_fill = pcv.fill(bin_img=ab, size=200)

    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(rgb_img=masked, mask=ab_fill, mask_color='white')

    # Identify objects
    id_objects, obj_hierarchy = pcv.find_objects(img=masked2, mask=ab_fill)

    # Define ROI
    w = 1600
    h = 1200
    pot = 230  #340
    roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                            x=(2472 - w) / 2,
                                            y=(3296 - h - pot),
                                            h=h,
                                            w=w)

    # Decide which objects to keep
    roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
        img=img,
        roi_contour=roi1,
        roi_hierarchy=roi_hierarchy,
        object_contour=id_objects,
        obj_hierarchy=obj_hierarchy,
        roi_type='partial')

    # Object combine kept objects
    obj, mask = pcv.object_composition(img=img,
                                       contours=roi_objects,
                                       hierarchy=hierarchy3)

    # Find shape properties, output shape image (optional)
    shape_imgs = pcv.analyze_object(img=img, obj=obj, mask=mask)

    if args.writeimg == True:
        pcv.print_image(img=shape_imgs,
                        filename="{}_shape.png".format(args.result[:-5]))
        pcv.print_image(img=masked2,
                        filename="{}_obj_on_img.png".format(args.result[:-5]))

    # Shape properties relative to user boundary line (optional)
    #boundary_img1 = pcv.analyze_bound_horizontal(img=img, obj=obj, mask=mask, line_position=1680)

    # Determine color properties: Histograms, Color Slices, output color analyzed histogram (optional)
    color_histogram = pcv.analyze_color(rgb_img=img,
                                        mask=kept_mask,
                                        hist_plot_type='all')

    # Pseudocolor the grayscale image
    pseudocolored_img = pcv.visualize.pseudocolor(gray_img=s,
                                                  mask=kept_mask,
                                                  cmap='jet')

    # Write shape and color data to results file
    pcv.print_results(filename=args.result)
Exemplo n.º 19
0
def plantCVProcess(img, x, y, w, h):

    # Convert RGB to HSV and extract the saturation channel
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')

    # Threshold the saturation image
    s_thresh = pcv.threshold.binary(gray_img=s, threshold=85, max_value=255, object_type='light')

    # Median Blur
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)
    s_cnt = pcv.median_blur(gray_img=s_thresh, ksize=5)

    # Convert RGB to LAB and extract the Blue channel
    b = pcv.rgb2gray_lab(rgb_img=img, channel='b')

    # Threshold the blue image
    b_thresh = pcv.threshold.binary(gray_img=b, threshold=160, max_value=255, object_type='light')
    b_cnt = pcv.threshold.binary(gray_img=b, threshold=160, max_value=255, object_type='light')

    # Fill small objects
    # b_fill = pcv.fill(b_thresh, 10)

    # Join the thresholded saturation and blue-yellow images
    bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_cnt)

    # Apply Mask (for VIS images, mask_color=white)
    masked = pcv.apply_mask(img=img, mask=bs, mask_color='white')

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')

    # Threshold the green-magenta and blue images
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a, threshold=115, max_value=255, object_type='dark')
    maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a, threshold=135, max_value=255, object_type='light')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b, threshold=128, max_value=255, object_type='light')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)

    # Fill small objects
    ab_fill = pcv.fill(bin_img=ab, size=200)

    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(img=masked, mask=ab_fill, mask_color='white')

    # Identify objects
    id_objects, obj_hierarchy = pcv.find_objects(img=masked2, mask=ab_fill)

    # Define ROI
    roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2, x=x, y=y, h=h, w=w)

    # Decide which objects to keep
    roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img=img, roi_contour=roi1,
                                                               roi_hierarchy=roi_hierarchy,
                                                               object_contour=id_objects,
                                                               obj_hierarchy=obj_hierarchy,
                                                               roi_type='partial')

    # Object combine kept objects
    obj, mask = pcv.object_composition(img=img, contours=roi_objects, hierarchy=hierarchy3)

    ############### Analysis ################

    # Find shape properties, output shape image (optional)
    shape_imgs = pcv.analyze_object(img=img, obj=obj, mask=mask)

    # Shape properties relative to user boundary line (optional)
    boundary_img1 = pcv.analyze_bound_horizontal(img=img, obj=obj, mask=mask, line_position=1680)

    # Determine color properties: Histograms, Color Slices, output color analyzed histogram (optional)
    color_histogram = pcv.analyze_color(rgb_img=img, mask=mask, hist_plot_type='all')

    # Pseudocolor the grayscale image
    pseudocolored_img = pcv.visualize.pseudocolor(gray_img=s, mask=mask, cmap='jet')

    return print_results()
Exemplo n.º 20
0
def shoot():
    				uploaded_file = st.file_uploader("Choose an image...", type="jpg")
    				if uploaded_file is not None:
    					inp = Image.open(uploaded_file)
    					inp.save('input.jpg')
    					img, path, filename = pcv.readimage(filename='input.jpg')
    					image = Image.open('input.jpg')
    					st.image(image, caption='Original Image',use_column_width=True)
                    # Convert RGB to HSV and extract the saturation channel
    # Inputs:
    #   rgb_image - RGB image data 
    #   channel - Split by 'h' (hue), 's' (saturation), or 'v' (value) channel
					
    					s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')
    					pcv.print_image(s, "plant/rgbtohsv.png")
    					image = Image.open('plant/rgbtohsv.png')
    					st.image(image, caption='RGB to HSV', use_column_width=True)
    					s_thresh = pcv.threshold.binary(gray_img=s, threshold=85, max_value=255, object_type='light')
    					pcv.print_image(s_thresh, "plant/binary_threshold.png")
    					image = Image.open('plant/binary_threshold.png')
    					st.image(image, caption='Binary Threshold',use_column_width=True)
                   
    # Median Blur to clean noise 

    # Inputs: 
    #   gray_img - Grayscale image data 
    #   ksize - Kernel size (integer or tuple), (ksize, ksize) box if integer input,
    #           (n, m) box if tuple input 

    					s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)
    					pcv.print_image(s_mblur, "plant/Median_blur.png")
    					image = Image.open('plant/Median_blur.png')
    					st.image(image, caption='Median Blur',use_column_width=True)
                    
     # An alternative to using median_blur is gaussian_blur, which applies 
    # a gaussian blur filter to the image. Depending on the image, one 
    # technique may be more effective than others. 

    # Inputs:
    #   img - RGB or grayscale image data
    #   ksize - Tuple of kernel size
    #   sigma_x - Standard deviation in X direction; if 0 (default), 
    #            calculated from kernel size
    #   sigma_y - Standard deviation in Y direction; if sigmaY is 
    #            None (default), sigmaY is taken to equal sigmaX
                
    					gaussian_img = pcv.gaussian_blur(img=s_thresh, ksize=(5, 5), sigma_x=0, sigma_y=None)
    # Convert RGB to LAB and extract the blue channel ('b')

    # Input:
    #   rgb_img - RGB image data 
    #   channel- Split by 'l' (lightness), 'a' (green-magenta), or 'b' (blue-yellow) channel
    					b = pcv.rgb2gray_lab(rgb_img=img, channel='b')
    					b_thresh = pcv.threshold.binary(gray_img=b, threshold=160, max_value=255, 
                                object_type='light')
                     # Join the threshold saturation and blue-yellow images with a logical or operation 

    # Inputs: 
    #   bin_img1 - Binary image data to be compared to bin_img2
    #   bin_img2 - Binary image data to be compared to bin_img1

    
    					bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_thresh)
    					pcv.print_image(bs, "plant/threshold comparison.png")
    					image = Image.open('plant/threshold comparison.png')
    					st.image(image, caption='Threshold Comparision',use_column_width=True)
                    
 # Appy Mask (for VIS images, mask_color='white')

    # Inputs:
    #   img - RGB or grayscale image data 
    #   mask - Binary mask image data 
    #   mask_color - 'white' or 'black' 
    
    					masked = pcv.apply_mask(img=img, mask=bs, mask_color='white')
    					pcv.print_image(masked, "plant/Apply_mask.png")
    					image = Image.open('plant/Apply_mask.png')
    					st.image(image, caption='Applied Mask',use_column_width=True)
                   # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    					masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    					masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')
                     # Threshold the green-magenta and blue images
    					maskeda_thresh = pcv.threshold.binary(gray_img=masked_a, threshold=115, max_value=255, object_type='dark')
    					maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a, threshold=135,max_value=255, object_type='light')
    					maskedb_thresh = pcv.threshold.binary(gray_img=masked_b, threshold=128, max_value=255, object_type='light')
    					pcv.print_image( maskeda_thresh, "plant/maskeda_thresh.png")
    					pcv.print_image(maskeda_thresh1, "plant/maskeda_thresh1.png")
    					pcv.print_image(maskedb_thresh, "plant/maskedb_thresh1.png")
  
    					image = Image.open('plant/maskeda_thresh.png')
    					st.image(image, caption='Threshold green-magneta and blue image',use_column_width=True)


   # Join the thresholded saturation and blue-yellow images (OR)
    					ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    					ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)
Exemplo n.º 21
0
    def initcrop(imagePath):
        dire = dir
        path = dire + '/Classifyer_dump'
        try:
            os.makedirs(path)
        except OSError:
            pass
        image = cv2.imread(imagePath)
        blue_image = pcv.rgb2gray_lab(image, 'l')
        Gaussian_blue = cv2.adaptiveThreshold(blue_image, 255,
                                              cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                              cv2.THRESH_BINARY, 981,
                                              -1)  # 241 is good 981
        cv2.imwrite(os.path.join(path, "blue_test.png"), Gaussian_blue)
        fill = pcv.fill_holes(Gaussian_blue)
        fill_again = pcv.fill(fill, 100000)

        id_objects, obj_hierarchy = pcv.find_objects(
            img=image,
            mask=fill_again)  # lazy way to findContours and draw them

        roi1, roi_hierarchy = pcv.roi.rectangle(img=image,
                                                x=3000,
                                                y=1000,
                                                h=200,
                                                w=300)

        roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
            img=image,
            roi_contour=roi1,
            roi_hierarchy=roi_hierarchy,
            object_contour=id_objects,
            obj_hierarchy=obj_hierarchy,
            roi_type='partial')
        cv2.imwrite(os.path.join(path, "plate_mask.png"), kept_mask)

        mask = cv2.imread(os.path.join(path, "plate_mask.png"))
        result = image * (mask.astype(image.dtype))
        result = cv2.bitwise_not(result)
        cv2.imwrite(os.path.join(path, "AutoCrop.png"), result)

        output = cv2.connectedComponentsWithStats(kept_mask, connectivity=8)
        stats = output[2]
        left = (stats[1, cv2.CC_STAT_LEFT])
        # print(stats[1, cv2.CC_STAT_TOP])
        # print(stats[1, cv2.CC_STAT_HEIGHT])
        # exit(2)

        L, a, b = cv2.split(result)
        # cv2.imwrite("gray_scale.png", L)
        plate_threshold = cv2.adaptiveThreshold(b, 255,
                                                cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                                cv2.THRESH_BINARY, 87,
                                                -1)  # 867 is good 241
        cv2.imwrite(os.path.join(path, "plate_threshold.png"), plate_threshold)

        fill_again2 = pcv.fill(plate_threshold, 1000)

        cv2.imwrite(os.path.join(path, "fill_test.png"), fill_again2)
        # fill = pcv.fill_holes(fill_again2)
        # cv2.imwrite(os.path.join(path, "fill_test2.png"), fill)
        blur_image = pcv.median_blur(fill_again2, 10)
        nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(
            blur_image, connectivity=8)
        sizes = stats[1:, -1]
        nb_components = nb_components - 1
        min_size = 20000
        img2 = np.zeros((output.shape))
        for i in range(0, nb_components):
            if sizes[i] <= min_size:
                img2[output == i + 1] = 255
        cv2.imwrite(os.path.join(path, "remove_20000.png"),
                    img2)  # this can be made better to speed it up
        thresh_image = img2.astype(
            np.uint8)  # maybe crop to the roi below then do it
        thresh_image = pcv.fill_holes(thresh_image)
        cv2.imwrite("NEWTEST.jpg", thresh_image)
        id_objects, obj_hierarchy = pcv.find_objects(img=image,
                                                     mask=thresh_image)

        roi1, roi_hierarchy = pcv.roi.rectangle(img=image,
                                                x=(left + 380),
                                                y=750,
                                                h=175,
                                                w=100)
        try:
            where_cell = 0
            roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
                img=image,
                roi_contour=roi1,
                roi_hierarchy=roi_hierarchy,
                object_contour=id_objects,
                obj_hierarchy=obj_hierarchy,
                roi_type='partial')

            cv2.imwrite(os.path.join(path, "test_mask.png"), kept_mask)
            mask = cv2.imread(os.path.join(path, "test_mask.png"))
            result = image * (mask.astype(image.dtype))
            result = cv2.bitwise_not(result)
            cv2.imwrite(os.path.join(path, "TEST.png"), result)

            output = cv2.connectedComponentsWithStats(kept_mask,
                                                      connectivity=8)
            stats = output[2]
            centroids = output[3]
            centroids_x = (int(centroids[1][0]))
            centroids_y = (int(centroids[1][1]))
        except:
            where_cell = 1
            print("did this work?")
            roi1, roi_hierarchy = pcv.roi.rectangle(img=image,
                                                    x=(left + 380),
                                                    y=3200,
                                                    h=100,
                                                    w=100)
            roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
                img=image,
                roi_contour=roi1,
                roi_hierarchy=roi_hierarchy,
                object_contour=id_objects,
                obj_hierarchy=obj_hierarchy,
                roi_type='partial')
            cv2.imwrite(os.path.join(path, "test_mask.png"), kept_mask)
            mask = cv2.imread(os.path.join(path, "test_mask.png"))
            result = image * (mask.astype(image.dtype))
            result = cv2.bitwise_not(result)
            cv2.imwrite(os.path.join(path, "TEST.png"), result)

            output = cv2.connectedComponentsWithStats(kept_mask,
                                                      connectivity=8)
            stats = output[2]
            centroids = output[3]
            centroids_x = (int(centroids[1][0]))
            centroids_y = (int(centroids[1][1]))
        flag = 0

        # print(stats[1, cv2.CC_STAT_AREA])
        if ((stats[1, cv2.CC_STAT_AREA]) > 4000):
            flag = 30
        # print(centroids_x)
        # print(centroids_y)

        # print(centroids)
        if (where_cell == 0):
            left = (centroids_x - 70)
            right = (centroids_x + 3695 + flag)  # was 3715
            top = (centroids_y - 80)
            bottom = (centroids_y + 2462)
        if (where_cell == 1):
            left = (centroids_x - 70)
            right = (centroids_x + 3715 + flag)
            top = (centroids_y - 2480)
            bottom = (centroids_y + 62)

        # print(top)
        # print(bottom)
        image = Image.open(imagePath)
        img_crop = image.crop((left, top, right, bottom))
        # img_crop.show()
        img_crop.save(os.path.join(path, 'Cropped_full_yeast.png'))
        circle_me = cv2.imread(os.path.join(path, "Cropped_full_yeast.png"))
        cropped_img = cv2.imread(
            os.path.join(path, "Cropped_full_yeast.png"
                         ))  # changed from Yeast_Cluster.%d.png  %counter
        L, a, b = cv2.split(cropped_img)  # can do l a or b
        Gaussian_blue = cv2.adaptiveThreshold(b, 255,
                                              cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                              cv2.THRESH_BINARY, 241,
                                              -1)  # For liz's pictures 241
        cv2.imwrite(os.path.join(path, "blue_test.png"), Gaussian_blue)
        blur_image = pcv.median_blur(Gaussian_blue, 10)
        heavy_fill_blue = pcv.fill(blur_image, 1000)  # value 400
        hole_fill = pcv.fill_holes(heavy_fill_blue)
        cv2.imwrite(os.path.join(path, "Cropped_Threshold.png"), hole_fill)
Exemplo n.º 22
0
def root():
    				uploaded_file = st.file_uploader("Choose an image...", type="jpg")
    				if uploaded_file is not None:
    					inp = Image.open(uploaded_file)
    					inp.save('input.jpg')
    					img, path, filename = pcv.readimage(filename='input.jpg')
    					image = Image.open('input.jpg')
    					st.image(image, caption='Original Image',use_column_width=True)
                    # Convert RGB to HSV and extract the saturation channel
    # Inputs:
    #   rgb_image - RGB image data 
    #   channel - Split by 'h' (hue), 's' (saturation), or 'v' (value) channel
					
    					s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')
    					pcv.print_image(s, "plant/rgbtohsv.png")
    					image = Image.open('plant/rgbtohsv.png')
    					st.image(image, caption='RGB to HSV', use_column_width=True)
    					s_thresh = pcv.threshold.binary(gray_img=s, threshold=85, max_value=255, object_type='light')
    					pcv.print_image(s_thresh, "plant/binary_threshold.png")
    					image = Image.open('plant/binary_threshold.png')
    					st.image(image, caption='Binary Threshold',use_column_width=True)
                   
    # Median Blur to clean noise 

    # Inputs: 
    #   gray_img - Grayscale image data 
    #   ksize - Kernel size (integer or tuple), (ksize, ksize) box if integer input,
    #           (n, m) box if tuple input 

    					s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)
    					pcv.print_image(s_mblur, "plant/Median_blur.png")
    					image = Image.open('plant/Median_blur.png')
    					st.image(image, caption='Median Blur',use_column_width=True)
                    
     # An alternative to using median_blur is gaussian_blur, which applies 
    # a gaussian blur filter to the image. Depending on the image, one 
    # technique may be more effective than others. 

    # Inputs:
    #   img - RGB or grayscale image data
    #   ksize - Tuple of kernel size
    #   sigma_x - Standard deviation in X direction; if 0 (default), 
    #            calculated from kernel size
    #   sigma_y - Standard deviation in Y direction; if sigmaY is 
    #            None (default), sigmaY is taken to equal sigmaX
                
    					gaussian_img = pcv.gaussian_blur(img=s_thresh, ksize=(5, 5), sigma_x=0, sigma_y=None)
    # Convert RGB to LAB and extract the blue channel ('b')

    # Input:
    #   rgb_img - RGB image data 
    #   channel- Split by 'l' (lightness), 'a' (green-magenta), or 'b' (blue-yellow) channel
    					b = pcv.rgb2gray_lab(rgb_img=img, channel='b')
    					b_thresh = pcv.threshold.binary(gray_img=b, threshold=160, max_value=255, 
                                object_type='light')
                     # Join the threshold saturation and blue-yellow images with a logical or operation 

    # Inputs: 
    #   bin_img1 - Binary image data to be compared to bin_img2
    #   bin_img2 - Binary image data to be compared to bin_img1

    
    					bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_thresh)
    					pcv.print_image(bs, "plant/threshold comparison.png")
    					image = Image.open('plant/threshold comparison.png')
    					st.image(image, caption='Threshold Comparision',use_column_width=True)
                    
 # Appy Mask (for VIS images, mask_color='white')

    # Inputs:
    #   img - RGB or grayscale image data 
    #   mask - Binary mask image data 
    #   mask_color - 'white' or 'black' 
    
    					masked = pcv.apply_mask(img=img, mask=bs, mask_color='white')
    					pcv.print_image(masked, "plant/Apply_mask.png")
    					image = Image.open('plant/Apply_mask.png')
    					st.image(image, caption='Applied Mask',use_column_width=True)
                   # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    					masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    					masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')
                     # Threshold the green-magenta and blue images
    					maskeda_thresh = pcv.threshold.binary(gray_img=masked_a, threshold=115, max_value=255, object_type='dark')
    					maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a, threshold=135,max_value=255, object_type='light')
    					maskedb_thresh = pcv.threshold.binary(gray_img=masked_b, threshold=128, max_value=255, object_type='light')
    					pcv.print_image( maskeda_thresh, "plant/maskeda_thresh.png")
    					pcv.print_image(maskeda_thresh1, "plant/maskeda_thresh1.png")
    					pcv.print_image(maskedb_thresh, "plant/maskedb_thresh1.png")
  
    					image = Image.open('plant/maskeda_thresh.png')
    					st.image(image, caption='Threshold green-magneta and blue image',use_column_width=True)


   # Join the thresholded saturation and blue-yellow images (OR)
    					ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    					ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)
        # Opening filters out bright noise from an image.

# Inputs:
#   gray_img - Grayscale or binary image data
#   kernel - Optional neighborhood, expressed as an array of 1's and 0's. If None (default),
#   uses cross-shaped structuring element.
    					opened_ab = pcv.opening(gray_img=ab)

# Depending on the situation it might be useful to use the 
# exclusive or (pcv.logical_xor) function. 

# Inputs: 
#   bin_img1 - Binary image data to be compared to bin_img2
#   bin_img2 - Binary image data to be compared to bin_img1
    					xor_img = pcv.logical_xor(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
# Fill small objects (reduce image noise) 

# Inputs: 
#   bin_img - Binary image data 
#   size - Minimum object area size in pixels (must be an integer), and smaller objects will be filled
    					ab_fill = pcv.fill(bin_img=ab, size=200)
# Closing filters out dark noise from an image.

# Inputs:
#   gray_img - Grayscale or binary image data
#   kernel - Optional neighborhood, expressed as an array of 1's and 0's. If None (default),
#   uses cross-shaped structuring element.
    					closed_ab = pcv.closing(gray_img=ab_fill)
# Apply mask (for VIS images, mask_color=white)
    					masked2 = pcv.apply_mask(img=masked, mask=ab_fill, mask_color='white')
# 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=masked2, mask=ab_fill)
# Define the region of interest (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=masked2, x=50, y=50, h=100, w=100)
# 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 the ROI), 'cutto', or 
#                     'largest' (keep only largest contour)
    					roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(img=img, roi_contour=roi1, 
                                                               roi_hierarchy=roi_hierarchy, 
                                                               object_contour=id_objects, 
                                                               obj_hierarchy=obj_hierarchy,
                                                               roi_type='partial')
# Object combine kept objects
# Inputs:
#   img - RGB or grayscale image data for plotting 
#   contours - Contour list 
#   hierarchy - Contour hierarchy array 
    					obj, mask = pcv.object_composition(img=img, contours=roi_objects, hierarchy=hierarchy3)
############### Analysis ################ 
# Find shape properties, data gets stored to an Outputs class automatically
# Inputs:
#   img - RGB or grayscale image data 
#   obj- Single or grouped contour object
#   mask - Binary image mask to use as mask for moments analysis 
    					analysis_image = pcv.analyze_object(img=img, obj=obj, mask=mask)
    					pcv.print_image(analysis_image, "plant/analysis_image.png")
    					image = Image.open('plant/analysis_image.png')
    					st.image(image, caption='Analysis_image',use_column_width=True)
# Shape properties relative to user boundary line (optional)
# Inputs:
#   img - RGB or grayscale image data 
#   obj - Single or grouped contour object 
#   mask - Binary mask of selected contours 
#   line_position - Position of boundary line (a value of 0 would draw a line 
#                   through the bottom of the image) 
    					boundary_image2 = pcv.analyze_bound_horizontal(img=img, obj=obj, mask=mask, 
                                               line_position=370)
    					pcv.print_image(boundary_image2, "plant/boundary_image2.png")
    					image = Image.open('plant/boundary_image2.png')
    					st.image(image, caption='Boundary Image',use_column_width=True)
# Determine color properties: Histograms, Color Slices and Pseudocolored Images, output color analyzed images (optional)
# Inputs:
#   rgb_img - RGB image data
#   mask - Binary mask of selected contours 
#   hist_plot_type - None (default), 'all', 'rgb', 'lab', or 'hsv'
#                    This is the data to be printed to the SVG histogram file  
    					color_histogram = pcv.analyze_color(rgb_img=img, mask=kept_mask, hist_plot_type='all')
# Print the histogram out to save it 
    					pcv.print_image(img=color_histogram, filename="plant/vis_tutorial_color_hist.jpg")
    					image = Image.open('plant/vis_tutorial_color_hist.jpg')
    					st.image(image, caption='Color Histogram',use_column_width=True)
# Divide plant object into twenty equidistant bins and assign pseudolandmark points based upon their 
# actual (not scaled) position. Once this data is scaled this approach may provide some information 
# regarding shape independent of size.
# Inputs:
#   img - RGB or grayscale image data 
#   obj - Single or grouped contour object 
#   mask - Binary mask of selected contours 
    					top_x, bottom_x, center_v_x = pcv.x_axis_pseudolandmarks(img=img, obj=obj, mask=mask)
    					top_y, bottom_y, center_v_y = pcv.y_axis_pseudolandmarks(img=img, obj=obj, mask=mask)
# The print_results function will take the measurements stored when running any (or all) of these functions, format, 
# and print an output text file for data analysis. The Outputs class stores data whenever any of the following functions
# are ran: analyze_bound_horizontal, analyze_bound_vertical, analyze_color, analyze_nir_intensity, analyze_object, 
# fluor_fvfm, report_size_marker_area, watershed. If no functions have been run, it will print an empty text file 
    					pcv.print_results(filename='vis_tutorial_results.txt')
Exemplo n.º 23
0
def main():
    # Get options
    args = options()

    pcv.params.debug = args.debug  # set debug mode
    pcv.params.debug_outdir = args.outdir  # set output directory

    # Read image
    img, path, filename = pcv.readimage(filename=args.image)

    # Convert RGB to HSV and extract the saturation channel
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')

    # Threshold the saturation image
    s_thresh = pcv.threshold.binary(gray_img=s,
                                    threshold=85,
                                    max_value=255,
                                    object_type='light')

    # Median Blur
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)
    s_cnt = pcv.median_blur(gray_img=s_thresh, ksize=5)

    # Convert RGB to LAB and extract the Blue channel
    b = pcv.rgb2gray_lab(rgb_img=img, channel='b')

    # Threshold the blue image
    b_thresh = pcv.threshold.binary(gray_img=b,
                                    threshold=160,
                                    max_value=255,
                                    object_type='light')
    b_cnt = pcv.threshold.binary(gray_img=b,
                                 threshold=160,
                                 max_value=255,
                                 object_type='light')

    # Fill small objects
    # b_fill = pcv.fill(b_thresh, 10)

    # Join the thresholded saturation and blue-yellow images
    bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_cnt)

    # Apply Mask (for VIS images, mask_color=white)
    masked = pcv.apply_mask(img=img, mask=bs, mask_color='white')

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')
    cv2.imwrite("masked.jpeg", masked)

    # Threshold the green-magenta and blue images
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a,
                                          threshold=115,
                                          max_value=255,
                                          object_type='dark')
    maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a,
                                           threshold=135,
                                           max_value=255,
                                           object_type='light')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b,
                                          threshold=128,
                                          max_value=255,
                                          object_type='light')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)

    # Fill small objects
    ab_fill = pcv.fill(bin_img=ab, size=200)

    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(img=masked, mask=ab_fill, mask_color='white')
    cv2.imwrite("masked2.jpeg", masked2)
Exemplo n.º 24
0
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():

    # Set variables
    args = options()
    pcv.params.debug = args.debug

    # Read and rotate image
    img, path, filename = pcv.readimage(filename=args.image)
    img = pcv.rotate(img, -90, False)

    # Create mask from LAB b channel
    l = pcv.rgb2gray_lab(rgb_img=img, channel='b')
    l_thresh = pcv.threshold.binary(gray_img=l,
                                    threshold=115,
                                    max_value=255,
                                    object_type='dark')
    l_mblur = pcv.median_blur(gray_img=l_thresh, ksize=5)

    # Apply mask to image
    masked = pcv.apply_mask(img=img, mask=l_mblur, mask_color='white')
    ab_fill = pcv.fill(bin_img=l_mblur, size=50)

    # Extract plant object from image
    id_objects, obj_hierarchy = pcv.find_objects(img=img, mask=ab_fill)
    roi1, roi_hierarchy = pcv.roi.rectangle(img=masked,
                                            x=150,
                                            y=270,
                                            h=100,
                                            w=100)
    roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
        img=img,
        roi_contour=roi1,
        roi_hierarchy=roi_hierarchy,
        object_contour=id_objects,
        obj_hierarchy=obj_hierarchy,
        roi_type='partial')
    obj, mask = pcv.object_composition(img=img,
                                       contours=roi_objects,
                                       hierarchy=hierarchy3)

    ############### Analysis ################

    # Analyze shape properties
    analysis_image = pcv.analyze_object(img=img, obj=obj, mask=mask)
    boundary_image2 = pcv.analyze_bound_horizontal(img=img,
                                                   obj=obj,
                                                   mask=mask,
                                                   line_position=370)

    # Analyze colour properties
    color_histogram = pcv.analyze_color(rgb_img=img,
                                        mask=kept_mask,
                                        hist_plot_type='all')

    # Analyze shape independent of size
    top_x, bottom_x, center_v_x = pcv.x_axis_pseudolandmarks(img=img,
                                                             obj=obj,
                                                             mask=mask)
    top_y, bottom_y, center_v_y = pcv.y_axis_pseudolandmarks(img=img,
                                                             obj=obj,
                                                             mask=mask)

    # Print results
    pcv.print_results(filename='{}'.format(args.result))
    pcv.print_image(img=color_histogram,
                    filename='{}_color_hist.jpg'.format(args.outdir))
    pcv.print_image(img=kept_mask, filename='{}_mask.jpg'.format(args.outdir))
Exemplo n.º 26
0
def main():

    # 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'
    img, path, filename = pcv.readimage(filename=args.image, mode='rgb')

    ### SELECTING THE PLANT

    ### Attempt 5 combineren
    # Parameters
    hue_lower_tresh = 22  # 24
    hue_higher_tresh = 50  # 50
    saturation_lower_tresh = 138  # 140
    saturation_higher_tresh = 230  # 230
    value_lower_tresh = 120  # 125
    value_higher_tresh = 255  # 255
    # RGB color space
    green_lower_tresh = 105  # 110
    green_higher_tresh = 255  # 255
    red_lower_tresh = 22  # 24
    red_higher_thresh = 98  # 98
    blue_lower_tresh = 85  # 85
    blue_higher_tresh = 253  # 255
    # CIELAB color space
    #lab_blue_lower_tresh = 0            # Blue yellow channel
    #lab_blue_higher_tresh = 255

    s = pcv.rgb2gray_hsv(rgb_img=img, channel='h')
    mask, masked_image = pcv.threshold.custom_range(
        rgb_img=s,
        lower_thresh=[hue_lower_tresh],
        upper_thresh=[hue_higher_tresh],
        channel='gray')
    masked = pcv.apply_mask(rgb_img=img, mask=mask, mask_color='white')
    # Filtered on Hue
    s = pcv.rgb2gray_hsv(rgb_img=masked, channel='s')
    mask, masked_image = pcv.threshold.custom_range(
        rgb_img=s,
        lower_thresh=[saturation_lower_tresh],
        upper_thresh=[saturation_higher_tresh],
        channel='gray')
    masked = pcv.apply_mask(rgb_img=masked, mask=mask, mask_color='white')
    #filtered on saturation
    s = pcv.rgb2gray_hsv(rgb_img=masked, channel='v')
    mask, masked_image = pcv.threshold.custom_range(
        rgb_img=s,
        lower_thresh=[value_lower_tresh],
        upper_thresh=[value_higher_tresh],
        channel='gray')
    masked = pcv.apply_mask(rgb_img=masked, mask=mask, mask_color='white')
    #filtered on value
    mask, masked = pcv.threshold.custom_range(
        rgb_img=masked,
        lower_thresh=[0, green_lower_tresh, 0],
        upper_thresh=[255, green_higher_tresh, 255],
        channel='RGB')
    masked = pcv.apply_mask(rgb_img=masked, mask=mask, mask_color='white')
    #filtered on green
    mask, masked = pcv.threshold.custom_range(
        rgb_img=masked,
        lower_thresh=[red_lower_tresh, 0, 0],
        upper_thresh=[red_higher_thresh, 255, 255],
        channel='RGB')
    masked = pcv.apply_mask(rgb_img=masked, mask=mask, mask_color='white')
    #filtered on red
    mask_old, masked_old = pcv.threshold.custom_range(
        rgb_img=masked,
        lower_thresh=[0, 0, blue_lower_tresh],
        upper_thresh=[255, 255, blue_higher_tresh],
        channel='RGB')
    masked = pcv.apply_mask(rgb_img=masked_old,
                            mask=mask_old,
                            mask_color='white')
    #filtered on blue
    #b = pcv.rgb2gray_lab(rgb_img = masked, channel = 'b')   # Converting toe CIElab blue_yellow image
    #b_thresh =pcv.threshold.binary(gray_img = b, threshold=lab_blue_lower_tresh, max_value = lab_blue_higher_tresh)

    ###_____________________________________ Now to identify objects
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')

    # Threshold the green-magenta and blue images
    maskeda_thresh = pcv.threshold.binary(
        gray_img=masked_a,
        threshold=125,  # original 115
        max_value=255,
        object_type='dark')
    maskeda_thresh1 = pcv.threshold.binary(
        gray_img=masked_a,
        threshold=140,  # original 135
        max_value=255,
        object_type='light')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b,
                                          threshold=128,
                                          max_value=255,
                                          object_type='light')

    ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)

    # Fill small objects
    # Inputs:
    #   bin_img - Binary image data
    #   size - Minimum object area size in pixels (must be an integer), and smaller objects will be filled
    ab = pcv.median_blur(gray_img=ab, ksize=3)
    ab_fill = pcv.fill(bin_img=ab, size=1000)
    #print("filled")
    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(rgb_img=masked, mask=ab_fill, mask_color='white')
    # ID the objects
    id_objects, obj_hierarchy = pcv.find_objects(masked2, ab_fill)
    # Let's just take the largest
    roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                            x=0,
                                            y=0,
                                            h=960,
                                            w=1280)  # Currently hardcoded

    # 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, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
            img=img,
            roi_contour=roi1,
            roi_hierarchy=roi_hierarchy,
            object_contour=id_objects,
            obj_hierarchy=obj_hierarchy,
            roi_type='partial')
    # Object combine kept objects
    # Inputs:
    #   img - RGB or grayscale image data for plotting
    #   contours - Contour list
    #   hierarchy - Contour hierarchy array
    obj, mask = pcv.object_composition(img=img,
                                       contours=roi_objects,
                                       hierarchy=hierarchy3)
    #print("final plant")
    new_im = Image.fromarray(masked2)
    new_im.save("output//" + args.filename + "last_masked.png")

    ##################_________________ Analysis

    outfile = args.outdir + "/" + filename
    # Here come all the analyse functions.
    # pcv.acute_vertex(img, obj, 30, 15, 100)

    color_img = pcv.analyze_color(rgb_img=img,
                                  mask=kept_mask,
                                  hist_plot_type=None)
    #new_im = Image.fromarray(color_img)
    #new_im.save(args.filename + "color_img.png")

    # Find shape properties, output shape image (optional)

    # 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=obj, mask=mask)
    new_im = Image.fromarray(shape_img)
    new_im.save("output//" + args.filename + "shape_img.png")
    # Shape properties relative to user boundary line (optional)

    # Inputs:
    #   img - RGB or grayscale image data
    #   obj - Single or grouped contour object
    #   mask - Binary mask of selected contours
    #   line_position - Position of boundary line (a value of 0 would draw a line
    #                   through the bottom of the image)
    boundary_img1 = pcv.analyze_bound_horizontal(img=img,
                                                 obj=obj,
                                                 mask=mask,
                                                 line_position=1680)
    new_im = Image.fromarray(boundary_img1)
    new_im.save("output//" + args.filename + "boundary_img.png")
    # Determine color properties: Histograms, Color Slices, output color analyzed histogram (optional)

    # Inputs:
    #   rgb_img - RGB image data
    #   mask - Binary mask of selected contours
    #   hist_plot_type - None (default), 'all', 'rgb', 'lab', or 'hsv'
    #                    This is the data to be printed to the SVG histogram file
    color_histogram = pcv.analyze_color(rgb_img=img,
                                        mask=kept_mask,
                                        hist_plot_type='all')
    #new_im = Image.fromarray(color_histogram)
    #new_im.save(args.filename + "color_histogram_img.png")

    # Pseudocolor the grayscale image

    # 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, default), "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=s,
                                                  mask=kept_mask,
                                                  cmap='jet')
    #new_im = Image.fromarray(pseudocolored_img)
    #new_im.save(args.filename + "pseudocolored.png")

    # Write shape and color data to results file
    pcv.print_results(filename=args.result)
Exemplo n.º 27
0
def main():
    # Get options
    args = options()

    # Set variables
    device = 0
    pcv.params.debug = args.debug
    img_file = args.image

    # Read image
    img, path, filename = pcv.readimage(filename=img_file, mode='rgb')

    # Process saturation channel from HSV colour space
    s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')
    lp_s = pcv.laplace_filter(s, 1, 1)
    shrp_s = pcv.image_subtract(s, lp_s)
    s_eq = pcv.hist_equalization(shrp_s)
    s_thresh = pcv.threshold.binary(gray_img=s_eq,
                                    threshold=215,
                                    max_value=255,
                                    object_type='light')
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)

    # Process green-magenta channel from LAB colour space
    b = pcv.rgb2gray_lab(rgb_img=img, channel='a')
    b_lp = pcv.laplace_filter(b, 1, 1)
    b_shrp = pcv.image_subtract(b, b_lp)
    b_thresh = pcv.threshold.otsu(b_shrp, 255, object_type='dark')

    # Create and apply mask
    bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_thresh)
    filled = pcv.fill_holes(bs)
    masked = pcv.apply_mask(img=img, mask=filled, mask_color='white')

    # Extract colour channels from masked image
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')

    # Threshold the green-magenta and blue images
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a,
                                          threshold=115,
                                          max_value=255,
                                          object_type='dark')
    maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a,
                                           threshold=140,
                                           max_value=255,
                                           object_type='light')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b,
                                          threshold=128,
                                          max_value=255,
                                          object_type='light')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)

    # Produce and apply a mask
    opened_ab = pcv.opening(gray_img=ab)
    ab_fill = pcv.fill(bin_img=ab, size=200)
    closed_ab = pcv.closing(gray_img=ab_fill)
    masked2 = pcv.apply_mask(img=masked, mask=bs, mask_color='white')

    # Identify objects
    id_objects, obj_hierarchy = pcv.find_objects(img=masked2, mask=ab_fill)

    # Define region of interest (ROI)
    roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                            x=250,
                                            y=100,
                                            h=200,
                                            w=200)

    # Decide what objects to keep
    roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
        img=img,
        roi_contour=roi1,
        roi_hierarchy=roi_hierarchy,
        object_contour=id_objects,
        obj_hierarchy=obj_hierarchy,
        roi_type='partial')

    # Object combine kept objects
    obj, mask = pcv.object_composition(img=img,
                                       contours=roi_objects,
                                       hierarchy=hierarchy3)

    ############### Analysis ################

    outfile = False
    if args.writeimg == True:
        outfile = args.outdir + "/" + filename

    # Analyze the plant
    analysis_image = pcv.analyze_object(img=img, obj=obj, mask=mask)
    color_histogram = pcv.analyze_color(rgb_img=img,
                                        mask=kept_mask,
                                        hist_plot_type='all')
    top_x, bottom_x, center_v_x = pcv.x_axis_pseudolandmarks(img=img,
                                                             obj=obj,
                                                             mask=mask)
    top_y, bottom_y, center_v_y = pcv.y_axis_pseudolandmarks(img=img,
                                                             obj=obj,
                                                             mask=mask)

    # Print results of the analysis
    pcv.print_results(filename=args.result)
    pcv.output_mask(img,
                    kept_mask,
                    filename,
                    outdir=args.outdir,
                    mask_only=True)
Exemplo n.º 28
0
def generateMask(input, output, maskType=MASK_TYPES['BW']):
    pcv.params.debug = True  #set debug mode
    # pcv.params.debug_outdir="./output.txt" #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', 'envi', or 'csv'
    img, path, filename = pcv.readimage(filename=input, mode='rgb')

    s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')

    # Threshold the saturation image
    s_thresh = pcv.threshold.binary(gray_img=s,
                                    threshold=85,
                                    max_value=255,
                                    object_type='light')

    # Median Blur
    s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=5)
    s_cnt = pcv.median_blur(gray_img=s_thresh, ksize=5)

    # Convert RGB to LAB and extract the Blue channel
    b = pcv.rgb2gray_lab(rgb_img=img, channel='b')

    # Threshold the blue image
    b_thresh = pcv.threshold.binary(gray_img=b,
                                    threshold=160,
                                    max_value=255,
                                    object_type='light')
    b_cnt = pcv.threshold.binary(gray_img=b,
                                 threshold=160,
                                 max_value=255,
                                 object_type='light')

    # Fill small objects
    # b_fill = pcv.fill(b_thresh, 10)

    # Join the thresholded saturation and blue-yellow images
    bs = pcv.logical_or(bin_img1=s_mblur, bin_img2=b_cnt)

    # Apply Mask (for VIS images, mask_color=white)
    masked = pcv.apply_mask(img=img, mask=bs, mask_color='white')

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')

    # Threshold the green-magenta and blue images
    maskeda_thresh = pcv.threshold.binary(gray_img=masked_a,
                                          threshold=115,
                                          max_value=255,
                                          object_type='dark')
    maskeda_thresh1 = pcv.threshold.binary(gray_img=masked_a,
                                           threshold=135,
                                           max_value=255,
                                           object_type='light')
    maskedb_thresh = pcv.threshold.binary(gray_img=masked_b,
                                          threshold=128,
                                          max_value=255,
                                          object_type='light')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab1 = pcv.logical_or(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_or(bin_img1=maskeda_thresh1, bin_img2=ab1)
    if maskType == MASK_TYPES['BW']:
        pcv.print_image(ab, filename=output)
        return (True, None)

    # Fill small objects
    ab_fill = pcv.fill(bin_img=ab, size=200)

    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(img=masked, mask=ab_fill, mask_color='black')
    if maskType == MASK_TYPES['COLORED']:
        pcv.print_image(masked2, filename=output)
        return (True, None)

    return (False, 'Unknown mask type.')
    """
Exemplo n.º 29
0
# In[109]:

# Convert RGB to HSV and extract the saturation channel
# Then set threshold for saturation
s = pcv.rgb2gray_hsv(rgb_img=img1, channel='s')
s_thresh = pcv.threshold.binary(gray_img=s,
                                threshold=122,
                                max_value=255,
                                object_type='dark')

# In[110]:

# Set Median Blur
#Input box size "ksize"
s_mblur = pcv.median_blur(gray_img=s_thresh, ksize=2)
s_cnt = pcv.median_blur(gray_img=s_thresh, ksize=2)

# In[111]:

# Convert RGB to LAB and extract the blue channel
#Then threshold the image
b = pcv.rgb2gray_lab(rgb_img=img1, channel='b')
b_thresh = pcv.threshold.binary(gray_img=b,
                                threshold=135,
                                max_value=255,
                                object_type='light')

#Setting threshold continued
b_cnt = pcv.threshold.binary(gray_img=b,
                             threshold=135,
def test(true_positive_file, test_parameters):
    saturation_lower_tresh = test_parameters[0]
    saturation_higher_tresh = test_parameters[1]
    hue_lower_tresh = test_parameters[2]
    hue_higher_tresh = test_parameters[3]
    value_lower_tresh = test_parameters[4]
    value_higher_tresh = test_parameters[5]
    l_lower_thresh = test_parameters[6]
    a_lower_thresh_1 = test_parameters[7]
    a_lower_thresh_2 = test_parameters[8]
    b_lower_thresh_1 = test_parameters[9]
    b_higher_thresh_1 = test_parameters[10]
    b_lower_thresh_2 = test_parameters[11]
    b_higher_thresh_2 = test_parameters[12]
    HSV_blur_k = test_parameters[13]
    LAB_blur_k = test_parameters[14]
    b_fill_k = test_parameters[15]
    LAB_fill_k = test_parameters[16]

    class args:
        #image = "C:\\Users\\RensD\\OneDrive\\studie\\Master\\The_big_project\\top_perspective\\0214_2018-03-07 08.55 - 26_cam9.png"
        image = true_positive_file
        outdir = "C:\\Users\\RensD\\OneDrive\\studie\\Master\\The_big_project\\top_perspective\\output"
        debug = debug_setting
        result = "results.txt"

    # Get options
    pcv.params.debug = args.debug  #set debug mode
    pcv.params.debug_outdir = args.outdir  #set output directory

    pcv.params.debug = args.debug  # set debug mode
    pcv.params.debug_outdir = args.outdir  # set output directory

    # Read image
    img, path, filename = pcv.readimage(filename=args.image)

    #______________________________________________________________#### BEGIN HSV COLORSPACE WORKFLOW ###
    # Convert RGB to HSV and extract the saturation channel
    # Threshold the saturation

    s = pcv.rgb2gray_hsv(rgb_img=img, channel='s')
    s_thresh, maskeds_image = pcv.threshold.custom_range(
        rgb_img=s,
        lower_thresh=[saturation_lower_tresh],
        upper_thresh=[saturation_higher_tresh],
        channel='gray')
    # Threshold the hue
    h = pcv.rgb2gray_hsv(rgb_img=img, channel='h')
    h_thresh, maskedh_image = pcv.threshold.custom_range(
        rgb_img=h,
        lower_thresh=[hue_lower_tresh],
        upper_thresh=[hue_higher_tresh],
        channel='gray')
    v = pcv.rgb2gray_hsv(rgb_img=img, channel='v')
    v_thresh, maskedv_image = pcv.threshold.custom_range(
        rgb_img=v,
        lower_thresh=[value_lower_tresh],
        upper_thresh=[value_higher_tresh],
        channel='gray')
    # Join saturation, Hue and Value
    sh = pcv.logical_and(bin_img1=s_thresh, bin_img2=h_thresh)
    hsv = pcv.logical_and(bin_img1=sh, bin_img2=v_thresh)
    # Median Blur
    s_mblur = pcv.median_blur(gray_img=hsv, ksize=HSV_blur_k)
    #s_cnt = pcv.median_blur(gray_img=s_thresh, ksize=5)
    #______________________________________________________________#### END HSV COLORSPACE WORKFLOW ###

    #______________________________________________________________#### BEGIN CIELAB COLORSPACE WORKFLOW ###
    # Convert RGB to LAB and extract the Blue channel
    b = pcv.rgb2gray_lab(rgb_img=img, channel='b')

    # Threshold the blue image
    b_thresh = pcv.threshold.binary(gray_img=b,
                                    threshold=b_lower_thresh_1,
                                    max_value=b_higher_thresh_1,
                                    object_type='light')
    b_cnt = pcv.threshold.binary(gray_img=b,
                                 threshold=b_lower_thresh_1,
                                 max_value=b_higher_thresh_1,
                                 object_type='light')
    # Fill small objects
    b_cnt = pcv.fill(
        b_thresh, b_fill_k
    )  # If the fill step fails because of small objects try a smaller fill, else abort.

    # Join the thresholded saturation and blue-yellow images
    bs = pcv.logical_and(bin_img1=s_mblur, bin_img2=b_cnt)  # CHANGER OR TO AND

    # Apply Mask (for VIS images, mask_color=white)
    masked = pcv.apply_mask(rgb_img=img, mask=bs, mask_color='white')
    #Now the background is filtered away. Next step is to capture the plant.

    # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels
    masked_l = pcv.rgb2gray_lab(rgb_img=masked, channel='l')
    masked_a = pcv.rgb2gray_lab(rgb_img=masked, channel='a')
    masked_b = pcv.rgb2gray_lab(rgb_img=masked, channel='b')
    # Threshold the green-magenta and blue images
    maskedl_thresh, maskedl_image = pcv.threshold.custom_range(
        rgb_img=masked_l,
        lower_thresh=[120],
        upper_thresh=[247],
        channel='gray')
    maskeda_thresh, maskeda_image = pcv.threshold.custom_range(
        rgb_img=masked_a, lower_thresh=[0], upper_thresh=[114], channel='gray')
    maskedb_thresh, maskedb_image = pcv.threshold.custom_range(
        rgb_img=masked_b,
        lower_thresh=[130],
        upper_thresh=[240],
        channel='gray')

    # Join the thresholded saturation and blue-yellow images (OR)
    ab1 = pcv.logical_and(bin_img1=maskeda_thresh, bin_img2=maskedb_thresh)
    ab = pcv.logical_and(bin_img1=maskedl_thresh, bin_img2=ab1)

    # Fill small objects
    ab_fill = pcv.median_blur(gray_img=ab, ksize=LAB_blur_k)
    ab_fill = pcv.fill(bin_img=ab_fill, size=LAB_fill_k)
    # Apply mask (for VIS images, mask_color=white)
    masked2 = pcv.apply_mask(rgb_img=masked, mask=ab_fill, mask_color='white')

    # Identify objects
    id_objects, obj_hierarchy = pcv.find_objects(img=masked2, mask=ab_fill)

    # Define ROI
    roi1, roi_hierarchy = pcv.roi.rectangle(img=masked2,
                                            x=0,
                                            y=0,
                                            h=960,
                                            w=1280)

    # Decide which objects to keep
    roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects(
        img=img,
        roi_contour=roi1,
        roi_hierarchy=roi_hierarchy,
        object_contour=id_objects,
        obj_hierarchy=obj_hierarchy,
        roi_type='partial')

    # Object combine kept objects
    obj, mask = pcv.object_composition(img=img,
                                       contours=roi_objects,
                                       hierarchy=hierarchy3)

    if use_mask == True:
        return (mask)
    else:
        masked2 = pcv.apply_mask(rgb_img=masked, mask=mask, mask_color='white')
        return (masked2)