Lane and Object Detection
Using OpenCV and YOLOv7
Loading...
Searching...
No Matches
VideoManager.cpp
1#include <chrono>
2#include <cstdint>
3#include <cstdlib>
4#include <format>
5#include <iostream>
6#include <string>
7#include <vector>
8
9#include <opencv2/core/types.hpp>
10#include <opencv2/highgui.hpp>
11#include <opencv2/videoio.hpp>
12
13#include "detectors/LaneDetector.hpp"
14#include "detectors/ObjectDetector.hpp"
15#include "helpers/FrameBuilder.hpp"
16#include "helpers/Globals.hpp"
17#include "helpers/Information.hpp"
18#include "helpers/Performance.hpp"
19
20#include "helpers/VideoManager.hpp"
21
23{
31
32 VideoManager::VideoManager(const int32_t& p_inputVideoCamera,
33 const std::string& p_yoloFolderPath,
34 const Globals::ObjectDetectorTypes& p_objectDetectorTypes,
35 const Globals::ObjectDetectorBackEnds& p_objectDetectorBackEnds,
36 const Globals::ObjectDetectorBlobSizes& p_objectDetectorBlobSizes)
37 {
40 m_videoManagerInformation.m_debugMode = false;
41 m_videoManagerInformation.m_saveOutput = false;
42
43 SetProperties(p_inputVideoCamera, p_yoloFolderPath, p_objectDetectorTypes, p_objectDetectorBackEnds, p_objectDetectorBlobSizes);
44 }
45
46 VideoManager::VideoManager(const std::string& p_inputVideoFilePath,
47 const std::string& p_yoloFolderPath,
48 const Globals::ObjectDetectorTypes& p_objectDetectorTypes,
49 const Globals::ObjectDetectorBackEnds& p_objectDetectorBackEnds,
50 const Globals::ObjectDetectorBlobSizes& p_objectDetectorBlobSizes)
51 {
54 m_videoManagerInformation.m_debugMode = false;
55 m_videoManagerInformation.m_saveOutput = false;
56
57 SetProperties(p_inputVideoFilePath, p_yoloFolderPath, p_objectDetectorTypes, p_objectDetectorBackEnds, p_objectDetectorBlobSizes);
58 }
59
60 VideoManager::VideoManager(const std::vector<std::string>& p_commandLineArguments) // NOLINT(readability-function-cognitive-complexity)
61 {
64 m_videoManagerInformation.m_debugMode = false;
65 m_videoManagerInformation.m_saveOutput = false;
66
67 std::string parsedInputVideoFilePath;
68 std::string parsedYoloFolderPath;
69 Globals::ObjectDetectorTypes parsedObjectDetectorTypes = Globals::ObjectDetectorTypes::NONE;
70 Globals::ObjectDetectorBackEnds parsedObjectDetectorBackEnds = Globals::ObjectDetectorBackEnds::NONE;
71 Globals::ObjectDetectorBlobSizes parsedObjectDetectorBlobSizes = Globals::ObjectDetectorBlobSizes::NONE;
72
73 uint32_t index = 0;
74
75 for (const std::string& argument : p_commandLineArguments)
76 {
77 if (argument == "-h" || argument == "--help")
78 {
79 std::cout << Globals::G_CLI_HELP_MESSAGE;
80 std::exit(1);
81 }
82
83 try
84 {
85 if (argument == "-i" || argument == "--input")
86 {
87 parsedInputVideoFilePath = p_commandLineArguments.at(index + 1);
88 }
89
90 if (argument == "-y" || argument == "--yolo-folder-path")
91 {
92 parsedYoloFolderPath = p_commandLineArguments.at(index + 1);
93 }
94
95 if (argument == "-o" || argument == "--object-detector-type")
96 {
97 if (p_commandLineArguments.at(index + 1) == "none")
98 {
99 parsedObjectDetectorTypes = Globals::ObjectDetectorTypes::NONE;
100 }
101
102 else if (p_commandLineArguments.at(index + 1) == "standard")
103 {
104 parsedObjectDetectorTypes = Globals::ObjectDetectorTypes::STANDARD;
105 }
106
107 else if (p_commandLineArguments.at(index + 1) == "tiny")
108 {
109 parsedObjectDetectorTypes = Globals::ObjectDetectorTypes::TINY;
110 }
111
112 else
113 {
114 std::cout << Globals::G_CLI_HELP_MESSAGE;
115 std::exit(1);
116 }
117 }
118
119 if (argument == "-b" || argument == "--object-detector-backend")
120 {
121 if (p_commandLineArguments.at(index + 1) == "cpu")
122 {
123 parsedObjectDetectorBackEnds = Globals::ObjectDetectorBackEnds::CPU;
124 }
125
126 else if (p_commandLineArguments.at(index + 1) == "gpu")
127 {
128 parsedObjectDetectorBackEnds = Globals::ObjectDetectorBackEnds::GPU;
129 }
130
131 else if (p_commandLineArguments.at(index + 1) == "cuda")
132 {
133 parsedObjectDetectorBackEnds = Globals::ObjectDetectorBackEnds::CUDA;
134 }
135
136 else
137 {
138 std::cout << Globals::G_CLI_HELP_MESSAGE;
139 std::exit(1);
140 }
141 }
142
143 if (argument == "-s" || argument == "--object-detector-blob-size")
144 {
145 parsedObjectDetectorBlobSizes = static_cast<Globals::ObjectDetectorBlobSizes>(std::stoi(p_commandLineArguments.at(index + 1)));
146 }
147 }
148
149 catch (...)
150 {
151 std::cout << Globals::G_CLI_HELP_MESSAGE;
152 std::exit(1);
153 }
154
155 index++;
156 }
157
158 // Check that the required arguments have been provided
159 if (parsedInputVideoFilePath.empty() ||
160 parsedYoloFolderPath.empty() ||
161 (parsedObjectDetectorTypes != Globals::ObjectDetectorTypes::NONE && (parsedObjectDetectorBackEnds == Globals::ObjectDetectorBackEnds::NONE || parsedObjectDetectorBlobSizes == Globals::ObjectDetectorBlobSizes::NONE)))
162 {
163 std::cout << Globals::G_CLI_HELP_MESSAGE;
164 std::exit(1);
165 }
166
167 SetProperties(parsedInputVideoFilePath, parsedYoloFolderPath, parsedObjectDetectorTypes, parsedObjectDetectorBackEnds, parsedObjectDetectorBlobSizes);
168 }
169
171 {
172 Quit();
173 }
174
175 void VideoManager::SetProperties(const int32_t& p_inputVideoCamera,
176 const std::string& p_yoloFolderPath,
177 const Globals::ObjectDetectorTypes& p_objectDetectorTypes,
178 const Globals::ObjectDetectorBackEnds& p_objectDetectorBackEnds,
179 const Globals::ObjectDetectorBlobSizes& p_objectDetectorBlobSizes)
180 {
181 m_inputVideo.open(p_inputVideoCamera);
182
183 if (!m_inputVideo.isOpened())
184 {
185 std::cout << "\nERROR: Input video camera '" + std::to_string(p_inputVideoCamera) + "' cannot be found!\n";
186 std::exit(1);
187 }
188
189 m_inputVideo.set(cv::CAP_PROP_FRAME_WIDTH, Globals::G_VIDEO_INPUT_WIDTH);
190 m_inputVideo.set(cv::CAP_PROP_FRAME_HEIGHT, Globals::G_VIDEO_INPUT_HEIGHT);
191
192 if (m_videoManagerInformation.m_saveOutput)
193 {
195 }
196
197 m_objectDetector.SetProperties(p_yoloFolderPath, p_objectDetectorTypes, p_objectDetectorBackEnds, p_objectDetectorBlobSizes);
198
199 m_performance.ClearPerformanceInformation();
200 }
201
202 void VideoManager::SetProperties(const std::string& p_inputVideoFilePath,
203 const std::string& p_yoloFolderPath,
204 const Globals::ObjectDetectorTypes& p_objectDetectorTypes,
205 const Globals::ObjectDetectorBackEnds& p_objectDetectorBackEnds,
206 const Globals::ObjectDetectorBlobSizes& p_objectDetectorBlobSizes)
207 {
208 m_inputVideo.open(p_inputVideoFilePath);
209
210 if (!m_inputVideo.isOpened())
211 {
212 std::cout << "\nERROR: Input video file path '" + p_inputVideoFilePath + "' cannot be found!\n";
213 std::exit(1);
214 }
215
216 m_inputVideo.set(cv::CAP_PROP_FRAME_WIDTH, Globals::G_VIDEO_INPUT_WIDTH);
217 m_inputVideo.set(cv::CAP_PROP_FRAME_HEIGHT, Globals::G_VIDEO_INPUT_HEIGHT);
218
219 if (m_videoManagerInformation.m_saveOutput)
220 {
222 }
223
224 m_objectDetector.SetProperties(p_yoloFolderPath, p_objectDetectorTypes, p_objectDetectorBackEnds, p_objectDetectorBlobSizes);
225
226 m_performance.ClearPerformanceInformation();
227 }
228
230 {
231 while (true)
232 {
233 m_performance.StartTimer();
234
235 if (!m_inputVideo.read(m_currentFrame))
236 {
237 break;
238 }
239
240 m_objectDetector.RunObjectDetector(m_currentFrame);
241
242 m_laneDetector.RunLaneDetector(m_currentFrame, m_objectDetector.GetInformation(), m_videoManagerInformation.m_debugMode);
243
245
246 if (m_videoManagerInformation.m_saveOutput)
247 {
250 }
251
252 cv::imshow("currentFrame", m_currentFrame);
253
254 if (m_videoManagerInformation.m_debugMode)
255 {
256 cv::imshow("roiFrame", m_laneDetector.GetInformation().m_roiFrame);
257 cv::imshow("cannyFrame", m_laneDetector.GetInformation().m_cannyFrame);
258 cv::imshow("houghLinesFrame", m_laneDetector.GetInformation().m_houghLinesFrame);
259 }
260
261 switch (cv::waitKey(1))
262 {
265 break;
266
269 break;
270
272 Quit();
273 return;
274
275 default:
276 break;
277 }
278
279 m_performance.EndTimer();
280 }
281 }
282
287
289 {
290 m_videoManagerInformation.m_debugMode = !m_videoManagerInformation.m_debugMode;
292
293 if (!m_videoManagerInformation.m_debugMode)
294 {
295 cv::destroyWindow("roiFrame");
296 cv::destroyWindow("cannyFrame");
297 cv::destroyWindow("houghLinesFrame");
298 }
299 }
300
302 {
303 m_videoManagerInformation.m_saveOutput = !m_videoManagerInformation.m_saveOutput;
304
305 if (m_videoManagerInformation.m_saveOutput)
306 {
307 m_saveOutputStartTime = std::chrono::high_resolution_clock::now();
308
309 const std::string OUTPUT_FILE_NAME = std::format("{:%Y-%m-%d-%H-%M-%S}-output.mp4", std::chrono::system_clock::now());
310
311 m_outputVideo.open(OUTPUT_FILE_NAME,
312 cv::VideoWriter::fourcc('m', 'p', '4', 'v'),
315
316 if (!m_outputVideo.isOpened())
317 {
318 std::cout << std::format("\nERROR: Output video file '{}' could not be opened! Recording stopped!\n", OUTPUT_FILE_NAME);
319 m_videoManagerInformation.m_saveOutput = false;
320 }
321
322 else
323 {
325 }
326 }
327
328 else
329 {
330 m_outputVideo.release();
332 }
333 }
334
336 {
337 m_inputVideo.release();
338 m_outputVideo.release();
339 cv::destroyAllWindows();
340 }
341}
static void UpdateFrame(cv::Mat &p_frame, const ObjectDetectionInformation &p_objectDetectionInformation, const LaneDetectionInformation &p_laneDetectionInformation, const PerformanceInformation &p_performanceInformation, const VideoManagerInformation &p_videoManagerInformation)
Updates p_frame with object detection, lane detection, performance and video manager information.
Calculates the frame times and current/average frames per second for real-time performance tracking.
~VideoManager()
Destructs a VideoManager object.
ObjectDetector m_objectDetector
The object detector.
void SetProperties(const int32_t &p_inputVideoCamera, 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 VideoManager object.
VideoManagerInformation m_videoManagerInformation
The VideoManagerInformation struct containing all video manager-related information.
cv::VideoCapture m_inputVideo
Represents the input video stream.
VideoManager()
Constructs a new VideoManager object.
cv::VideoWriter m_outputVideo
Represents the output video stream.
LaneDetector m_laneDetector
The lane detector.
std::chrono::time_point< std::chrono::high_resolution_clock > m_saveOutputStartTime
The time that the output started to be saved locally.
void ToggleDebugMode()
Toggles the debug mode and whether to destroy the debug frames.
void ToggleSaveOutput()
Toggles whether the output video stream is saved locally. If toggled on, it creates a new file in the...
void RunLaneAndObjectDetector()
Orchestration function which contains the main program loop.
Performance m_performance
The frame time and current/average frames per second performance calculator.
Performance GetPerformance()
Get the performance object to extract performance-related information.
void Quit()
Destroys all windows and releases all input/output videos.
cv::Mat m_currentFrame
Represents the current frame being processed.
static const uint32_t G_KEY_QUIT
Keyboard values when getting user input.
Definition Globals.hpp:126
static const uint32_t G_VIDEO_OUTPUT_FPS
Output video FPS.
Definition Globals.hpp:118
static const std::string G_UI_TEXT_RECORDING
Text to display whether or not recording.
Definition Globals.hpp:182
static const uint32_t G_VIDEO_OUTPUT_WIDTH
Output video dimensions.
Definition Globals.hpp:112
static const uint32_t G_KEY_DEBUG_MODE
Keyboard values when getting user input.
Definition Globals.hpp:124
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 std::string G_UI_TEXT_DEBUG_MODE
Text to display whether or not in debug mode.
Definition Globals.hpp:190
static const uint32_t G_VIDEO_OUTPUT_HEIGHT
Output video dimensions.
Definition Globals.hpp:111
ObjectDetectorTypes
The type of object detector to use with an option to disable object detection. The tiny version is mo...
Definition Globals.hpp:446
ObjectDetectorBackEnds
The supported backends for the object detector to run on. In theory, GPU should be significantly more...
Definition Globals.hpp:458
static std::string GetTimeElapsed(const std::chrono::time_point< std::chrono::high_resolution_clock > &p_startTime)
Gets the elapsed time from p_startTime to now.
Definition Globals.hpp:49
static const uint32_t G_KEY_TOGGLE_SAVE_OUTPUT
Keyboard values when getting user input.
Definition Globals.hpp:125
static const std::string G_CLI_HELP_MESSAGE
CLI help message for the video manager.
Definition Globals.hpp:97
static const std::string G_UI_TEXT_NOT_RECORDING
Text to display whether or not recording.
Definition Globals.hpp:183
static const std::string G_UI_TEXT_NOT_DEBUG_MODE
Text to display whether or not in debug mode.
Definition Globals.hpp:191
ObjectDetectorBlobSizes
The supported blob sizes for the object detector to run with. The larger the blob size the more perfo...
Definition Globals.hpp:470
Contains all Lane-and-Object-Detection objects.