Exemplo n.º 1
0
def predict_image(model,
                  image_path,
                  score_threshold=0.1,
                  max_detections=200,
                  return_plot=True):
    """
        Predict an image
        return_plot: Logical. If true, return a image object, else return bounding boxes
        """
    #predict
    raw_image = cv2.imread(image_path)
    image = image_utils.preprocess_image(raw_image)
    image, scale = keras_retinanet_image.resize_image(image)

    if keras.backend.image_data_format() == 'channels_first':
        image = image.transpose((2, 0, 1))

    # run network
    boxes, scores, labels = model.predict_on_batch(
        np.expand_dims(image, axis=0))[:3]

    # correct boxes for image scale
    boxes /= scale

    # select indices which have a score above the threshold
    indices = np.where(scores[0, :] > score_threshold)[0]

    # select those scores
    scores = scores[0][indices]

    # find the order with which to sort the scores
    scores_sort = np.argsort(-scores)[:max_detections]

    # select detections
    image_boxes = boxes[0, indices[scores_sort], :]
    image_scores = scores[scores_sort]
    image_labels = labels[0, indices[scores_sort]]
    image_detections = np.concatenate([
        image_boxes,
        np.expand_dims(image_scores, axis=1),
        np.expand_dims(image_labels, axis=1)
    ],
                                      axis=1)

    if return_plot:
        draw_detections(raw_image,
                        image_boxes,
                        image_scores,
                        image_labels,
                        label_to_name=label_to_name,
                        score_threshold=score_threshold)
        return raw_image
    else:
        return image_boxes
Exemplo n.º 2
0
                
    return new_detections, new_detections_metric


def save_images(path_list, detections, generator, score_threshold, save_path, iou_frames):
<<<<<<< HEAD
    for i in progressbar.progressbar(range(generator.size()), prefix='Saving images: '):
=======
    for i in progressbar.progressbar(range(generator.size()-9400), prefix='Saving images: '):
>>>>>>> 19c53023491d92692b7d44f1343b74e2d6623f42
        #draw_annotations(generator.load, generator.load_annotations(i), label_to_name=generator.label_to_name)
        image = generator.load_image(path_list[i][0])
        draw_detections(
            image, 
            detections[i][0], 
            detections[i][1], 
            detections[i][2], 
            label_to_name=generator.label_to_name, score_threshold=score_threshold
            )
        output_path = make_output_path(save_path, generator.image_path(path_list[i][0]), flatten=False)
        os.makedirs(os.path.dirname(output_path), exist_ok=True)
        cv2.imwrite(output_path, image)

def evaluate(generator, detections, iou_threshold):
    all_detections     = detections
    all_annotations    = _get_annotations(generator)
    average_precisions = {}
    for label in range(generator.num_classes()):
        if not generator.has_label(label):
            continue
Exemplo n.º 3
0
def _get_detections(generator,
                    model,
                    score_threshold=0.05,
                    max_detections=300,
                    save_path=None,
                    experiment=None,
                    postprocess=False):
    """ Get the detections from the model using the generator.

    The result is a list of lists such that the size is:
        all_detections[num_images][num_classes] = detections[num_detections, 4 + num_classes]

    # Arguments
        generator       : The generator used to run images through the model.
        model           : The model to run on the images.
        score_threshold : The score confidence threshold to use.
        max_detections  : The maximum number of detections to use per image.
        save_path       : The path to save the images with visualized detections to.
        experiment    : Comet ML experiment
    # Returns
        A list of lists containing the detections for each image in the generator.
    """
    all_detections = [[None for i in range(generator.num_classes())]
                      for j in range(generator.size())]

    for i in range(generator.size()):
        raw_image = generator.load_image(i)
        plot_image = copy.deepcopy(raw_image)

        #Format name and save
        image_name = generator.image_names[i]
        row = generator.image_data[image_name]
        lfname = os.path.splitext(row["tile"])[0] + "_" + str(
            row["window"]) + "raw_image"

        #Skip if missing a component data source
        if raw_image is False:
            print("Empty image, skipping")
            continue

        #Store plotting images
        plot_rgb = plot_image[:, :, :3].copy()

        #predict
        image = generator.preprocess_image(raw_image)
        image, scale = generator.resize_image(image)

        if keras.backend.image_data_format() == 'channels_first':
            image = image.transpose((2, 0, 1))

        # run network
        boxes, scores, labels = model.predict_on_batch(
            np.expand_dims(image, axis=0))[:3]

        # correct boxes for image scale
        boxes /= scale

        # select indices which have a score above the threshold
        indices = np.where(scores[0, :] > score_threshold)[0]

        # select those scores
        scores = scores[0][indices]

        # find the order with which to sort the scores
        scores_sort = np.argsort(-scores)[:max_detections]

        # select detections
        image_boxes = boxes[0, indices[scores_sort], :]
        image_scores = scores[scores_sort]
        image_labels = labels[0, indices[scores_sort]]
        image_detections = np.concatenate([
            image_boxes,
            np.expand_dims(image_scores, axis=1),
            np.expand_dims(image_labels, axis=1)
        ],
                                          axis=1)

        #name image
        image_name = generator.image_names[i]
        row = generator.image_data[image_name]
        fname = os.path.splitext(row["tile"])[0] + "_" + str(row["window"])

        #drape boxes if they exist
        if len(image_boxes) > 0:
            #get lidar cloud if a new tile, or if not the same tile as previous image.
            if generator.with_lidar:
                if i == 0:
                    generator.load_lidar_tile()
                elif not generator.image_data[i][
                        "tile"] == generator.image_data[i - 1]["tile"]:
                    generator.load_lidar_tile()

            #The tile could be the full tile, so let's check just the 400 pixel crop we are interested
            #Not the best structure, but the on-the-fly generator always has 0 bounds
            if hasattr(generator, 'hf'):
                bounds = generator.hf["utm_coords"][generator.row["window"]]
            else:
                bounds = []

        if save_path is not None:
            draw_annotations(plot_rgb,
                             generator.load_annotations(i),
                             label_to_name=generator.label_to_name)
            draw_detections(plot_rgb,
                            image_boxes,
                            image_scores,
                            image_labels,
                            label_to_name=generator.label_to_name,
                            score_threshold=score_threshold)

            #name image
            image_name = generator.image_names[i]
            row = generator.image_data[image_name]
            fname = os.path.splitext(row["tile"])[0] + "_" + str(row["window"])

            #Write RGB
            cv2.imwrite(os.path.join(save_path, '{}.png'.format(fname)),
                        plot_rgb)

            if experiment:
                experiment.log_image(os.path.join(save_path,
                                                  '{}.png'.format(fname)),
                                     name=fname)

        # copy detections to all_detections
        for label in range(generator.num_classes()):
            all_detections[i][label] = image_detections[
                image_detections[:, -1] == label, :-1]

    return all_detections
Exemplo n.º 4
0
def _get_detections(generator,
                    model,
                    score_threshold=0.05,
                    max_detections=100,
                    save_path=None):
    """ Get the detections from the model using the generator.

    The result is a list of lists such that the size is:
        all_detections[num_images][num_classes] = detections[num_detections, 4 + num_classes]

    # Arguments
        generator       : The generator used to run images through the model.
        model           : The model to run on the images.
        score_threshold : The score confidence threshold to use.
        max_detections  : The maximum number of detections to use per image.
        save_path       : The path to save the images with visualized detections to.
    # Returns
        A list of lists containing the detections for each image in the generator.
    """
    all_detections = [[None for i in range(generator.num_classes())]
                      for j in range(generator.size())]
    all_masks = [[None for i in range(generator.num_classes())]
                 for j in range(generator.size())]

    for i in range(generator.size()):
        raw_image = generator.load_image(i)
        image = generator.preprocess_image(raw_image.copy())
        image, scale = generator.resize_image(image)

        # run network
        outputs = model.predict_on_batch(np.expand_dims(image, axis=0))
        boxes = outputs[-4]
        scores = outputs[-3]
        labels = outputs[-2]
        masks = outputs[-1]

        # correct boxes for image scale
        boxes /= scale

        # select indices which have a score above the threshold
        indices = np.where(scores[0, :] > score_threshold)[0]

        # select those scores
        scores = scores[0][indices]

        # find the order with which to sort the scores
        scores_sort = np.argsort(-scores)[:max_detections]

        # select detections
        image_boxes = boxes[0, indices[scores_sort], :]
        image_scores = scores[scores_sort]
        image_labels = labels[0, indices[scores_sort]]
        image_masks = masks[0, indices[scores_sort], :, :, image_labels]
        image_detections = np.concatenate([
            image_boxes,
            np.expand_dims(image_scores, axis=1),
            np.expand_dims(image_labels, axis=1)
        ],
                                          axis=1)

        if save_path is not None:
            # draw_annotations(raw_image, generator.load_annotations(i)[0], label_to_name=generator.label_to_name)
            draw_detections(raw_image,
                            image_boxes,
                            image_scores,
                            image_labels,
                            score_threshold=score_threshold,
                            label_to_name=generator.label_to_name)
            draw_masks(raw_image,
                       image_boxes.astype(int),
                       image_masks,
                       labels=image_labels)

            cv2.imwrite(os.path.join(save_path, '{}.png'.format(i)), raw_image)

        # copy detections to all_detections
        for label in range(generator.num_classes()):
            all_detections[i][label] = image_detections[
                image_detections[:, -1] == label, :-1]
            all_masks[i][label] = image_masks[image_detections[:, -1] == label,
                                              ...]

        print('{}/{}'.format(i + 1, generator.size()), end='\r')

    return all_detections, all_masks
Exemplo n.º 5
0
def neonRecall(
    sites,
    generator,
    model,
    score_threshold=0.05,
    max_detections=100,
    suppression_threshold=0.15,
    save_path=None,
    experiment=None):

    point_contains = [ ]

    site_data_dict = {}
    for site in sites:
        #Container for recall pts.
        
        #load field data
        field_data = pd.read_csv("data/field_data.csv") 
        field_data = field_data[field_data['UTM_E'].notnull()]
    
        #select site
        site_data = field_data[field_data["siteID"]==site]
    
        #select tree species
        specieslist = pd.read_csv("data/AcceptedSpecies.csv",encoding="utf-8")
        specieslist =  specieslist[specieslist["siteID"] == site]
    
        site_data = site_data[site_data["scientificName"].isin(specieslist["scientificName"].values)]
    
        #Single bole individuals as representitve, no individualID ending in non-digits
        site_data = site_data[site_data["individualID"].str.contains("\d$")]
        site_data_dict[site] = site_data
        
        #Only data within the last two years, sites can be hand managed
        #site_data=site_data[site_data["eventID"].str.contains("2015|2016|2017|2018")]
        
    for i in range(generator.size()):
        
        #Load image
        raw_image    = generator.load_image(i)
        plot_image = copy.deepcopy(raw_image)
   
        #Skip if missing a component data source
        if raw_image is False:
            print("Empty image, skipping")
            continue
        
        #Store plotting images.
        plot_rgb = plot_image[:,:,:3].copy()
        plot_chm = plot_image[:,:,3]     
        
        image        = generator.preprocess_image(raw_image)
        image, scale = generator.resize_image(image)

        # run network
        boxes, scores, labels = model.predict_on_batch(np.expand_dims(image, axis=0))[:3]

        # correct boxes for image scale
        boxes /= scale

        # select indices which have a score above the threshold
        indices = np.where(scores[0, :] > score_threshold)[0]

        # select those scores
        scores = scores[0][indices]

        # find the order with which to sort the scores
        scores_sort = np.argsort(-scores)[:max_detections]

        # select detections
        image_boxes      = boxes[0, indices[scores_sort], :]
        image_scores     = scores[scores_sort]
        image_labels     = labels[0, indices[scores_sort]]
        image_detections = np.concatenate([image_boxes, np.expand_dims(image_scores, axis=1), np.expand_dims(image_labels, axis=1)], axis=1)
        
        #Find geographic bounds
        base_dir = generator.DeepForest_config[generator.row["site"]][generator.name]["RGB"]
        tile_path = os.path.join(base_dir, generator.image_data[i]["tile"])
        
        with rasterio.open(tile_path) as dataset:
            tile_bounds = dataset.bounds   
    
        #drape boxes
        #get lidar cloud if a new tile, or if not the same tile as previous image.
        if i == 0:
            generator.load_lidar_tile()
        elif not generator.image_data[i]["tile"] == generator.image_data[i-1]["tile"]:
            generator.load_lidar_tile()
        
        #The tile could be the full tile, so let's check just the 400 pixel crop we are interested    
        #Not the best structure, but the on-the-fly generator always has 0 bounds
        if hasattr(generator, 'hf'):
            bounds = generator.hf["utm_coords"][generator.row["window"]]    
        else:
            bounds=[]
            
        density = Lidar.check_density(generator.lidar_tile, bounds=bounds)
        
        #print("Point density is {:.2f}".format(density))
                
        if density > 100:
            #find window utm coordinates
            #print("Bounds for image {}, window {}, are {}".format(generator.row["tile"], generator.row["window"], bounds))
            pc = postprocessing.drape_boxes(boxes=image_boxes, pc = generator.lidar_tile, bounds=bounds)     
            
            #Get new bounding boxes
            new_boxes = postprocessing.cloud_to_box(pc, bounds)    
            new_scores = image_scores[:new_boxes.shape[0]]
            new_labels = image_labels[:new_boxes.shape[0]]          
            image_detections = np.concatenate([new_boxes, np.expand_dims(new_scores, axis=1), np.expand_dims(new_labels, axis=1)], axis=1)
            
        else:
            #print("Point density of {:.2f} is too low, skipping image {}".format(density, generator.row["tile"]))   
            pass

        #add spatial NEON points
        site_data =site_data_dict[generator.row["site"]]
        plotID = os.path.splitext(generator.image_data[i]["tile"])[0]
        plot_data = site_data[site_data.plotID == plotID]

        #Save image and send it to logger
        if save_path is not None:
            
            x = (plot_data.UTM_E - tile_bounds.left).values / 0.1
            y = (tile_bounds.top - plot_data.UTM_N).values / 0.1
            
            for j in np.arange(len(x)):
                cv2.circle(plot_image,(int(x[j]),int(y[j])), 2, (0,0,255), -1)
    
            #Write RGB
            draw_detections(plot_rgb, image_boxes, image_scores, image_labels, label_to_name=generator.label_to_name,score_threshold=score_threshold)
        
            #name image
            image_name=generator.image_names[i]        
            row=generator.image_data[image_name]             
            fname=os.path.splitext(row["tile"])[0] + "_" + str(row["window"])
        
            #Write RGB
            cv2.imwrite(os.path.join(save_path, '{}_NeonPlot.png'.format(fname)), plot_rgb)
            
            plot_chm = plot_chm/plot_chm.max() * 255                        
            chm = np.uint8(plot_chm)
            draw_detections(chm, image_boxes, image_scores, image_labels, label_to_name=generator.label_to_name, score_threshold=score_threshold, color = (80,127,255))            
            cv2.imwrite(os.path.join(save_path, '{}_Lidar_NeonPlot.png'.format(plotID)), chm)
                
            #Format name and save
            if experiment:
                experiment.log_image(os.path.join(save_path, '{}_NeonPlot.png'.format(plotID)),file_name=str(plotID))
                experiment.log_image(os.path.join(save_path, '{}_Lidar_NeonPlot.png'.format(plotID)),file_name=str("Lidar_" + plotID))
        
        #calculate recall
            s = gp.GeoSeries(map(Point, zip(plot_data.UTM_E, plot_data.UTM_N)))
    
        #Calculate recall
        projected_boxes = []
        
        for row in  image_boxes:
            #Add utm bounds and create a shapely polygon
            pbox=create_polygon(row, tile_bounds, cell_size=0.1)
            projected_boxes.append(pbox)
    
        #for each point, is it within a prediction?
        for index, tree in plot_data.iterrows():
            p=Point(tree.UTM_E, tree.UTM_N)
    
            within_polygon=[]
            for prediction in projected_boxes:
                within_polygon.append(p.within(prediction))
    
            #Check for overlapping polygon, add it to list
            is_within = sum(within_polygon) > 0
            point_contains.append(is_within)
                
    #sum recall across plots
    if len(point_contains)==0:
        recall = None
    else:
        ## Recall rate for plot
        recall = sum(point_contains)/len(point_contains)    
        
    return(recall)
Exemplo n.º 6
0
def predictTest(model,
                data_dir,
                target_path,
                score_threshold=0.2,
                seriesuids=None,
                imshow=True,
                input_min_max_side=(768, 768)):
    data_npy_name_list = [
        file_name for file_name in os.listdir(data_dir) if '.npy' in file_name
    ]
    anno_list = []

    target_dir = os.path.dirname(target_path)
    if not os.path.exists(target_dir):
        os.mkdir(target_dir)

    for data_npy_name in data_npy_name_list:

        seriesuid = data_npy_name.split('.npy')[0]
        if seriesuids is not None and seriesuid not in seriesuids:
            continue
        print('detect', seriesuid)
        data_path = os.path.join(data_dir, data_npy_name)
        info_pkl_path = os.path.join(data_dir, seriesuid + '.pkl')

        with open(info_pkl_path, 'rb') as fp:
            patient_info = pickle.load(fp)

        data_npy = np.load(data_path)  # zyx
        data_npy = np.transpose(data_npy, (1, 2, 0))  # zyx -> yxz

        slice_start = INPUT_SLICE // 2

        for slice_idx in range(slice_start,
                               data_npy.shape[2] - INPUT_SLICE // 2,
                               max(INPUT_SLICE // 2, 1)):
            s_start = slice_idx - INPUT_SLICE // 2
            input_data = (data_npy[:, :, s_start:s_start + INPUT_SLICE]).copy()
            input_img, scale = resize_image(
                preprocess_image(input_data, 'caffe'), input_min_max_side[0],
                input_min_max_side[1])
            boxes, scores, labels = model.predict_on_batch(
                np.expand_dims(input_img, axis=0))
            boxes = boxes[0]
            scores = scores[0]
            labels = labels[0]

            if imshow:
                img_show = np.tile(
                    ((input_img + 128)[:, :, 1:2]).astype(np.uint8), (1, 1, 3))
                draw_detections(img_show,
                                boxes,
                                scores,
                                labels,
                                color=(0, 255, 0),
                                score_threshold=score_threshold)
                cv2.imshow('detect_image', img_show)
                k = cv2.waitKey()
                if k == ord('q'):
                    exit()
                elif k == ord('c'):
                    imshow = False

            boxes /= scale

            for label, score, box in zip(labels, scores, boxes):
                if score < score_threshold:
                    continue
                x1, y1, x2, y2 = box

                voxelX = (x1 + x2) / 2
                voxelY = (y1 + y2) / 2
                voxelZ = slice_idx

                coordX, coordY, coordZ = coord_pix_to_world(
                    [voxelX, voxelY, voxelZ], patient_info['spacing'],
                    patient_info['origin'], patient_info['direction'])

                the_label = CLASS_IDX_TO_MODEL_CLASS_ID[str(label)]
                anno_list.append(
                    [seriesuid, coordX, coordY, coordZ, the_label, score])

    anno_csv = pd.DataFrame(data=anno_list, columns=RESULT_CSV_COLUMNS)
    anno_csv.to_csv(target_path, index=False, encoding='UTF-8')
Exemplo n.º 7
0
def predict_image(model,
                  image_path,
                  score_threshold=0.1,
                  max_detections=200,
                  return_plot=True):
    """
    Predict invidiual tree crown bounding boxes for a single image
    
    model (object): A keras-retinanet model to predict bounding boxes, either load a model from weights, use the latest release, or train a new model from scratch.  
    image_path (str): Path to image file on disk
    score_threshold (float): Minimum probability score to be included in final boxes, ranging from 0 to 1.
    max_detections (int): Maximum number of bounding box predictions per tile
    return_plot (bool):  If true, return a image object, else return bounding boxes as a numpy array
    Returns:
        raw_image (array): If return_plot is TRUE, the image with the overlaid boxes is returned
        image_boxes: If return_plot is FALSE, the bounding boxes as a 4 column array -> xmin, ymin, xmax, ymax
    """
    #predict
    raw_image = cv2.imread(image_path)
    image = preprocess(raw_image)
    image, scale = keras_retinanet_image.resize_image(image)

    if keras.backend.image_data_format() == 'channels_first':
        image = image.transpose((2, 0, 1))

    # run network
    boxes, scores, labels = model.predict_on_batch(
        np.expand_dims(image, axis=0))[:3]

    # correct boxes for image scale
    boxes /= scale

    # select indices which have a score above the threshold
    indices = np.where(scores[0, :] > score_threshold)[0]

    # select those scores
    scores = scores[0][indices]

    # find the order with which to sort the scores
    scores_sort = np.argsort(-scores)[:max_detections]

    # select detections
    image_boxes = boxes[0, indices[scores_sort], :]
    image_scores = scores[scores_sort]
    image_labels = labels[0, indices[scores_sort]]
    image_detections = np.concatenate([
        image_boxes,
        np.expand_dims(image_scores, axis=1),
        np.expand_dims(image_labels, axis=1)
    ],
                                      axis=1)

    if return_plot:
        draw_detections(raw_image,
                        image_boxes,
                        image_scores,
                        image_labels,
                        label_to_name=label_to_name,
                        score_threshold=score_threshold)
        return raw_image
    else:
        return image_boxes
Exemplo n.º 8
0
    # print("image_scores",image_scores.shape,image_scores)
    # print("image_labels",image_labels.shape,image_labels)

    image_boxes      = image_boxes[indices_postnms]
    image_scores     = image_scores[indices_postnms]
    image_labels     = image_labels[indices_postnms]

    #
    # print("image_boxes",image_boxes.shape,image_boxes)
    # print("image_scores",image_scores.shape,image_scores)
    # print("image_labels",image_labels.shape,image_labels)
    # print("indices_postnms", indices_postnms)


    image_detections = np.concatenate([image_boxes, np.expand_dims(image_scores, axis=1), np.expand_dims(image_labels, axis=1)], axis=1)
    data_sequence.results[id]=image_detections
    if save_path is not None and len(indices)>0:
        draw_detections(image, image_boxes, image_scores, image_labels, label_to_name=label_to_name,score_threshold=0)
        cv2.imwrite(os.path.join(save_path, '{}.jpg'.format(id)), image)

    # if len(indices)>0:
    psaver.add_instances(data_sequence.filename, xywh, image_boxes, image_scores)
psaver.save()
psaver.save_nms()
psaver.save_tagbrowser()
psaver.save_nms_tagbrowser()

# with open(saving_result_path, 'wb') as handle:
#     pickle.dump(img_infos, handle, protocol = pickle.HIGHEST_PROTOCOL)
ordered_data_sequence.stop()
Exemplo n.º 9
0
def predict_image(model,
                  image_path=None,
                  raw_image=None,
                  score_threshold=0.05,
                  max_detections=200,
                  return_plot=True,
                  classes={"0": "Tree"},
                  color=None):
    """
    Predict invidiual tree crown bounding boxes for a single image
    
    Args:
        model (object): A keras-retinanet model to predict bounding boxes, either load a model from weights, use the latest release, or train a new model from scratch.  
        image_path (str): Path to image file on disk
        raw_image (str): Numpy image array in BGR channel order following openCV convention
        score_threshold (float): Minimum probability score to be included in final boxes, ranging from 0 to 1.
        max_detections (int): Maximum number of bounding box predictions per tile
        return_plot (bool):  If true, return a image object, else return bounding boxes as a numpy array
    
    Returns:
        raw_image (array): If return_plot is TRUE, the image with the overlaid boxes is returned
        image_detections: If return_plot is FALSE, a np.array of image_boxes, image_scores, image_labels
    """
    #Check for raw_image
    if raw_image is not None:
        numpy_image = raw_image.copy()
    else:
        #Read from path
        numpy_image = cv2.imread(image_path)

    #Make sure image exists
    try:
        numpy_image.shape
    except:
        raise IOError(
            "Image file {} cannot be read, check that it exists".format(
                image_path))

    #Check that its 3 band
    bands = numpy_image.shape[2]
    if not bands == 3:
        raise IOError(
            "Input file {} has {} bands. DeepForest only accepts 3 band RGB rasters. If the image was cropped and saved as a .jpg, please ensure that no alpha channel was used."
            .format(path_to_raster, bands))

    image = keras_retinanet_image.preprocess_image(numpy_image)
    image, scale = keras_retinanet_image.resize_image(image)

    if keras.backend.image_data_format() == 'channels_first':
        image = image.transpose((2, 0, 1))

    # run network
    boxes, scores, labels = model.predict_on_batch(
        np.expand_dims(image, axis=0))[:3]

    # correct boxes for image scale
    boxes /= scale

    # select indices which have a score above the threshold
    indices = np.where(scores[0, :] > score_threshold)[0]

    # select those scores
    scores = scores[0][indices]

    # find the order with which to sort the scores
    scores_sort = np.argsort(-scores)[:max_detections]

    # select detections
    image_boxes = boxes[0, indices[scores_sort], :]
    image_scores = scores[scores_sort]
    image_labels = labels[0, indices[scores_sort]]
    image_detections = np.concatenate([
        image_boxes,
        np.expand_dims(image_scores, axis=1),
        np.expand_dims(image_labels, axis=1)
    ],
                                      axis=1)

    df = pd.DataFrame(
        image_detections,
        columns=["xmin", "ymin", "xmax", "ymax", "score", "label"])

    #Change numberic class into string label
    df.label = df.label.astype(int)
    df.label = df.label.apply(lambda x: classes[x])

    if return_plot:
        draw_detections(numpy_image,
                        image_boxes,
                        image_scores,
                        image_labels,
                        label_to_name=None,
                        score_threshold=score_threshold,
                        color=color)
        return numpy_image
    else:
        return df
Exemplo n.º 10
0
def Jaccard(
        generator,
        model,
        iou_threshold=0.5,
        score_threshold=0.05,
        max_detections=100,
        suppression_threshold=0.2,
        save_path=None,
        experiment=None,
        DeepForest_config = None
        ):
        """ Evaluate a given dataset using a given model.

        # Arguments
            generator       : The generator that represents the dataset to evaluate.
            model           : The model to evaluate.
            iou_threshold   : The threshold used to consider when a detection is positive or negative.
            score_threshold : The score confidence threshold to use for detections.
            max_detections  : The maximum number of detections to use per image.
            save_path       : The path to save images with visualized detections to.
            experiment     : Comet ml experiment to evaluate
        # Returns
            A dict mapping class names to mAP scores.
        """

        #Load ground truth polygons
        ground_truth, ground_truth_tiles, ground_truth_utmbox=_load_groundtruth(DeepForest_config)

        plot_IoU ={}

        for plot in ground_truth:

            print(plot)

            #Load polygons
            polys=ground_truth[plot]["data"]

            #read rgb tile
            tile=ground_truth_tiles[plot]
            numpy_image=load_image(tile)

            #Gather detections
            final_boxes=predict_tile(numpy_image,
                                     generator,
                                     model,
                                     score_threshold,
                                     max_detections,
                                     suppression_threshold)

            #Save image and send it to logger
            if save_path is not None:
                draw_detections(numpy_image, final_boxes[:,:4], final_boxes[:,4], final_boxes[:,5], label_to_name=generator.label_to_name,score_threshold=score_threshold)
                cv2.imwrite(os.path.join(save_path, '{}.png'.format(plot)), numpy_image)
                if experiment:              
                    experiment.log_image(os.path.join(save_path, '{}.png'.format(plot)),file_name=str(plot)+"groundtruth")

            #Find overlap 
            projected_boxes=[]

            for row in  final_boxes:

                #Add utm bounds and create a shapely polygon
                pbox=create_polygon(row, ground_truth_utmbox[plot],cell_size=0.1)
                projected_boxes.append(pbox)

            if save_path is not None:
                draw_ground_overlap(plot,ground_truth,ground_truth_tiles,projected_boxes,save_path=save_path,experiment=experiment)

            #Match overlap and generate cost matrix and fill with non-zero elements
            IoU=calculateIoU(ground_truth[plot], projected_boxes)

            plot_IoU[plot]=IoU

        #Mean IoU across all plots
        #Mean IoU across all plots
        all_values=list(plot_IoU.values())
        meanIoU=np.mean(list(chain(*all_values)))
        return meanIoU
Exemplo n.º 11
0
def neonRecall(
    site,
    generator,
    model,
    score_threshold=0.05,
    max_detections=100,
    suppression_threshold=0.2,
    save_path=None,
    experiment=None,
    DeepForest_config = None):

    #load field data
    field_data=pd.read_csv("data/field_data.csv") 
    field_data=field_data[field_data['UTM_E'].notnull()]

    #select site
    site_data=field_data[field_data["siteID"]==site]

    #select tree species
    specieslist=pd.read_csv("data/AcceptedSpecies.csv")
    specieslist =  specieslist[specieslist["siteID"]==site]

    site_data=site_data[site_data["scientificName"].isin(specieslist["scientificName"].values)]

    #Single bole individuals as representitve, no individualID ending in non-digits
    site_data=site_data[site_data["individualID"].str.contains("\d$")]

    #Only data within the last two years, sites can be hand managed
    #site_data=site_data[site_data["eventID"].str.contains("2015|2016|2017|2018")]

    #Get remaining plots
    plots=site_data.plotID.unique()
    
    point_contains=[]
    for plot in plots:

        #select plot
        plot_data=site_data[site_data["plotID"]==plot]

        #load plot image
        tile="data/" + site + "/" + plot + ".tif"
        
        #Check if file exists, if not, skip
        if os.path.exists(tile):
            numpy_image=load_image(tile)
        else:
            continue

        #Gather detections
        final_boxes=predict_tile(numpy_image,generator,model,score_threshold,max_detections,suppression_threshold)            

        #If empty, skip.
        if final_boxes is None:
            continue
    
        #Find geographic bounds
        with rasterio.open(tile) as dataset:
            bounds=dataset.bounds   
    
        #Save image and send it to logger
        if save_path is not None:
            draw_detections(numpy_image, final_boxes[:,:4], final_boxes[:,4], final_boxes[:,5], label_to_name=generator.label_to_name,score_threshold=0.05)
    
            #add points
            x=(plot_data.UTM_E- bounds.left).values/0.1
            y=(bounds.top - plot_data.UTM_N).values/0.1
            for i in np.arange(len(x)):
                cv2.circle(numpy_image,(int(x[i]),int(y[i])), 5, (0,0,255), 1)
    
            cv2.imwrite(os.path.join(save_path, '{}_NeonPlot.png'.format(plot)), numpy_image)
            if experiment:
                experiment.log_image(os.path.join(save_path, '{}_NeonPlot.png'.format(plot)),file_name=str(plot))            
    
        projected_boxes = []
        for row in  final_boxes:
            #Add utm bounds and create a shapely polygon
            pbox=create_polygon(row, bounds,cell_size=0.1)
            projected_boxes.append(pbox)
    
        #for each point
    
        for index,tree in plot_data.iterrows():
            p=Point(tree.UTM_E,tree.UTM_N)
    
            within_polygon=[]
    
            for prediction in projected_boxes:
                within_polygon.append(p.within(prediction))
    
            #Check for overlapping polygon, add it to list
            point_contains.append(sum(within_polygon) > 0)

    if len(point_contains)==0:
        recall=0
    else:
        ## Recall rate for plot
        recall=sum(point_contains)/len(point_contains)

    #Log
    return(recall)