1
+ from PIL import Image
2
+ import io
3
+ import pandas as pd
4
+ import numpy as np
5
+
6
+ from typing import Optional
7
+
8
+ from ultralytics import YOLO
9
+ from ultralytics .yolo .utils .plotting import Annotator , colors
10
+
11
+
12
+ # Initialize the models
13
+ model_sample_model = YOLO ("./models/sample_model/yolov8n.pt" )
14
+
15
+
16
+ def get_image_from_bytes (binary_image : bytes ) -> Image :
17
+ """Convert image from bytes to PIL RGB format
18
+
19
+ Args:
20
+ binary_image (bytes): The binary representation of the image
21
+
22
+ Returns:
23
+ PIL.Image: The image in PIL RGB format
24
+ """
25
+ input_image = Image .open (io .BytesIO (binary_image )).convert ("RGB" )
26
+ return input_image
27
+
28
+
29
+ def get_bytes_from_image (image : Image ) -> bytes :
30
+ """
31
+ Convert PIL image to Bytes
32
+
33
+ Args:
34
+ image (Image): A PIL image instance
35
+
36
+ Returns:
37
+ bytes : BytesIO object that contains the image in JPEG format with quality 85
38
+ """
39
+ return_image = io .BytesIO ()
40
+ image .save (return_image , format = 'JPEG' , quality = 85 ) # save the image in JPEG format with quality 85
41
+ return_image .seek (0 ) # set the pointer to the beginning of the file
42
+ return return_image
43
+
44
+ def transform_predict_to_df (results : list , labeles_dict : dict ) -> pd .DataFrame :
45
+ """
46
+ Transform predict from yolov8 (torch.Tensor) to pandas DataFrame.
47
+
48
+ Args:
49
+ results (list): A list containing the predict output from yolov8 in the form of a torch.Tensor.
50
+ labeles_dict (dict): A dictionary containing the labels names, where the keys are the class ids and the values are the label names.
51
+
52
+ Returns:
53
+ predict_bbox (pd.DataFrame): A DataFrame containing the bounding box coordinates, confidence scores and class labels.
54
+ """
55
+ # Transform the Tensor to numpy array
56
+ predict_bbox = pd .DataFrame (results [0 ].to ("cpu" ).numpy ().boxes .xyxy , columns = ['xmin' , 'ymin' , 'xmax' ,'ymax' ])
57
+ # Add the confidence of the prediction to the DataFrame
58
+ predict_bbox ['confidence' ] = results [0 ].to ("cpu" ).numpy ().boxes .conf
59
+ # Add the class of the prediction to the DataFrame
60
+ predict_bbox ['class' ] = (results [0 ].to ("cpu" ).numpy ().boxes .cls ).astype (int )
61
+ # Replace the class number with the class name from the labeles_dict
62
+ predict_bbox ['name' ] = predict_bbox ["class" ].replace (labeles_dict )
63
+ return predict_bbox
64
+
65
+ 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 :
66
+ """
67
+ Get the predictions of a model on an input image.
68
+
69
+ Args:
70
+ model (YOLO): The trained YOLO model.
71
+ input_image (Image): The image on which the model will make predictions.
72
+ save (bool, optional): Whether to save the image with the predictions. Defaults to False.
73
+ image_size (int, optional): The size of the image the model will receive. Defaults to 1248.
74
+ conf (float, optional): The confidence threshold for the predictions. Defaults to 0.5.
75
+ augment (bool, optional): Whether to apply data augmentation on the input image. Defaults to False.
76
+
77
+ Returns:
78
+ pd.DataFrame: A DataFrame containing the predictions.
79
+ """
80
+ # Make predictions
81
+ predictions = model .predict (
82
+ imgsz = image_size ,
83
+ source = input_image ,
84
+ conf = conf ,
85
+ save = save ,
86
+ augment = augment ,
87
+ flipud = 0.0 ,
88
+ fliplr = 0.0 ,
89
+ mosaic = 0.0 ,
90
+ )
91
+
92
+ # Transform predictions to pandas dataframe
93
+ predictions = transform_predict_to_df (predictions , model .model .names )
94
+ return predictions
95
+
96
+
97
+ ################################# BBOX Func #####################################
98
+
99
+ def add_bboxs_on_img (image : Image , predict : pd .DataFrame ()) -> Image :
100
+ """
101
+ add a bounding box on the image
102
+
103
+ Args:
104
+ image (Image): input image
105
+ predict (pd.DataFrame): predict from model
106
+
107
+ Returns:
108
+ Image: image whis bboxs
109
+ """
110
+ # Create an annotator object
111
+ annotator = Annotator (np .array (image ))
112
+
113
+ # sort predict by xmin value
114
+ predict = predict .sort_values (by = ['xmin' ], ascending = True )
115
+
116
+ # iterate over the rows of predict dataframe
117
+ for i , row in predict .iterrows ():
118
+ # create the text to be displayed on image
119
+ text = f"{ row ['name' ]} : { int (row ['confidence' ]* 100 )} %"
120
+ # get the bounding box coordinates
121
+ bbox = [row ['xmin' ], row ['ymin' ], row ['xmax' ], row ['ymax' ]]
122
+ # add the bounding box and text on the image
123
+ annotator .box_label (bbox , text , color = colors (row ['class' ], True ))
124
+ # convert the annotated image to PIL image
125
+ return Image .fromarray (annotator .result ())
126
+
127
+
128
+ ################################# Models #####################################
129
+
130
+
131
+ def detect_sample_model (input_image : Image ) -> pd .DataFrame :
132
+ """
133
+ Predict from sample_model.
134
+ Base on YoloV8
135
+
136
+ Args:
137
+ input_image (Image): The input image.
138
+
139
+ Returns:
140
+ pd.DataFrame: DataFrame containing the object location.
141
+ """
142
+ predict = get_model_predict (
143
+ model = model_sample_model ,
144
+ input_image = input_image ,
145
+ save = False ,
146
+ image_size = 640 ,
147
+ augment = False ,
148
+ conf = 0.5 ,
149
+ )
150
+ return predict
0 commit comments