Lane and Object Detection
Using OpenCV and YOLOv7
Loading...
Searching...
No Matches
ObjectDetector.cpp
1#include <cfloat>
2#include <cstdint>
3#include <format>
4#include <string>
5#include <vector>
6
7#include <opencv2/core.hpp>
8#include <opencv2/core/mat.hpp>
9#include <opencv2/core/types.hpp>
10#include <opencv2/dnn/dnn.hpp>
11
12#include "helpers/Globals.hpp"
13
14#include "detectors/ObjectDetector.hpp"
15
17{
22
23 void ObjectDetector::SetProperties(const std::string& p_yoloFolderPath,
24 const Globals::ObjectDetectorTypes& p_objectDetectorTypes,
25 const Globals::ObjectDetectorBackEnds& p_objectDetectorBackEnds,
26 const Globals::ObjectDetectorBlobSizes& p_objectDetectorBlobSizes)
27 {
28 switch (p_objectDetectorTypes)
29 {
30 case Globals::ObjectDetectorTypes::NONE:
32 break;
33
34 case Globals::ObjectDetectorTypes::STANDARD:
36 m_net = cv::dnn::readNetFromDarknet(p_yoloFolderPath + "yolov7.cfg", p_yoloFolderPath + "yolov7.weights");
37 break;
38
39 case Globals::ObjectDetectorTypes::TINY:
41 m_net = cv::dnn::readNetFromDarknet(p_yoloFolderPath + "yolov7-tiny.cfg", p_yoloFolderPath + "yolov7-tiny.weights");
42 break;
43
44 default:
46 }
47
48 switch (p_objectDetectorBackEnds)
49 {
50 case Globals::ObjectDetectorBackEnds::NONE:
51 break;
52 case Globals::ObjectDetectorBackEnds::CPU:
53 m_net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
54 m_net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
55 break;
56
57 case Globals::ObjectDetectorBackEnds::GPU:
58 m_net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
59 m_net.setPreferableTarget(cv::dnn::DNN_TARGET_OPENCL);
60 break;
61
62 case Globals::ObjectDetectorBackEnds::CUDA:
63 m_net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
64 m_net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
65 break;
66
67 default:
69 }
70
71 m_blobSize = static_cast<int32_t>(p_objectDetectorBlobSizes);
72
73 m_unconnectedOutputLayerNames = m_net.getUnconnectedOutLayersNames();
74
75 m_objectDetectionInformation.m_objectInformation.clear();
76 }
77
78 void ObjectDetector::RunObjectDetector(const cv::Mat& p_frame)
79 {
81 {
82 return;
83 }
84
85 m_objectDetectionInformation.m_objectInformation.clear();
86
87 // Get output blobs from the frame
88 std::vector<cv::Mat> outputBlobs;
89 const cv::Mat BLOB_FROM_IMAGE = cv::dnn::blobFromImage(p_frame, Globals::G_OBJECT_DETECTOR_SCALE_FACTOR, cv::Size(m_blobSize, m_blobSize), Globals::G_COLOUR_BLACK);
90 m_net.setInput(BLOB_FROM_IMAGE);
91 m_net.forward(outputBlobs, m_unconnectedOutputLayerNames);
92
93 // Go through all output blobs and only allow those with confidence above threshold
94 std::vector<std::string> initialObjectNames;
95 std::vector<cv::Rect> initialObjectBoundingBoxes;
96 std::vector<float> initialObjectConfidences;
97 cv::Point maxConfidenceObjectIndex;
98 double maxConfidence = -DBL_MAX;
99
100 for (auto& outputBlob : outputBlobs)
101 {
102 for (int32_t rowIndex = 0; rowIndex < outputBlob.rows; rowIndex++)
103 {
104 // Each row is structured as the following [cx, cy, w, h, box score, object 1 score, object 2 score, ..., object n score]
105
106 // minMaxLoc returns the object index that has the maximum confidence as well as the maximum confidence
107 cv::minMaxLoc(outputBlob.row(rowIndex).colRange(Globals::G_OBJECT_DETECTOR_OUTPUT_BLOBS_OBJECT_SCORES_START_INDEX, outputBlob.cols), nullptr, &maxConfidence, nullptr, &maxConfidenceObjectIndex);
108
110 {
111 const double CENTER_X = outputBlob.at<float>(rowIndex, Globals::G_OBJECT_DETECTOR_OUTPUT_BLOBS_CENTER_X_COORD_INDEX) * Globals::G_VIDEO_INPUT_WIDTH;
112 const double CENTER_Y = outputBlob.at<float>(rowIndex, Globals::G_OBJECT_DETECTOR_OUTPUT_BLOBS_CENTER_Y_COORD_INDEX) * Globals::G_VIDEO_INPUT_HEIGHT;
115
116 // Remove object detections on the hood of car
117 if (CENTER_Y < Globals::G_ROI_BOTTOM_HEIGHT)
118 {
119 initialObjectNames.push_back(Globals::G_OBJECT_DETECTOR_OBJECT_NAMES.at(maxConfidenceObjectIndex.x));
120 initialObjectBoundingBoxes.emplace_back(CENTER_X - (WIDTH / Globals::G_DIVIDE_BY_TWO), CENTER_Y - (HEIGHT / Globals::G_DIVIDE_BY_TWO), WIDTH, HEIGHT);
121 initialObjectConfidences.push_back(static_cast<float>(maxConfidence));
122 }
123 }
124 }
125 }
126
127 // Apply non-maxima suppression to suppress overlapping bounding boxes for objects that overlap, the highest confidence object will be chosen
128 std::vector<int> nonMaximaSuppressedFilteredIndicies;
129
130 cv::dnn::NMSBoxes(initialObjectBoundingBoxes, initialObjectConfidences, 0.0, static_cast<float>(Globals::G_OBJECT_DETECTOR_NMS_THRESHOLD), nonMaximaSuppressedFilteredIndicies);
131
132 for (const int32_t& index : nonMaximaSuppressedFilteredIndicies)
133 {
134 m_objectDetectionInformation.m_objectInformation.push_back({.m_boundingBox = initialObjectBoundingBoxes.at(index),
135 .m_boundingBoxColour = Globals::G_OBJECT_DETECTOR_OBJECT_NAMES_AND_COLOURS.at(initialObjectNames.at(index)),
136 .m_objectName = std::format("{} ({} %)", initialObjectNames.at(index), std::to_string(static_cast<uint32_t>(initialObjectConfidences.at(index) * Globals::G_CONVERT_DECIMAL_TO_PERCENTAGE)))});
137 }
138 }
139
144}
Used for functionality that has not been implemented.
Definition Globals.hpp:32
ObjectDetectionInformation m_objectDetectionInformation
The ObjectDetectionInformation struct containing all object detection-related information.
cv::dnn::Net m_net
OpenCV object which allows the use of pre-trained neural networks.
std::vector< std::string > m_unconnectedOutputLayerNames
The names of layers with unconnected outputs.
void SetProperties(const std::string &p_yoloFolderPath, const Globals::ObjectDetectorTypes &p_objectDetectorTypes, const Globals::ObjectDetectorBackEnds &p_objectDetectorBackEnds, const Globals::ObjectDetectorBlobSizes &p_objectDetectorBlobSizes)
Set the properties of the ObjectDetector object.
int32_t m_blobSize
The spatial size for the output image used by the cv::dnn::blobFromImage function.
ObjectDetector()
Construct a new ObjectDetector object.
void RunObjectDetector(const cv::Mat &p_frame)
Run the object detector against p_frame.
bool m_skipObjectDetection
Whether to skip object detection.
ObjectDetectionInformation GetInformation()
Get the ObjectDetectionInformation struct.
static const cv::Scalar G_COLOUR_BLACK
OpenCV Colours (in BGR format).
Definition Globals.hpp:145
static const int32_t G_OBJECT_DETECTOR_OUTPUT_BLOBS_CENTER_Y_COORD_INDEX
The indicies representing various values in the output blobs.
Definition Globals.hpp:505
static const uint32_t G_OBJECT_DETECTOR_BOUNDING_BOX_BUFFER
Object detection bounding box properties.
Definition Globals.hpp:492
static const uint32_t G_VIDEO_INPUT_HEIGHT
Input video dimensions.
Definition Globals.hpp:103
static const uint32_t G_VIDEO_INPUT_WIDTH
Input video dimensions.
Definition Globals.hpp:104
static const double G_OBJECT_DETECTOR_CONFIDENCE_THRESHOLD
Object detection threshold and properties.
Definition Globals.hpp:484
static const double G_OBJECT_DETECTOR_NMS_THRESHOLD
Object detection threshold and properties.
Definition Globals.hpp:485
static const double G_DIVIDE_BY_TWO
Divide by two.
Definition Globals.hpp:176
static const int32_t G_OBJECT_DETECTOR_OUTPUT_BLOBS_HEIGHT_INDEX
The indicies representing various values in the output blobs.
Definition Globals.hpp:507
static const std::array< std::string, G_OBJECT_DETECTOR_NUMBER_OF_DETECTABLE_OBJECTS > G_OBJECT_DETECTOR_OBJECT_NAMES
Names of detectable objects. The order is significant and should not be changed.
Definition Globals.hpp:516
static const int32_t G_ROI_BOTTOM_HEIGHT
Region-of-interest dimensions.
Definition Globals.hpp:267
ObjectDetectorTypes
The type of object detector to use with an option to disable object detection. The tiny version is mo...
Definition Globals.hpp:446
static const int32_t G_OBJECT_DETECTOR_OUTPUT_BLOBS_OBJECT_SCORES_START_INDEX
The indicies representing various values in the output blobs.
Definition Globals.hpp:508
ObjectDetectorBackEnds
The supported backends for the object detector to run on. In theory, GPU should be significantly more...
Definition Globals.hpp:458
static const int32_t G_OBJECT_DETECTOR_OUTPUT_BLOBS_CENTER_X_COORD_INDEX
The indicies representing various values in the output blobs.
Definition Globals.hpp:504
static const std::map< std::string, cv::Scalar > G_OBJECT_DETECTOR_OBJECT_NAMES_AND_COLOURS
Object names and bounding box colours. G_OPENCV_WHITE is used as the default colour while custom colo...
Definition Globals.hpp:604
static const double G_OBJECT_DETECTOR_SCALE_FACTOR
Object detection threshold and properties.
Definition Globals.hpp:483
static const int32_t G_OBJECT_DETECTOR_OUTPUT_BLOBS_WIDTH_INDEX
The indicies representing various values in the output blobs.
Definition Globals.hpp:506
ObjectDetectorBlobSizes
The supported blob sizes for the object detector to run with. The larger the blob size the more perfo...
Definition Globals.hpp:470
static const uint32_t G_CONVERT_DECIMAL_TO_PERCENTAGE
Convert a decimal value to a percentage.
Definition Globals.hpp:171
Contains all Lane-and-Object-Detection objects.
The information needed by FrameBuilder to update frame with object detection information.