File size: 6,290 Bytes
aa83289
 
 
 
 
 
9e65958
aa83289
19c3c5f
f23cdff
aa83289
 
 
 
19c3c5f
aa83289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import openvino as ov
import gradio as gr
import yaml
import cv2 
import numpy as np
from ultralytics.utils.plotting import colors
core = ov.Core()

model = core.read_model(model = "models/best.xml")
compiled_model = core.compile_model(model = model, device_name = "AUTO")

input_layer = compiled_model.input(0)
output_layer = compiled_model.output(0)

with open('models/metadata.yaml') as info:
    info_dict = yaml.load(info, Loader=yaml.Loader)

labels = info_dict['names']

def prepare_data(image, input_layer):
    input_w, input_h = input_layer.shape[2], input_layer.shape[3]
 
    input_image = cv2.resize(image, (input_w, input_h))
    input_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2RGB)
    input_image = input_image/255
    input_image = input_image.transpose(2,0,1)
    input_image = np.expand_dims(input_image, 0)
 
    return input_image

def evaluate(output, conf_threshold):
    
    boxes = []
    scores = []
    label_key = []
    label_index = 0
    
    for class_ in output[0][4:]:
  
        for index in range (len(class_)):
            confidence = class_[index]

            if  confidence > conf_threshold:

                xcen = output[0][0][index]
                ycen = output[0][1][index]
                w = output[0][2][index]
                h = output[0][3][index]

                xmin = int(xcen - (w/2))
                xmax = int(xcen + (w/2))
                ymin = int(ycen - (h/2))
                ymax = int(ycen + (h/2))

                box = (xmin, ymin, xmax, ymax)
                boxes.append(box)
                scores.append(confidence)

                label_key.append(label_index)
  
        label_index += 1 
        
    boxes = np.array(boxes)
    scores = np.array(scores)
    
    return boxes, scores, label_key

def non_max_suppression(boxes, scores, threshold):	
    assert boxes.shape[0] == scores.shape[0]
    # bottom-left origin
    ys1 = boxes[:, 0]
    xs1 = boxes[:, 1]
    # top-right target
    ys2 = boxes[:, 2]
    xs2 = boxes[:, 3]
    # box coordinate ranges are inclusive-inclusive
    areas = (ys2 - ys1) * (xs2 - xs1)
    scores_indexes = scores.argsort().tolist()
    boxes_keep_index = []
    while len(scores_indexes):
        index = scores_indexes.pop()
        boxes_keep_index.append(index)
        if not len(scores_indexes):
            break
        ious = compute_iou(boxes[index], boxes[scores_indexes], areas[index],
                           areas[scores_indexes])
        filtered_indexes = set((ious > threshold).nonzero()[0])
        # if there are no more scores_index
        # then we should pop it
        scores_indexes = [
            v for (i, v) in enumerate(scores_indexes)
            if i not in filtered_indexes
        ]
    return np.array(boxes_keep_index)


def compute_iou(box, boxes, box_area, boxes_area):
    # this is the iou of the box against all other boxes
    assert boxes.shape[0] == boxes_area.shape[0]
    # get all the origin-ys
    # push up all the lower origin-xs, while keeping the higher origin-xs
    ys1 = np.maximum(box[0], boxes[:, 0])
    # get all the origin-xs
    # push right all the lower origin-xs, while keeping higher origin-xs
    xs1 = np.maximum(box[1], boxes[:, 1])
    # get all the target-ys
    # pull down all the higher target-ys, while keeping lower origin-ys
    ys2 = np.minimum(box[2], boxes[:, 2])
    # get all the target-xs
    # pull left all the higher target-xs, while keeping lower target-xs
    xs2 = np.minimum(box[3], boxes[:, 3])
    # each intersection area is calculated by the
    # pulled target-x minus the pushed origin-x
    # multiplying
    # pulled target-y minus the pushed origin-y
    # we ignore areas where the intersection side would be negative
    # this is done by using maxing the side length by 0
    intersections = np.maximum(ys2 - ys1, 0) * np.maximum(xs2 - xs1, 0)
    # each union is then the box area
    # added to each other box area minusing their intersection calculated above
    unions = box_area + boxes_area - intersections
    # element wise division
    # if the intersection is 0, then their ratio is 0
    ious = intersections / unions
    return ious
    
def visualize(image, nms_output, boxes, label_key,scores, conf_threshold):
    image_h, image_w, c = image.shape
    input_w, input_h = input_layer.shape[2], input_layer.shape[3]

    for i in nms_output:
        xmin, ymin, xmax, ymax = boxes[i]
 
        xmin = int(xmin*image_w/input_w)
        xmax = int(xmax*image_w/input_w)
        ymin = int(ymin*image_h/input_h)
        ymax = int(ymax*image_h/input_h)
 
        label = label_key[i]
        color = colors(label)
        cv2.rectangle(image, (xmin, ymin), (xmax, ymax), color, 1)
        font = cv2.FONT_HERSHEY_SIMPLEX
        text = str(int(scores[i]*100)) + "%" + labels[label]
        font_scale= (image_w/1000)
        label_width, label_height = cv2.getTextSize(text, font,font_scale, 1)[0]
        cv2.rectangle(image, (xmin, ymin-label_height), (xmin + label_width, ymin), color, -1)
        
        cv2.putText(image, text, (xmin+2, ymin), font, font_scale, (255,255,255), 1, cv2.LINE_AA)    
    return image

def predict_image(image, conf_threshold = .4):

    if image is not None: 
        image_RGB = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
        input_image = prepare_data(image_RGB, input_layer)
        output = compiled_model([input_image])[output_layer]
        boxes, scores, label_key = evaluate(output, conf_threshold)
     
        if len(boxes):
            nms_output = non_max_suppression(boxes, scores, conf_threshold)
      
            visualized_image = visualize(image_RGB, nms_output, boxes, label_key,scores, conf_threshold)
            visualized_image = cv2.cvtColor(visualized_image, cv2.COLOR_BGR2RGB)
            return visualized_image
        else:
            return image

image_interface = gr.Interface(
    fn = predict_image,
    inputs = [gr.Image(label="Upload Image"),
              gr.Slider(minimum=0.05, maximum = 1, value = .4, label = "Confidence")
             ],
    outputs = gr.Image(label="Results"),
    title = "AI Kickboard Safety Project", 
    description = "Upload images for Inference on YOLOv8.",
    live = True
)


if __name__=="__main__":
    image_interface.launch(share=True)