Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/learnopencv
Path: blob/master/AgeGender/AgeGender.cpp
3118 views
1
#include <opencv2/imgproc.hpp>
2
#include <opencv2/highgui.hpp>
3
#include <opencv2/dnn.hpp>
4
#include <tuple>
5
#include <iostream>
6
#include <opencv2/opencv.hpp>
7
#include <iterator>
8
using namespace cv;
9
using namespace cv::dnn;
10
using namespace std;
11
12
tuple<Mat, vector<vector<int>>> getFaceBox(Net net, Mat &frame, double conf_threshold)
13
{
14
Mat frameOpenCVDNN = frame.clone();
15
int frameHeight = frameOpenCVDNN.rows;
16
int frameWidth = frameOpenCVDNN.cols;
17
double inScaleFactor = 1.0;
18
Size size = Size(300, 300);
19
// std::vector<int> meanVal = {104, 117, 123};
20
Scalar meanVal = Scalar(104, 117, 123);
21
22
cv::Mat inputBlob;
23
inputBlob = cv::dnn::blobFromImage(frameOpenCVDNN, inScaleFactor, size, meanVal, true, false);
24
25
net.setInput(inputBlob, "data");
26
cv::Mat detection = net.forward("detection_out");
27
28
cv::Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());
29
30
vector<vector<int>> bboxes;
31
32
for(int i = 0; i < detectionMat.rows; i++)
33
{
34
float confidence = detectionMat.at<float>(i, 2);
35
36
if(confidence > conf_threshold)
37
{
38
int x1 = static_cast<int>(detectionMat.at<float>(i, 3) * frameWidth);
39
int y1 = static_cast<int>(detectionMat.at<float>(i, 4) * frameHeight);
40
int x2 = static_cast<int>(detectionMat.at<float>(i, 5) * frameWidth);
41
int y2 = static_cast<int>(detectionMat.at<float>(i, 6) * frameHeight);
42
vector<int> box = {x1, y1, x2, y2};
43
bboxes.push_back(box);
44
cv::rectangle(frameOpenCVDNN, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(0, 255, 0),2, 4);
45
}
46
}
47
48
return make_tuple(frameOpenCVDNN, bboxes);
49
}
50
51
int main(int argc, char** argv)
52
{
53
string faceProto = "opencv_face_detector.pbtxt";
54
string faceModel = "opencv_face_detector_uint8.pb";
55
56
string ageProto = "age_deploy.prototxt";
57
string ageModel = "age_net.caffemodel";
58
59
string genderProto = "gender_deploy.prototxt";
60
string genderModel = "gender_net.caffemodel";
61
62
Scalar MODEL_MEAN_VALUES = Scalar(78.4263377603, 87.7689143744, 114.895847746);
63
64
vector<string> ageList = {"(0-2)", "(4-6)", "(8-12)", "(15-20)", "(25-32)",
65
"(38-43)", "(48-53)", "(60-100)"};
66
67
vector<string> genderList = {"Male", "Female"};
68
69
70
cout << "USAGE : ./AgeGender <videoFile> " << endl;
71
cout << "USAGE : ./AgeGender <device> " << endl;
72
cout << "USAGE : ./AgeGender <videoFile> <device>" << endl;
73
74
string device = "cpu";
75
76
string videoFile = "0";
77
78
// Take arguments from commmand line
79
if (argc == 2)
80
{
81
if((string)argv[1] == "gpu")
82
device = "gpu";
83
else if((string)argv[1] == "cpu")
84
device = "cpu";
85
else
86
videoFile = argv[1];
87
}
88
else if (argc == 3)
89
{
90
videoFile = argv[1];
91
if((string)argv[2] == "gpu")
92
device = "gpu";
93
}
94
95
// Load Network
96
Net ageNet = readNet(ageModel, ageProto);
97
Net genderNet = readNet(genderModel, genderProto);
98
Net faceNet = readNet(faceModel, faceProto);
99
100
if (device == "cpu")
101
{
102
cout << "Using CPU device" << endl;
103
ageNet.setPreferableBackend(DNN_TARGET_CPU);
104
105
genderNet.setPreferableBackend(DNN_TARGET_CPU);
106
107
faceNet.setPreferableBackend(DNN_TARGET_CPU);
108
}
109
else if (device == "gpu")
110
{
111
cout << "Using GPU device" << endl;
112
ageNet.setPreferableBackend(DNN_BACKEND_CUDA);
113
ageNet.setPreferableTarget(DNN_TARGET_CUDA);
114
115
genderNet.setPreferableBackend(DNN_BACKEND_CUDA);
116
genderNet.setPreferableTarget(DNN_TARGET_CUDA);
117
118
faceNet.setPreferableBackend(DNN_BACKEND_CUDA);
119
faceNet.setPreferableTarget(DNN_TARGET_CUDA);
120
}
121
122
123
VideoCapture cap;
124
if (videoFile.length() > 1)
125
cap.open(videoFile);
126
else
127
cap.open(0);
128
int padding = 20;
129
while(waitKey(1) < 0) {
130
// read frame
131
Mat frame;
132
cap.read(frame);
133
if (frame.empty())
134
{
135
waitKey();
136
break;
137
}
138
139
vector<vector<int>> bboxes;
140
Mat frameFace;
141
tie(frameFace, bboxes) = getFaceBox(faceNet, frame, 0.7);
142
143
if(bboxes.size() == 0) {
144
cout << "No face detected, checking next frame." << endl;
145
continue;
146
}
147
for (auto it = begin(bboxes); it != end(bboxes); ++it) {
148
Rect rec(it->at(0) - padding, it->at(1) - padding, it->at(2) - it->at(0) + 2*padding, it->at(3) - it->at(1) + 2*padding);
149
Mat face = frame(rec); // take the ROI of box on the frame
150
151
Mat blob;
152
blob = blobFromImage(face, 1, Size(227, 227), MODEL_MEAN_VALUES, false);
153
genderNet.setInput(blob);
154
// string gender_preds;
155
vector<float> genderPreds = genderNet.forward();
156
// printing gender here
157
// find max element index
158
// distance function does the argmax() work in C++
159
int max_index_gender = std::distance(genderPreds.begin(), max_element(genderPreds.begin(), genderPreds.end()));
160
string gender = genderList[max_index_gender];
161
cout << "Gender: " << gender << endl;
162
163
/* // Uncomment if you want to iterate through the gender_preds vector
164
for(auto it=begin(gender_preds); it != end(gender_preds); ++it) {
165
cout << *it << endl;
166
}
167
*/
168
169
ageNet.setInput(blob);
170
vector<float> agePreds = ageNet.forward();
171
/* // uncomment below code if you want to iterate through the age_preds
172
* vector
173
cout << "PRINTING AGE_PREDS" << endl;
174
for(auto it = age_preds.begin(); it != age_preds.end(); ++it) {
175
cout << *it << endl;
176
}
177
*/
178
179
// finding maximum indicd in the age_preds vector
180
int max_indice_age = std::distance(agePreds.begin(), max_element(agePreds.begin(), agePreds.end()));
181
string age = ageList[max_indice_age];
182
cout << "Age: " << age << endl;
183
string label = gender + ", " + age; // label
184
cv::putText(frameFace, label, Point(it->at(0), it->at(1) -15), cv::FONT_HERSHEY_SIMPLEX, 0.9, Scalar(0, 255, 255), 2, cv::LINE_AA);
185
imshow("Frame", frameFace);
186
imwrite("out.jpg",frameFace);
187
}
188
189
}
190
}
191
192