-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackend.py
202 lines (181 loc) · 8.28 KB
/
backend.py
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
191
192
193
194
195
196
197
198
199
200
201
import cv2
import numpy as np
class Detection:
classes = []
height, width, channels = 0, 0, 0
img = None
outs = None
grade_object = None
objects_details = None
def __init__(self):
# Load Yolo
self.net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
layer_names = self.net.getLayerNames()
self.output_layers = [layer_names[i[0] - 1] for i in self.net.getUnconnectedOutLayers()]
# load objects names
with open("coco.names", "r") as f:
self.classes = [line.strip() for line in f.readlines()]
# This method is for loading image
def load_image(self, image_path):
# Loading image
self.img = cv2.imread(image_path)
self.img = cv2.resize(self.img, None, fx=0.2, fy=0.2)
self.height, self.width, self.channels = self.img.shape
# This function is for detecting the objects in the image
def detect_objects(self, confidence_level=0.2):
# Detecting objects
blob = cv2.dnn.blobFromImage(self.img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
self.net.setInput(blob)
outs = self.net.forward(self.output_layers)
height, width, channels = self.height, self.width, self.channels
class_ids = []
confidences = []
boxes = []
# out = layer box with some objects
for out in outs:
# detection = single object that was detected
for detection in out:
# make sure we dont detect the same object in different outs
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > confidence_level:
# get object detected details
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
# Rectangle coordinates
x = int(center_x - w / 2)
y = int(center_y - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
return self.draw_detected_object(confidences, class_ids, boxes)
# Showing informations on the screen
def draw_detected_object(self, confidences, class_ids, boxes):
objects_details = []
# Dictionary for counting the number of objects types
grade_object = {
"f_person": 0, #front person
"b_person": 0, # back person
"other_obj": 0 # other objects
}
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
people = []
for i in range(len(boxes)):
if i in indexes:
# is a person
if class_ids[i] == 0:
people.append(boxes[i])
color = [0, 255, 0]
# is not a person
else:
grade_object["other_obj"] = grade_object["other_obj"] + 1
x, y, w, h = boxes[i]
label = str(self.classes[class_ids[i]])
color = [0, 0, 255]
# draw rectangle and put the name of each the object
cv2.rectangle(self.img, (x, y), (x + w, y + h), color, 2)
cv2.putText(self.img, label, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
# put object index number on pic
cv2.putText(self.img, str(len(objects_details)), (x + w, y + h), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
objects_details.append([label, "other_obj", [x, y, w, h], color])
if len(people) > 0:
max_high = np.max(np.array(people)[:, 3])
threshold_person_size_percent = 0.6
# front person
for i in people:
object_type = ""
if i[3] == max_high or i[3] >= max_high * threshold_person_size_percent:
grade_object["f_person"] = grade_object["f_person"] + 1
object_type = "f_person"
color = [0, 255, 0]
# back person
else:
grade_object["b_person"] = grade_object["b_person"] + 1
object_type = "b_person"
color = [255, 0, 0]
x, y, w, h = i
label = str(self.classes[0])
# draw rectangle and put the name of each the object
cv2.rectangle(self.img, (x, y), (x + w, y + h), color, 2)
cv2.putText(self.img, label, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
# put object index number on pic
cv2.putText(self.img, str(len(objects_details)), (x + w, y + h), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
objects_details.append([label, object_type, [x, y, w, h], color])
self.grade_object = grade_object
self.objects_details = objects_details
# ##########################################################################
# cv2.imshow("Image", self.img)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
##########################################################################
return self.img
# This method is for redraw informations on the screen across to user choice
def redraw(self, object_index):
object_type = self.objects_details[object_index][1]
# Update counters on dictionary
if object_type == "f_person":
self.objects_details[object_index][1] = "b_person"
self.objects_details[object_index][3] = [255, 0, 0]
self.grade_object["b_person"] = self.grade_object["b_person"] + 1
self.grade_object["f_person"] = self.grade_object["f_person"] - 1
elif object_type == "b_person" :
self.objects_details[object_index][1] = "f_person"
self.objects_details[object_index][3] = [0, 255, 0]
self.grade_object["f_person"] = self.grade_object["f_person"] + 1
self.grade_object["b_person"] = self.grade_object["b_person"] - 1
elif object_type == "other_obj":
self.objects_details[object_index][1] = "f_person"
self.objects_details[object_index][3] = [0, 255, 0]
self.grade_object["f_person"] = self.grade_object["f_person"] + 1
self.grade_object["other_obj"] = self.grade_object["other_obj"] - 1
# redraw
indx = 0
for i in self.objects_details:
label = i[0]
x, y, w, h = i[2]
color = i[3]
# draw rectangle and put the name of each the object
cv2.rectangle(self.img, (x, y), (x + w, y + h), color, 2)
cv2.putText(self.img, label, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
# put object index number on pic
cv2.putText(self.img, str(indx), (x + w, y + h), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
indx += 1
return self.img
##########################################################################
# cv2.imshow("Image", self.img)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
##########################################################################
# This method is for calculating the grade for the image
def calculate_grade(self):
grade_object = self.grade_object
grade = 100
n_obj = grade_object["other_obj"]
n_f_person = grade_object["f_person"]
n_b_person = grade_object["b_person"]
n = n_obj + n_f_person + n_b_person
# Algorithm
grade = grade - 70*(n_b_person/n) - 30*(n_obj/n)
return grade
# This method return the number of objects that detected
def get_number_of_objects(self):
if self.objects_details:
return len(self.objects_details)
# Tests
# detc = Detection()
# # detc.load_image('bad_grade.jpg')
# # detc.load_image('woman_in_background.jpg')
# detc.load_image('ice_river.jpg')
# detc.detect_objects()
# print(detc.calculate_grade())
#
# detc.redraw(0)
# print(detc.calculate_grade())
# detc.redraw(0)
# print(detc.calculate_grade())
# detc.redraw(0)
# print(detc.calculate_grade())
# print(detc.get_number_of_objects())