Spaces:
Runtime error
Runtime error
| from PIL import Image | |
| import io | |
| import pandas as pd | |
| import numpy as np | |
| import gradio as gr | |
| import cv2 | |
| import requests | |
| import os | |
| from ultralytics import YOLO | |
| from ultralytics.utils.plotting import Annotator, colors | |
| from render import custom_render_result | |
| file_urls = [ | |
| 'https://www.dropbox.com/s/b5g97xo901zb3ds/pothole_example.jpg?dl=1', | |
| 'https://www.dropbox.com/s/86uxlxxlm1iaexa/pothole_screenshot.png?dl=1', | |
| 'https://www.dropbox.com/s/7sjfwncffg8xej2/video_7.mp4?dl=1' | |
| ] | |
| def download_file(url, save_name): | |
| url = url | |
| if not os.path.exists(save_name): | |
| file = requests.get(url) | |
| open(save_name, 'wb').write(file.content) | |
| for i, url in enumerate(file_urls): | |
| if 'mp4' in file_urls[i]: | |
| download_file( | |
| file_urls[i], | |
| f"video.mp4" | |
| ) | |
| else: | |
| download_file( | |
| file_urls[i], | |
| f"image_{i}.jpg" | |
| ) | |
| def get_image_from_bytes(binary_image: bytes) -> Image: | |
| """Convert image from bytes to PIL RGB format | |
| **Args:** | |
| - **binary_image (bytes):** The binary representation of the image | |
| **Returns:** | |
| - **PIL.Image:** The image in PIL RGB format | |
| """ | |
| input_image = Image.open(io.BytesIO(binary_image)).convert("RGB") | |
| return input_image | |
| def get_bytes_from_image(image: Image) -> bytes: | |
| """ | |
| Convert PIL image to Bytes | |
| Args: | |
| image (Image): A PIL image instance | |
| Returns: | |
| bytes : BytesIO object that contains the image in JPEG format with quality 85 | |
| """ | |
| return_image = io.BytesIO() | |
| image.save(return_image, format='JPEG', quality=85) # save the image in JPEG format with quality 85 | |
| return_image.seek(0) # set the pointer to the beginning of the file | |
| return return_image | |
| def transform_predict_to_df(results: list, labeles_dict: dict) -> pd.DataFrame: | |
| """ | |
| Transform predict from yolov8 (torch.Tensor) to pandas DataFrame. | |
| Args: | |
| results (list): A list containing the predict output from yolov8 in the form of a torch.Tensor. | |
| labeles_dict (dict): A dictionary containing the labels names, where the keys are the class ids and the values are the label names. | |
| Returns: | |
| predict_bbox (pd.DataFrame): A DataFrame containing the bounding box coordinates, confidence scores and class labels. | |
| """ | |
| # Transform the Tensor to numpy array | |
| predict_bbox = pd.DataFrame(results[0].to("cpu").numpy().boxes.xyxy, columns=['xmin', 'ymin', 'xmax', 'ymax']) | |
| # Add the confidence of the prediction to the DataFrame | |
| predict_bbox['confidence'] = results[0].to("cpu").numpy().boxes.conf | |
| # Add the class of the prediction to the DataFrame | |
| predict_bbox['class'] = (results[0].to("cpu").numpy().boxes.cls).astype(int) | |
| # Replace the class number with the class name from the labeles_dict | |
| predict_bbox['name'] = predict_bbox["class"].replace(labeles_dict) | |
| return predict_bbox | |
| def get_model_predict(model: YOLO, input_image: Image, save: bool = False, image_size: int = 1248, conf: float = 0.5, | |
| augment: bool = False) -> pd.DataFrame: | |
| """ | |
| Get the predictions of a model on an input image. | |
| Args: | |
| model (YOLO): The trained YOLO model. | |
| input_image (Image): The image on which the model will make predictions. | |
| save (bool, optional): Whether to save the image with the predictions. Defaults to False. | |
| image_size (int, optional): The size of the image the model will receive. Defaults to 1248. | |
| conf (float, optional): The confidence threshold for the predictions. Defaults to 0.5. | |
| augment (bool, optional): Whether to apply data augmentation on the input image. Defaults to False. | |
| Returns: | |
| pd.DataFrame: A DataFrame containing the predictions. | |
| """ | |
| # Make predictions | |
| predictions = model.predict( | |
| imgsz=image_size, | |
| source=input_image, | |
| conf=conf, | |
| save=save, | |
| augment=augment, | |
| flipud=0.0, | |
| fliplr=0.0, | |
| mosaic=0.0, | |
| ) | |
| # Transform predictions to pandas dataframe | |
| predictions = transform_predict_to_df(predictions, model.model.names) | |
| return predictions | |
| def get_model_segment(model: YOLO, input_image: Image, save: bool = False, image_size: int = 1248, conf: float = 0.25, | |
| augment: bool = False) -> pd.DataFrame: | |
| """ | |
| Get the predictions of a model on an input image. | |
| Args: | |
| model (YOLO): The trained YOLO model. | |
| input_image (Image): The image on which the model will make predictions. | |
| save (bool, optional): Whether to save the image with the predictions. Defaults to False. | |
| image_size (int, optional): The size of the image the model will receive. Defaults to 1248. | |
| conf (float, optional): The confidence threshold for the predictions. Defaults to 0.25. | |
| augment (bool, optional): Whether to apply data augmentation on the input image. Defaults to False. | |
| Returns: | |
| pd.DataFrame: A DataFrame containing the predictions. | |
| """ | |
| # Make predictions | |
| predictions = model.predict( | |
| imgsz=image_size, | |
| source=input_image, | |
| conf=conf, | |
| save=save, | |
| augment=augment, | |
| flipud=0.0, | |
| fliplr=0.0, | |
| mosaic=0.0, | |
| ) | |
| # Transform predictions to pandas dataframe | |
| predictions = transform_predict_to_df(predictions, model.model.names) | |
| return predictions | |
| ################################# BBOX Func ##################################### | |
| def add_bboxs_on_img(image: Image, predict: pd.DataFrame()) -> Image: | |
| """ | |
| add a bounding box on the image | |
| Args: | |
| image (Image): input image | |
| predict (pd.DataFrame): predict from model | |
| Returns: | |
| Image: image whis bboxs | |
| """ | |
| # Create an annotator object | |
| annotator = Annotator(np.array(image)) | |
| # sort predict by xmin value | |
| predict = predict.sort_values(by=['xmin'], ascending=True) | |
| # iterate over the rows of predict dataframe | |
| for i, row in predict.iterrows(): | |
| # create the text to be displayed on image | |
| text = f"{row['name']}: {int(row['confidence'] * 100)}%" | |
| # get the bounding box coordinates | |
| bbox = [row['xmin'], row['ymin'], row['xmax'], row['ymax']] | |
| # add the bounding box and text on the image | |
| annotator.box_label(bbox, text, color=colors(row['class'], True)) | |
| # convert the annotated image to PIL image | |
| return Image.fromarray(annotator.result()) | |
| ################################# Models ##################################### | |
| def detect_sample_model(input_image: Image) -> pd.DataFrame: | |
| """ | |
| Predict from sample_model. | |
| Base on YoloV8 | |
| Args: | |
| input_image (Image): The input image. | |
| Returns: | |
| pd.DataFrame: DataFrame containing the object location. | |
| """ | |
| predict = get_model_predict( | |
| model=model_sample_detect, | |
| input_image=input_image, | |
| save=False, | |
| image_size=640, | |
| augment=False, | |
| conf=0.2, | |
| ) | |
| return predict | |
| def yoloV8_func(image: gr.Image = None, | |
| image_size: int = 640, | |
| conf_threshold: float = 0.4, | |
| iou_threshold: float = 0.5, | |
| model_name: str = 'YOLOv8-medium'): | |
| """This function performs YOLOv8 object detection on the given image. | |
| Args: | |
| image (gr.Image, optional): Input image to detect objects on. Defaults to None. | |
| image_size (int, optional): Desired image size for the model. Defaults to 640. | |
| conf_threshold (float, optional): Confidence threshold for object detection. Defaults to 0.4. | |
| iou_threshold (float, optional): Intersection over Union threshold for object detection. Defaults to 0.50. | |
| """ | |
| # Load the YOLOv8 model from the 'best.pt' checkpoint | |
| # model_path = "best.pt" | |
| # model = torch.hub.load('ultralytics/yolov8', 'custom', path='/content/best.pt', force_reload=True, trust_repo=True) | |
| # Perform object detection on the input image using the YOLOv8 model | |
| results = model.predict(image, | |
| conf=conf_threshold, | |
| iou=iou_threshold, | |
| imgsz=image_size) | |
| # Print the detected objects' information (class, coordinates, and probability) | |
| box = results[0].boxes | |
| #print("Object type:", box.cls) | |
| #print("Coordinates:", box.xyxy) | |
| #print("Probability:", box.conf) | |
| # Render the output image with bounding boxes around detected objects | |
| render = custom_render_result(model=model, image=image, result=results[0]) | |
| return render | |
| model = YOLO('best.pt') | |
| path = [['image_tyre.png'], ['image_ladder.png']] | |
| video_path = [['video.mp4']] | |
| outputs_image = gr.components.Image(label="Output Image") | |
| inputs_image= [ | |
| gr.components.Image(label="Input Image"), | |
| gr.Slider(minimum=320, maximum=1280, step=32, label="Image Size", value=640), | |
| gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label="Confidence Threshold",value=0.4, info="Usual value is 0.5"), | |
| gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label="IOU Threshold",value=0.5, info="Usual value greater than 0.2"), | |
| gr.components.Dropdown(["YOLOv8-nano", "YOLOv8-small", "YOLOv8-medium", "YOLOv8-large", "YOLOv8-xlarge"], value="YOLOv8-medium", label="YOLOv8 Model") | |
| ] | |
| interface_image = gr.Interface( | |
| fn=yoloV8_func, | |
| inputs=inputs_image, | |
| outputs=[outputs_image], | |
| title="NonConforming Detector", | |
| examples=path, | |
| cache_examples=False, | |
| ) | |
| def show_preds_video(video_path): | |
| cap = cv2.VideoCapture(video_path) | |
| conf_threshold = 0.4 | |
| iou_threshold = 0.5 | |
| image_size = 640 | |
| while(cap.isOpened()): | |
| ret, frame = cap.read() | |
| if ret: | |
| frame_copy = frame.copy() | |
| results = model.predict(frame, | |
| conf=conf_threshold, | |
| iou=iou_threshold, | |
| imgsz=image_size) | |
| # Print the detected objects' information (class, coordinates, and probability) | |
| box = results[0].boxes | |
| #print("Object type:", box.cls) | |
| #print("Coordinates:", box.xyxy) | |
| #print("Probability:", box.conf) | |
| # Render the output image with bounding boxes around detected objects | |
| render = custom_render_result(model=model, image=frame, result=results[0]) | |
| yield render | |
| """ | |
| outputs = model.predict(source=frame) | |
| results = outputs[0].cpu().numpy() | |
| for i, det in enumerate(results.boxes.xyxy): | |
| cv2.rectangle( | |
| frame_copy, | |
| (int(det[0]), int(det[1])), | |
| (int(det[2]), int(det[3])), | |
| color=(0, 0, 255), | |
| thickness=2, | |
| lineType=cv2.LINE_AA | |
| ) | |
| yield cv2.cvtColor(frame_copy, cv2.COLOR_BGR2RGB) | |
| """ | |
| inputs_video = [ | |
| gr.components.Video(label="Input Video"), | |
| ] | |
| outputs_video = [ | |
| gr.components.Image(label="Output Image"), | |
| ] | |
| interface_video = gr.Interface( | |
| fn=show_preds_video, | |
| inputs=inputs_video, | |
| outputs=outputs_video, | |
| title="NonConforming Video Detector", | |
| examples=video_path, | |
| cache_examples=False, | |
| ) | |
| gr.TabbedInterface( | |
| [interface_image, interface_video], | |
| tab_names=['Image inference', 'Video inference'] | |
| ).queue().launch() | |