Skip to content

Commit 00f72a3

Browse files
committed
changed approach to use ultralytics YOLO
1 parent 2ade3ba commit 00f72a3

File tree

9 files changed

+59
-134
lines changed

9 files changed

+59
-134
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ venv
55
*.weights
66
*.cfg
77
*.names
8-
yolov3
8+
yolov8
99

1010
output

README.md

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,10 @@ source venv/bin/activate
1515
pip3 install -r requirements.txt
1616
```
1717

18-
3. Download YOLOv3 weights and configuration
18+
3. Run the app
1919

2020
```bash
21-
chmod +x get_yolov3.sh
22-
./get_yolov3.sh
23-
```
24-
25-
4. Run the app
26-
27-
```bash
28-
python3 src/app.py -i <image> -c yolov3/yolov3.cfg -w yolov3/yolov3.weights -cl yolov3/coco.names
29-
```
30-
or
31-
```bash
32-
./run.sh <image>
21+
python3 src/app.py
3322
```
3423

3524
## Architecture Diagram

get_yolov3.sh

Lines changed: 0 additions & 7 deletions
This file was deleted.

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
numpy==1.26.4
21
opencv-python==4.9.0.80
2+
ultralytics==8.2.10

run.sh

Lines changed: 0 additions & 5 deletions
This file was deleted.
-483 Bytes
Binary file not shown.

src/app.py

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,16 @@
1-
import cv2
2-
import argparse
3-
import numpy as np
41
import os
52

6-
from detection import Detector
3+
# Set YOLOv8 to quiet mode
4+
os.environ['YOLO_VERBOSE'] = 'False'
75

8-
classes = None
9-
COLORS = None
6+
from detection import Detector
107

11-
BASE_DIR = os.path.dirname(os.path.abspath(__name__))
8+
def callback(people):
9+
print(f"People detected: {people}")
1210

1311
def main():
14-
# handle command line arguments
15-
ap = argparse.ArgumentParser()
16-
ap.add_argument('-i', '--image', required=True,
17-
help = 'path to input image')
18-
ap.add_argument('-c', '--config', required=True,
19-
help = 'path to yolo config file')
20-
ap.add_argument('-w', '--weights', required=True,
21-
help = 'path to yolo pre-trained weights')
22-
ap.add_argument('-cl', '--classes', required=True,
23-
help = 'path to text file containing class names')
24-
args = ap.parse_args()
25-
26-
detector = Detector(args.config, args.weights, args.classes)
27-
28-
image = cv2.imread(args.image)
29-
image = detector.detect(image)
30-
31-
output_dir = os.path.join(BASE_DIR, "output")
32-
if not os.path.exists(output_dir):
33-
os.makedirs(output_dir)
34-
35-
num_files = len(os.listdir(output_dir))
36-
detector.export(image, f"{output_dir}/output{num_files}.jpg")
37-
38-
detector.show(image)
39-
12+
detector = Detector()
13+
detector.stream(callback, show=True)
4014

4115
if __name__ == "__main__":
4216
main()

src/camera.py

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/detection.py

Lines changed: 48 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,55 @@
11
import cv2
2-
import numpy as np
2+
from ultralytics import YOLO
33

44
class Detector:
5-
def __init__(self, config, weights, classes):
6-
self.net = cv2.dnn.readNet(weights, config)
7-
self.output_layers = self.net.getUnconnectedOutLayersNames()
8-
self.scale = 0.00392
9-
self.conf_threshold = 0.5
10-
self.nms_threshold = 0.4
11-
12-
with open(classes, 'r') as f:
13-
self.classes = [line.strip() for line in f.readlines()]
14-
15-
self.colors = np.random.uniform(0, 255, size=(len(self.classes), 3))
16-
17-
def detect(self, image):
18-
H, W, _ = image.shape
19-
blob = cv2.dnn.blobFromImage(image, self.scale, (416,416), (0,0,0), True, crop=False)
20-
self.net.setInput(blob)
21-
outs = self.net.forward(self.output_layers)
22-
23-
class_ids = []
24-
confidences = []
25-
boxes = []
26-
27-
for out in outs:
28-
for detection in out:
29-
scores = detection[5:]
30-
class_id = np.argmax(scores)
31-
confidence = scores[class_id]
32-
if confidence > self.conf_threshold:
33-
center_x = int(detection[0] * W)
34-
center_y = int(detection[1] * H)
35-
w = int(detection[2] * W)
36-
h = int(detection[3] * H)
37-
x = center_x - w / 2
38-
y = center_y - h / 2
39-
class_ids.append(class_id)
40-
confidences.append(float(confidence))
41-
boxes.append([x, y, w, h])
42-
43-
indices = cv2.dnn.NMSBoxes(boxes, confidences, self.conf_threshold, self.nms_threshold)
44-
45-
for i in indices:
46-
box = boxes[i]
47-
x = box[0]
48-
y = box[1]
49-
w = box[2]
50-
h = box[3]
51-
52-
self.draw_bounding_box(image, class_ids[i], round(x), round(y), round(x+w), round(y+h))
5+
def __init__(self):
6+
self.classNames = ["person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat",
7+
"traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat",
8+
"dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella",
9+
"handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
10+
"baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup",
11+
"fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli",
12+
"carrot", "hot dog", "pizza", "donut", "cake", "chair", "sofa", "pottedplant", "bed",
13+
"diningtable", "toilet", "tvmonitor", "laptop", "mouse", "remote", "keyboard", "cell phone",
14+
"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors",
15+
"teddy bear", "hair drier", "toothbrush"
16+
]
17+
self.model = YOLO("yolov8/yolov8n.pt", verbose=False)
18+
self.people = 0
19+
5320

54-
return image
21+
def stream(self, callback, show=True):
22+
cap = cv2.VideoCapture(0)
23+
cap.set(3, 640)
24+
cap.set(4, 480)
25+
26+
while True:
27+
ret, frame = cap.read()
28+
if not ret:
29+
break
30+
31+
results = self.model(frame, stream=True)
32+
self.people = 0
33+
for result in results:
34+
boxes = result.boxes
35+
for box in boxes:
36+
cls = int(box.cls[0])
37+
if self.classNames[cls] == "person":
38+
self.people += 1
39+
40+
if show and self.classNames[cls] == "person":
41+
x, y, w, h = box.xyxy[0]
42+
x, y, w, h = int(x), int(y), int(w), int(h)
43+
cv2.rectangle(frame, (x, y), (w, h), (0, 255, 0), 2)
44+
45+
cv2.putText(frame, self.classNames[cls], (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)
5546

56-
def draw_bounding_box(self, img, class_id, x, y, x_plus_w, y_plus_h):
57-
label = str(self.classes[class_id])
58-
color = self.colors[class_id]
59-
cv2.rectangle(img, (x,y), (x_plus_w,y_plus_h), color, 2)
60-
cv2.putText(img, label, (x-10,y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
47+
callback(self.people)
6148

62-
def show(self, image):
63-
cv2.imshow('Object Detection', image)
64-
cv2.waitKey(0)
65-
cv2.destroyAllWindows()
49+
if show:
50+
cv2.imshow("Frame", frame)
51+
if cv2.waitKey(1) & 0xFF == ord("q"):
52+
break
6653

67-
def export(self, image, path):
68-
cv2.imwrite(path, image)
54+
cap.release()
55+
cv2.destroyAllWindows()

0 commit comments

Comments
 (0)