def predict_tile(self, raster_path=None, image=None, patch_size=400, patch_overlap=0.05, iou_threshold=0.15, return_plot=False, use_soft_nms=False, sigma=0.5, thresh=0.001): """For images too large to input into the model, predict_tile cuts the image into overlapping windows, predicts trees on each window and reassambles into a single array. Args: raster_path: Path to image on disk image (array): Numpy image array in BGR channel order following openCV convention patch_size: patch size default400, patch_overlap: patch overlap default 0.15, iou_threshold: Minimum iou overlap among predictions between windows to be suppressed. Defaults to 0.5. Lower values suppress more boxes at edges. return_plot: Should the image be returned with the predictions drawn? use_soft_nms: whether to perform Gaussian Soft NMS or not, if false, default perform NMS. sigma: variance of Gaussian function used in Gaussian Soft NMS thresh: the score thresh used to filter bboxes after soft-nms performed Returns: boxes (array): if return_plot, an image. Otherwise a numpy array of predicted bounding boxes, scores and labels """ self.model.eval() result = predict.predict_tile(model=self.model, raster_path=raster_path, image=image, patch_size=patch_size, patch_overlap=patch_overlap, iou_threshold=iou_threshold, return_plot=return_plot, use_soft_nms=use_soft_nms, sigma=sigma, thresh=thresh, device=self.device) #edge case, if no boxes predictioned return None if result is None: print("No predictions made, returning None") return None #Set labels to character from numeric if returning boxes df if not return_plot: result["label"] = result.label.apply( lambda x: self.numeric_to_label_dict[x]) return result
def predict_tile(self, raster_path=None, image=None, patch_size=400, patch_overlap=0.05, iou_threshold=0.15, return_plot=False, mosaic=True, use_soft_nms=False, sigma=0.5, thresh=0.001, color=None, thickness=1): """For images too large to input into the model, predict_tile cuts the image into overlapping windows, predicts trees on each window and reassambles into a single array. Args: raster_path: Path to image on disk image (array): Numpy image array in BGR channel order following openCV convention patch_size: patch size default400, patch_overlap: patch overlap default 0.15, iou_threshold: Minimum iou overlap among predictions between windows to be suppressed. Defaults to 0.5. Lower values suppress more boxes at edges. return_plot: Should the image be returned with the predictions drawn? mosaic: Return a single prediction dataframe (True) or a tuple of image crops and predictions (False) use_soft_nms: whether to perform Gaussian Soft NMS or not, if false, default perform NMS. sigma: variance of Gaussian function used in Gaussian Soft NMS thresh: the score thresh used to filter bboxes after soft-nms performed color: color of the bounding box as a tuple of BGR color, e.g. orange annotations is (0, 165, 255) thickness: thickness of the rectangle border line in px Returns: boxes (array): if return_plot, an image. Otherwise a numpy array of predicted bounding boxes, scores and labels """ # Load on GPU is available if torch.cuda.is_available(): self.model = self.model.to("cuda") self.model.eval() self.model.score_thresh = self.config["score_thresh"] self.model.nms_thresh = self.config["nms_thresh"] result = predict.predict_tile(model=self.model, raster_path=raster_path, image=image, patch_size=patch_size, patch_overlap=patch_overlap, iou_threshold=iou_threshold, return_plot=return_plot, mosaic=mosaic, use_soft_nms=use_soft_nms, sigma=sigma, thresh=thresh, device=self.current_device, color=color, thickness=thickness) #edge case, if no boxes predictioned return None if result is None: print("No predictions made, returning None") return None #Set labels to character from numeric if returning boxes df if not return_plot: if mosaic: result["label"] = result.label.apply(lambda x: self.numeric_to_label_dict[x]) else: for df,image in result: df["label"] = df.label.apply(lambda x: self.numeric_to_label_dict[x]) return result