Skip to content

Commit 6521023

Browse files
Nuzhny007Smorodov
authored andcommitted
Added YOLO detector (Smorodov#76)
* Added hough3d sources * Calculate 3D hough trajectory lines * Added fps * Some warnings removing * Fixed warning * Added small crops in DNN detector for High resolution videos and small objects * Small refactoring * Some fix for single tracking * Added openmp flags to the compiler * Draw trajectory option * Update Readme * Fixed link * Hough3D disabled now in CMake * Added Yolo (and Tiny Yolo) detector * Update Readme
1 parent d1f3d0f commit 6521023

15 files changed

Lines changed: 10036 additions & 29 deletions

CMakeLists.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ endif()
5252
Detector/FaceDetector.cpp
5353
Detector/PedestrianDetector.cpp
5454
Detector/pedestrians/c4-pedestrian-detector.cpp
55-
Detector/DNNDetector.cpp
55+
Detector/SSDMobileNetDetector.cpp
56+
Detector/YoloDetector.cpp
5657

5758
Tracker/Ctracker.cpp
5859
Tracker/track.cpp
@@ -80,7 +81,8 @@ endif()
8081
Detector/FaceDetector.h
8182
Detector/PedestrianDetector.h
8283
Detector/pedestrians/c4-pedestrian-detector.h
83-
Detector/DNNDetector.h
84+
Detector/SSDMobileNetDetector.h
85+
Detector/YoloDetector.h
8486

8587
Tracker/Ctracker.h
8688
Tracker/track.h
@@ -250,7 +252,7 @@ endif(USE_OCV_BGFG)
250252
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
251253

252254
if (EIGEN3_FOUND)
253-
INCLUDE_DIRECTORIES("${EIGEN3_INCLUDE_DIR}")
255+
INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR})
254256
endif()
255257

256258
# ----------------------------------------------------------------------------

Detector/BaseDetector.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
#include "MotionDetector.h"
33
#include "FaceDetector.h"
44
#include "PedestrianDetector.h"
5-
#include "DNNDetector.h"
5+
#include "SSDMobileNetDetector.h"
6+
#include "YoloDetector.h"
67

78
///
89
/// \brief CreateDetector
@@ -59,8 +60,12 @@ BaseDetector* CreateDetector(
5960
detector = new PedestrianDetector(collectPoints, gray);
6061
break;
6162

62-
case tracking::DNN:
63-
detector = new DNNDetector(collectPoints, gray);
63+
case tracking::SSD_MobileNet:
64+
detector = new SSDMobileNetDetector(collectPoints, gray);
65+
break;
66+
67+
case tracking::Yolo:
68+
detector = new YoloDetector(collectPoints, gray);
6469
break;
6570

6671
default:
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
#include "DNNDetector.h"
1+
#include "SSDMobileNetDetector.h"
22
#include "nms.h"
33

44
///
5-
/// \brief DNNDetector::DNNDetector
5+
/// \brief SSDMobileNetDetector::SSDMobileNetDetector
66
/// \param collectPoints
77
/// \param gray
88
///
9-
DNNDetector::DNNDetector(
9+
SSDMobileNetDetector::SSDMobileNetDetector(
1010
bool collectPoints,
1111
cv::UMat& colorFrame
1212
)
@@ -27,17 +27,17 @@ DNNDetector::DNNDetector(
2727
}
2828

2929
///
30-
/// \brief DNNDetector::~DNNDetector
30+
/// \brief SSDMobileNetDetector::~SSDMobileNetDetector
3131
///
32-
DNNDetector::~DNNDetector(void)
32+
SSDMobileNetDetector::~SSDMobileNetDetector(void)
3333
{
3434
}
3535

3636
///
37-
/// \brief DNNDetector::Init
37+
/// \brief SSDMobileNetDetector::Init
3838
/// \return
3939
///
40-
bool DNNDetector::Init(const config_t& config)
40+
bool SSDMobileNetDetector::Init(const config_t& config)
4141
{
4242
auto modelConfiguration = config.find("modelConfiguration");
4343
auto modelBinary = config.find("modelBinary");
@@ -66,10 +66,10 @@ bool DNNDetector::Init(const config_t& config)
6666
}
6767

6868
///
69-
/// \brief DNNDetector::Detect
69+
/// \brief SSDMobileNetDetector::Detect
7070
/// \param gray
7171
///
72-
void DNNDetector::Detect(cv::UMat& colorFrame)
72+
void SSDMobileNetDetector::Detect(cv::UMat& colorFrame)
7373
{
7474
m_regions.clear();
7575

@@ -144,12 +144,12 @@ void DNNDetector::Detect(cv::UMat& colorFrame)
144144
}
145145

146146
///
147-
/// \brief DNNDetector::DetectInCrop
147+
/// \brief SSDMobileNetDetector::DetectInCrop
148148
/// \param colorFrame
149149
/// \param crop
150150
/// \param tmpRegions
151151
///
152-
void DNNDetector::DetectInCrop(cv::Mat colorFrame, const cv::Rect& crop, regions_t& tmpRegions)
152+
void SSDMobileNetDetector::DetectInCrop(cv::Mat colorFrame, const cv::Rect& crop, regions_t& tmpRegions)
153153
{
154154
//Convert Mat to batch of images
155155
cv::Mat inputBlob = cv::dnn::blobFromImage(cv::Mat(colorFrame, crop), m_inScaleFactor, cv::Size(InWidth, InHeight), m_meanVal, false, true);
Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
#include <opencv2/dnn.hpp>
66
#include <opencv2/dnn/shape_utils.hpp>
77

8+
// MobileNet Single-Shot Detector (https://arxiv.org/abs/1704.04861) to detect objects
9+
// .caffemodel model's file is available here: https://github.com/chuanqi305/MobileNet-SSD
10+
// Default network is 300x300 and 20-classes VOC
11+
812
///
9-
/// \brief The DNNDetector class
13+
/// \brief The SSDMobileNetDetector class
1014
///
11-
class DNNDetector : public BaseDetector
15+
class SSDMobileNetDetector : public BaseDetector
1216
{
1317
public:
14-
DNNDetector(bool collectPoints, cv::UMat& colorFrame);
15-
~DNNDetector(void);
18+
SSDMobileNetDetector(bool collectPoints, cv::UMat& colorFrame);
19+
~SSDMobileNetDetector(void);
1620

1721
bool Init(const config_t& config);
1822

Detector/YoloDetector.cpp

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
#include "YoloDetector.h"
2+
#include "nms.h"
3+
4+
///
5+
/// \brief YoloDetector::YoloDetector
6+
/// \param collectPoints
7+
/// \param gray
8+
///
9+
YoloDetector::YoloDetector(
10+
bool collectPoints,
11+
cv::UMat& colorFrame
12+
)
13+
:
14+
BaseDetector(collectPoints, colorFrame),
15+
m_WHRatio(InWidth / (float)InHeight),
16+
m_inScaleFactor(0.003921f),
17+
m_meanVal(0),
18+
m_confidenceThreshold(0.24f),
19+
m_maxCropRatio(2.0f)
20+
{
21+
m_classNames = { "background",
22+
"aeroplane", "bicycle", "bird", "boat",
23+
"bottle", "bus", "car", "cat", "chair",
24+
"cow", "diningtable", "dog", "horse",
25+
"motorbike", "person", "pottedplant",
26+
"sheep", "sofa", "train", "tvmonitor" };
27+
}
28+
29+
///
30+
/// \brief YoloDetector::~YoloDetector
31+
///
32+
YoloDetector::~YoloDetector(void)
33+
{
34+
}
35+
36+
///
37+
/// \brief YoloDetector::Init
38+
/// \return
39+
///
40+
bool YoloDetector::Init(const config_t& config)
41+
{
42+
auto modelConfiguration = config.find("modelConfiguration");
43+
auto modelBinary = config.find("modelBinary");
44+
if (modelConfiguration != config.end() && modelBinary != config.end())
45+
{
46+
m_net = cv::dnn::readNetFromDarknet(modelConfiguration->second, modelBinary->second);
47+
}
48+
49+
auto classNames = config.find("classNames");
50+
if (classNames != config.end())
51+
{
52+
std::ifstream classNamesFile(classNames->second);
53+
if (classNamesFile.is_open())
54+
{
55+
m_classNames.clear();
56+
std::string className;
57+
for (; std::getline(classNamesFile, className); )
58+
{
59+
m_classNames.push_back(className);
60+
}
61+
}
62+
}
63+
64+
auto confidenceThreshold = config.find("confidenceThreshold");
65+
if (confidenceThreshold != config.end())
66+
{
67+
m_confidenceThreshold = std::stof(confidenceThreshold->second);
68+
}
69+
70+
auto maxCropRatio = config.find("maxCropRatio");
71+
if (maxCropRatio != config.end())
72+
{
73+
m_maxCropRatio = std::stof(maxCropRatio->second);
74+
if (m_maxCropRatio < 1.f)
75+
{
76+
m_maxCropRatio = 1.f;
77+
}
78+
}
79+
80+
return !m_net.empty();
81+
}
82+
83+
///
84+
/// \brief YoloDetector::Detect
85+
/// \param gray
86+
///
87+
void YoloDetector::Detect(cv::UMat& colorFrame)
88+
{
89+
m_regions.clear();
90+
91+
regions_t tmpRegions;
92+
93+
cv::Mat colorMat = colorFrame.getMat(cv::ACCESS_READ);
94+
95+
int cropHeight = cvRound(m_maxCropRatio * InHeight);
96+
int cropWidth = cvRound(m_maxCropRatio * InWidth);
97+
98+
if (colorFrame.cols / (float)colorFrame.rows > m_WHRatio)
99+
{
100+
if (m_maxCropRatio <= 0 || cropHeight >= colorFrame.rows)
101+
{
102+
cropHeight = colorFrame.rows;
103+
}
104+
cropWidth = cvRound(cropHeight * m_WHRatio);
105+
}
106+
else
107+
{
108+
if (m_maxCropRatio <= 0 || cropWidth >= colorFrame.cols)
109+
{
110+
cropWidth = colorFrame.cols;
111+
}
112+
cropHeight = cvRound(colorFrame.cols / m_WHRatio);
113+
}
114+
115+
cv::Rect crop(0, 0, cropWidth, cropHeight);
116+
117+
for (; crop.y < colorMat.rows; crop.y += crop.height / 2)
118+
{
119+
bool needBreakY = false;
120+
if (crop.y + crop.height >= colorMat.rows)
121+
{
122+
crop.y = colorMat.rows - crop.height;
123+
needBreakY = true;
124+
}
125+
for (crop.x = 0; crop.x < colorMat.cols; crop.x += crop.width / 2)
126+
{
127+
bool needBreakX = false;
128+
if (crop.x + crop.width >= colorMat.cols)
129+
{
130+
crop.x = colorMat.cols - crop.width;
131+
needBreakX = true;
132+
}
133+
134+
DetectInCrop(colorMat, crop, tmpRegions);
135+
136+
if (needBreakX)
137+
{
138+
break;
139+
}
140+
}
141+
if (needBreakY)
142+
{
143+
break;
144+
}
145+
}
146+
147+
nms3<CRegion>(tmpRegions, m_regions, 0.4f,
148+
[](const CRegion& reg) -> cv::Rect { return reg.m_rect; },
149+
[](const CRegion& reg) -> float { return reg.m_confidence; },
150+
0, 0.f);
151+
152+
if (m_collectPoints)
153+
{
154+
for (auto& region : m_regions)
155+
{
156+
CollectPoints(region);
157+
}
158+
}
159+
}
160+
161+
///
162+
/// \brief YoloDetector::DetectInCrop
163+
/// \param colorFrame
164+
/// \param crop
165+
/// \param tmpRegions
166+
///
167+
void YoloDetector::DetectInCrop(cv::Mat colorFrame, const cv::Rect& crop, regions_t& tmpRegions)
168+
{
169+
//Convert Mat to batch of images
170+
cv::Mat inputBlob = cv::dnn::blobFromImage(cv::Mat(colorFrame, crop), m_inScaleFactor, cv::Size(InWidth, InHeight), m_meanVal, false, true);
171+
172+
m_net.setInput(inputBlob, "data"); //set the network input
173+
174+
cv::Mat detectionMat = m_net.forward("detection_out"); //compute output
175+
176+
for (int i = 0; i < detectionMat.rows; ++i)
177+
{
178+
const int probability_index = 5;
179+
const int probability_size = detectionMat.cols - probability_index;
180+
float* prob_array_ptr = &detectionMat.at<float>(i, probability_index);
181+
182+
size_t objectClass = std::max_element(prob_array_ptr, prob_array_ptr + probability_size) - prob_array_ptr;
183+
float confidence = detectionMat.at<float>(i, (int)objectClass + probability_index);
184+
185+
if (confidence > m_confidenceThreshold)
186+
{
187+
float x_center = detectionMat.at<float>(i, 0) * crop.width + crop.x;
188+
float y_center = detectionMat.at<float>(i, 1) * crop.height + crop.y;
189+
float width = detectionMat.at<float>(i, 2) * crop.width;
190+
float height = detectionMat.at<float>(i, 3) * crop.height;
191+
cv::Point p1(cvRound(x_center - width / 2), cvRound(y_center - height / 2));
192+
cv::Point p2(cvRound(x_center + width / 2), cvRound(y_center + height / 2));
193+
cv::Rect object(p1, p2);
194+
195+
tmpRegions.push_back(CRegion(object, m_classNames[objectClass], confidence));
196+
}
197+
}
198+
}

Detector/YoloDetector.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include "BaseDetector.h"
4+
5+
#include <opencv2/dnn.hpp>
6+
#include <opencv2/dnn/shape_utils.hpp>
7+
8+
// You only look once (YOLO)-Detector (https://arxiv.org/abs/1612.08242) to detect objects
9+
// Models can be downloaded here: https://pjreddie.com/darknet/yolo/
10+
// Default network is 416x416
11+
// Class names can be downloaded here: https://github.com/pjreddie/darknet/tree/master/data
12+
13+
///
14+
/// \brief The YoloDetector class
15+
///
16+
class YoloDetector : public BaseDetector
17+
{
18+
public:
19+
YoloDetector(bool collectPoints, cv::UMat& colorFrame);
20+
~YoloDetector(void);
21+
22+
bool Init(const config_t& config);
23+
24+
void Detect(cv::UMat& colorFrame);
25+
26+
private:
27+
cv::dnn::Net m_net;
28+
29+
void DetectInCrop(cv::Mat colorFrame, const cv::Rect& crop, regions_t& tmpRegions);
30+
31+
static const int InWidth = 416;
32+
static const int InHeight = 416;
33+
float m_WHRatio;
34+
float m_inScaleFactor;
35+
float m_meanVal;
36+
float m_confidenceThreshold;
37+
float m_maxCropRatio;
38+
std::vector<std::string> m_classNames;
39+
};

0 commit comments

Comments
 (0)