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
|
- import argparse
- import cv2.dnn
- import numpy as np
- from ultralytics.utils import ASSETS, yaml_load
- from ultralytics.utils.checks import check_yaml
- CLASSES = yaml_load(check_yaml('coco128.yaml'))['names']
- colors = np.random.uniform(0, 255, size=(len(CLASSES), 3))
- def draw_bounding_box(img, class_id, confidence, x, y, x_plus_w, y_plus_h):
- """
- Draws bounding boxes on the input image based on the provided arguments.
- Args:
- img (numpy.ndarray): The input image to draw the bounding box on.
- class_id (int): Class ID of the detected object.
- confidence (float): Confidence score of the detected object.
- x (int): X-coordinate of the top-left corner of the bounding box.
- y (int): Y-coordinate of the top-left corner of the bounding box.
- x_plus_w (int): X-coordinate of the bottom-right corner of the bounding box.
- y_plus_h (int): Y-coordinate of the bottom-right corner of the bounding box.
- """
- label = f'{CLASSES[class_id]} ({confidence:.2f})'
- color = colors[class_id]
- cv2.rectangle(img, (x, y), (x_plus_w, y_plus_h), color, 2)
- cv2.putText(img, label, (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
- def main(onnx_model, input_image):
- """
- Main function to load ONNX model, perform inference, draw bounding boxes, and display the output image.
- Args:
- onnx_model (str): Path to the ONNX model.
- input_image (str): Path to the input image.
- Returns:
- list: List of dictionaries containing detection information such as class_id, class_name, confidence, etc.
- """
- # Load the ONNX model
- model: cv2.dnn.Net = cv2.dnn.readNetFromONNX(onnx_model)
- # Read the input image
- original_image: np.ndarray = cv2.imread(input_image)
- [height, width, _] = original_image.shape
- # Prepare a square image for inference
- length = max((height, width))
- image = np.zeros((length, length, 3), np.uint8)
- image[0:height, 0:width] = original_image
- # Calculate scale factor
- scale = length / 640
- # Preprocess the image and prepare blob for model
- blob = cv2.dnn.blobFromImage(image, scalefactor=1 / 255, size=(640, 640), swapRB=True)
- model.setInput(blob)
- # Perform inference
- outputs = model.forward()
- # Prepare output array
- outputs = np.array([cv2.transpose(outputs[0])])
- rows = outputs.shape[1]
- boxes = []
- scores = []
- class_ids = []
- # Iterate through output to collect bounding boxes, confidence scores, and class IDs
- for i in range(rows):
- classes_scores = outputs[0][i][4:]
- (minScore, maxScore, minClassLoc, (x, maxClassIndex)) = cv2.minMaxLoc(classes_scores)
- if maxScore >= 0.25:
- box = [
- outputs[0][i][0] - (0.5 * outputs[0][i][2]), outputs[0][i][1] - (0.5 * outputs[0][i][3]),
- outputs[0][i][2], outputs[0][i][3]]
- boxes.append(box)
- scores.append(maxScore)
- class_ids.append(maxClassIndex)
- # Apply NMS (Non-maximum suppression)
- result_boxes = cv2.dnn.NMSBoxes(boxes, scores, 0.25, 0.45, 0.5)
- detections = []
- # Iterate through NMS results to draw bounding boxes and labels
- for i in range(len(result_boxes)):
- index = result_boxes[i]
- box = boxes[index]
- detection = {
- 'class_id': class_ids[index],
- 'class_name': CLASSES[class_ids[index]],
- 'confidence': scores[index],
- 'box': box,
- 'scale': scale}
- detections.append(detection)
- draw_bounding_box(original_image, class_ids[index], scores[index], round(box[0] * scale), round(box[1] * scale),
- round((box[0] + box[2]) * scale), round((box[1] + box[3]) * scale))
- # Display the image with bounding boxes
- cv2.imshow('image', original_image)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
- return detections
- if __name__ == '__main__':
- parser = argparse.ArgumentParser()
- parser.add_argument('--model', default='yolov8n.onnx', help='Input your ONNX model.')
- parser.add_argument('--img', default=str(ASSETS / 'bus.jpg'), help='Path to input image.')
- args = parser.parse_args()
- main(args.model, args.img)
|