circe 0.1.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/data/face_detection_yunet_2023mar.onnx +0 -0
- data/data/{yolov5s.onnx → yolov5su-sim.onnx} +0 -0
- data/data/yolov5su.onnx +0 -0
- data/data/yolov8s-sim.onnx +0 -0
- data/data/yolov8s.onnx +0 -0
- data/ext/circe.cpp +69 -33
- data/ext/extconf.rb +1 -1
- data/ext/yolo.h +1 -1
- data/ext/yunet.h +22 -22
- data/lib/circe/version.rb +1 -1
- data/lib/circe.rb +3 -3
- metadata +8 -6
- data/data/face_detection_yunet_2022mar.onnx +0 -0
- data/ext/yunet.cpp +0 -132
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d735b7de777b161f27ca0b0d50282eca7e18f1cd9e5aa6e298e089f6ccd2b89
|
4
|
+
data.tar.gz: 5ba4acf8e3c3ef5950c981de11a31f4bdcdb7a0fb1cc4c534b1e62f96a99fb3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8ac69c1f5b7d3af53db342306629fc880ae8b6386ba0ee4ee02fcec391fcab29b9acc3aa972a01f2d99b31cf0267861d6553d2cdc54b839e2a36648801b83fd3
|
7
|
+
data.tar.gz: 76a3084d3b0fc496d39e9efc04733b17a64a31e5b4285ad450bf1dc681db132671febe821ae3ae717b68771a20901f28247ae62c89a2ec57a013ef4ca7bb6c4b
|
Binary file
|
Binary file
|
data/data/yolov5su.onnx
ADDED
Binary file
|
Binary file
|
data/data/yolov8s.onnx
ADDED
Binary file
|
data/ext/circe.cpp
CHANGED
@@ -91,6 +91,7 @@ static VALUE eCirceError = Qundef;
|
|
91
91
|
#include <chrono>
|
92
92
|
#include <opencv2/highgui.hpp>
|
93
93
|
#include <opencv2/imgproc.hpp>
|
94
|
+
#include <opencv2/core/mat.hpp>
|
94
95
|
|
95
96
|
#include "yolo.h"
|
96
97
|
#include "yunet.h"
|
@@ -121,6 +122,7 @@ static ID id_jpg;
|
|
121
122
|
|
122
123
|
static ID id_label;
|
123
124
|
static ID id_thickness;
|
125
|
+
static ID id_extra;
|
124
126
|
static ID id_color;
|
125
127
|
|
126
128
|
static Yolo *yolo;
|
@@ -175,18 +177,21 @@ circe_annotate(Mat& img, Rect& box, VALUE v_annotation, int *state) {
|
|
175
177
|
VALUE v_label = Qnil;
|
176
178
|
VALUE v_color = ULONG2NUM(0x0000ff);
|
177
179
|
VALUE v_thickness = INT2NUM(1);
|
180
|
+
VALUE v_extra = Qtrue;
|
178
181
|
|
179
182
|
VALUE s_label = rb_id2sym(id_label);
|
180
183
|
VALUE s_color = rb_id2sym(id_color);
|
181
184
|
VALUE s_thickness = rb_id2sym(id_thickness);
|
182
|
-
|
185
|
+
VALUE s_extra = rb_id2sym(id_extra);
|
186
|
+
|
183
187
|
switch (TYPE(v_annotation)) {
|
184
188
|
case T_NIL:
|
185
189
|
break;
|
186
190
|
case T_HASH:
|
187
|
-
v_thickness =
|
188
|
-
v_color =
|
189
|
-
v_label =
|
191
|
+
v_thickness = rb_hash_lookup2(v_annotation, s_thickness, v_thickness);
|
192
|
+
v_color = rb_hash_lookup2(v_annotation, s_color, v_color );
|
193
|
+
v_label = rb_hash_lookup2(v_annotation, s_label, v_label );
|
194
|
+
v_extra = rb_hash_lookup2(v_annotation, s_extra, v_extra );
|
190
195
|
break;
|
191
196
|
case T_ARRAY:
|
192
197
|
switch(RARRAY_LENINT(v_annotation)) {
|
@@ -226,46 +231,74 @@ circe_annotate(Mat& img, Rect& box, VALUE v_annotation, int *state) {
|
|
226
231
|
rb_hash_aset(r, s_label, v_label );
|
227
232
|
rb_hash_aset(r, s_color, v_color );
|
228
233
|
rb_hash_aset(r, s_thickness, v_thickness);
|
234
|
+
rb_hash_aset(r, s_extra, v_extra );
|
229
235
|
return r;
|
230
236
|
}
|
231
237
|
|
232
238
|
|
233
239
|
|
234
240
|
void
|
235
|
-
yunet_process_features(
|
236
|
-
Mat& img, VALUE v_features, int *state)
|
241
|
+
yunet_process_features(cv::Mat& faces, Mat& img, VALUE v_features, int *state)
|
237
242
|
{
|
238
|
-
for (int i = 0; i < faces.
|
239
|
-
|
240
|
-
|
243
|
+
for (int i = 0; i < faces.rows; i++) {
|
244
|
+
// Face
|
245
|
+
int x_f = static_cast<int>(faces.at<float>(i, 0));
|
246
|
+
int y_f = static_cast<int>(faces.at<float>(i, 1));
|
247
|
+
int w_f = static_cast<int>(faces.at<float>(i, 2));
|
248
|
+
int h_f = static_cast<int>(faces.at<float>(i, 3));
|
249
|
+
// Right eye
|
250
|
+
int x_re = static_cast<int>(faces.at<float>(i, 4));
|
251
|
+
int y_re = static_cast<int>(faces.at<float>(i, 5));
|
252
|
+
// Left eye
|
253
|
+
int x_le = static_cast<int>(faces.at<float>(i, 6));
|
254
|
+
int y_le = static_cast<int>(faces.at<float>(i, 7));
|
255
|
+
// Nose tip
|
256
|
+
int x_nt = static_cast<int>(faces.at<float>(i, 8));
|
257
|
+
int y_nt = static_cast<int>(faces.at<float>(i, 9));
|
258
|
+
// Right corner mouth
|
259
|
+
int x_rcm = static_cast<int>(faces.at<float>(i, 10));
|
260
|
+
int y_rcm = static_cast<int>(faces.at<float>(i, 11));
|
261
|
+
// Left corner mouth
|
262
|
+
int x_lcm = static_cast<int>(faces.at<float>(i, 12));
|
263
|
+
int y_lcm = static_cast<int>(faces.at<float>(i, 13));
|
264
|
+
// Confidence
|
265
|
+
float confidence = faces.at<float>(i, 14);
|
241
266
|
|
242
|
-
|
267
|
+
VALUE v_type = ID2SYM(id_face);
|
243
268
|
VALUE v_box = rb_ary_new_from_args(4,
|
244
|
-
|
245
|
-
|
269
|
+
INT2NUM(x_f), INT2NUM(y_f),
|
270
|
+
INT2NUM(w_f), INT2NUM(h_f));
|
246
271
|
VALUE v_landmark = rb_ary_new_from_args(5,
|
247
|
-
rb_ary_new_from_args(2, INT2NUM(
|
248
|
-
INT2NUM(
|
249
|
-
|
250
|
-
INT2NUM(
|
251
|
-
|
252
|
-
INT2NUM(
|
253
|
-
|
254
|
-
INT2NUM(
|
255
|
-
rb_ary_new_from_args(2, INT2NUM(
|
256
|
-
|
257
|
-
VALUE
|
258
|
-
|
272
|
+
rb_ary_new_from_args(2, INT2NUM(x_re),
|
273
|
+
INT2NUM(y_re)),
|
274
|
+
rb_ary_new_from_args(2, INT2NUM(x_le),
|
275
|
+
INT2NUM(y_le)),
|
276
|
+
rb_ary_new_from_args(2, INT2NUM(x_nt),
|
277
|
+
INT2NUM(y_nt)),
|
278
|
+
rb_ary_new_from_args(2, INT2NUM(x_rcm),
|
279
|
+
INT2NUM(y_rcm)),
|
280
|
+
rb_ary_new_from_args(2, INT2NUM(x_lcm),
|
281
|
+
INT2NUM(y_lcm)));
|
282
|
+
VALUE v_confidence = DBL2NUM(confidence);
|
283
|
+
VALUE v_feature = rb_ary_new_from_args(4, v_type, v_box, v_landmark,
|
284
|
+
v_confidence);
|
285
|
+
|
259
286
|
rb_ary_push(v_features, v_feature);
|
287
|
+
|
260
288
|
|
261
289
|
if (!img.empty() && rb_block_given_p()) {
|
290
|
+
cv::Rect box = cv::Rect(x_f, y_f, w_f, h_f);
|
262
291
|
VALUE v_annotation = rb_yield_splat(v_feature);
|
263
|
-
VALUE cfg
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
292
|
+
VALUE cfg = circe_annotate(img, box, v_annotation, state);
|
293
|
+
VALUE s_extra = rb_id2sym(id_extra);
|
294
|
+
|
295
|
+
if (!NIL_P(cfg) && RTEST(rb_hash_aref(cfg, s_extra))) {
|
296
|
+
cv::Scalar color = cv::Scalar(255, 0, 0);
|
297
|
+
cv::circle(img, cv::Point(x_le, y_le ), 3, color, 2);
|
298
|
+
cv::circle(img, cv::Point(x_re, y_re ), 3, color, 2);
|
299
|
+
cv::circle(img, cv::Point(x_nt, y_nt ), 3, color, 2);
|
300
|
+
cv::circle(img, cv::Point(x_rcm, y_rcm), 3, color, 2);
|
301
|
+
cv::circle(img, cv::Point(x_lcm, y_lcm), 3, color, 2);
|
269
302
|
}
|
270
303
|
}
|
271
304
|
}
|
@@ -283,11 +316,11 @@ yolo_process_features(vector<Yolo::Item>& items,
|
|
283
316
|
Rect box = std::get<2>(items[i]);
|
284
317
|
|
285
318
|
VALUE v_type = ID2SYM(id_class);
|
286
|
-
VALUE v_name = rb_str_new(name.c_str(), name.size());
|
287
|
-
VALUE v_confidence = DBL2NUM(confidence);
|
288
319
|
VALUE v_box = rb_ary_new_from_args(4,
|
289
320
|
INT2NUM(box.x ), INT2NUM(box.y ),
|
290
321
|
INT2NUM(box.width), INT2NUM(box.height));
|
322
|
+
VALUE v_name = rb_str_new(name.c_str(), name.size());
|
323
|
+
VALUE v_confidence = DBL2NUM(confidence);
|
291
324
|
VALUE v_feature = rb_ary_new_from_args(4, v_type, v_box,
|
292
325
|
v_name, v_confidence);
|
293
326
|
rb_ary_push(v_features, v_feature);
|
@@ -349,9 +382,10 @@ circe_m_analyze(int argc, VALUE* argv, VALUE self) {
|
|
349
382
|
}
|
350
383
|
|
351
384
|
if (RTEST(v_face)) {
|
352
|
-
|
385
|
+
cv::Mat faces;
|
353
386
|
yunet->process(i_img, faces);
|
354
387
|
yunet_process_features(faces, o_img, v_features, &state);
|
388
|
+
faces.release();
|
355
389
|
if (state) goto exception;
|
356
390
|
}
|
357
391
|
|
@@ -375,6 +409,7 @@ circe_m_analyze(int argc, VALUE* argv, VALUE self) {
|
|
375
409
|
std::vector<uchar> buf;
|
376
410
|
cv::imencode(format, o_img, buf);
|
377
411
|
v_image = rb_str_new(reinterpret_cast<char*>(buf.data()), buf.size());
|
412
|
+
buf.clear();
|
378
413
|
}
|
379
414
|
|
380
415
|
i_img.release();
|
@@ -425,6 +460,7 @@ void Init_core(void) {
|
|
425
460
|
id_jpg = rb_intern_const("jpg" );
|
426
461
|
id_label = rb_intern_const("label" );
|
427
462
|
id_thickness = rb_intern_const("thickness");
|
463
|
+
id_extra = rb_intern_const("extra" );
|
428
464
|
id_color = rb_intern_const("color" );
|
429
465
|
|
430
466
|
|
data/ext/extconf.rb
CHANGED
data/ext/yolo.h
CHANGED
@@ -17,7 +17,7 @@ private:
|
|
17
17
|
static constexpr float INPUT_WIDTH = 640.0;
|
18
18
|
static constexpr float INPUT_HEIGHT = 640.0;
|
19
19
|
static constexpr float CONFIDENCE_THRESHOLD = 0.25;
|
20
|
-
static constexpr float SCORE_THRESHOLD = 0.
|
20
|
+
static constexpr float SCORE_THRESHOLD = 0.50;
|
21
21
|
static constexpr float NMS_THRESHOLD = 0.50;
|
22
22
|
|
23
23
|
bool letterBoxForSquare = true;
|
data/ext/yunet.h
CHANGED
@@ -2,37 +2,37 @@
|
|
2
2
|
#define __YUNET__
|
3
3
|
|
4
4
|
#include <string>
|
5
|
-
#include <
|
6
|
-
#include <
|
7
|
-
#include <utility>
|
8
|
-
|
9
|
-
#include <opencv2/dnn.hpp>
|
10
|
-
|
5
|
+
#include <opencv2/objdetect/face.hpp>
|
6
|
+
#include <opencv2/core.hpp>
|
11
7
|
|
12
8
|
class YuNet
|
13
9
|
{
|
14
10
|
|
15
11
|
public:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
12
|
+
YuNet(const std::string& model_path,
|
13
|
+
const cv::Size& input_size = cv::Size(320, 320),
|
14
|
+
float conf_threshold = 0.6f,
|
15
|
+
float nms_threshold = 0.3f,
|
16
|
+
int top_k = 5000,
|
17
|
+
int backend_id = cv::dnn::DNN_BACKEND_OPENCV,
|
18
|
+
int target_id = cv::dnn::DNN_TARGET_CPU)
|
19
|
+
{
|
20
|
+
model = cv::FaceDetectorYN::create(model_path, "", input_size,
|
21
|
+
conf_threshold,
|
22
|
+
nms_threshold, top_k,
|
23
|
+
backend_id, target_id);
|
24
|
+
}
|
28
25
|
|
29
|
-
public:
|
30
|
-
YuNet(const std::string& model);
|
31
26
|
~YuNet() {};
|
32
|
-
|
27
|
+
|
28
|
+
void process(const cv::Mat& img, cv::Mat& faces) {
|
29
|
+
model->setInputSize(img.size());
|
30
|
+
model->detect(img, faces);
|
31
|
+
}
|
33
32
|
|
34
33
|
private:
|
35
|
-
|
34
|
+
|
35
|
+
cv::Ptr<cv::FaceDetectorYN> model;
|
36
36
|
};
|
37
37
|
|
38
38
|
#endif
|
data/lib/circe/version.rb
CHANGED
data/lib/circe.rb
CHANGED
@@ -3,9 +3,9 @@ class Circe
|
|
3
3
|
private
|
4
4
|
|
5
5
|
# Don't know how to do it inside the c extension
|
6
|
-
DATA_DIR
|
7
|
-
ONNX_YOLO
|
8
|
-
ONNX_YUNET
|
6
|
+
DATA_DIR = File.join(__dir__, '..', 'data').freeze
|
7
|
+
ONNX_YOLO = [ File.join(DATA_DIR, 'yolov8s.onnx'), 480, 640 ]
|
8
|
+
ONNX_YUNET = [ File.join(DATA_DIR, 'face_detection_yunet_2023mar.onnx') ]
|
9
9
|
|
10
10
|
end
|
11
11
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: circe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stéphane D'Alu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2+
|
14
14
|
|
@@ -22,14 +22,16 @@ extensions:
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
files:
|
24
24
|
- circe.gemspec
|
25
|
-
- data/
|
26
|
-
- data/
|
25
|
+
- data/face_detection_yunet_2023mar.onnx
|
26
|
+
- data/yolov5su-sim.onnx
|
27
|
+
- data/yolov5su.onnx
|
28
|
+
- data/yolov8s-sim.onnx
|
29
|
+
- data/yolov8s.onnx
|
27
30
|
- ext/camera_model.h
|
28
31
|
- ext/circe.cpp
|
29
32
|
- ext/extconf.rb
|
30
33
|
- ext/yolo.cpp
|
31
34
|
- ext/yolo.h
|
32
|
-
- ext/yunet.cpp
|
33
35
|
- ext/yunet.h
|
34
36
|
- lib/circe.rb
|
35
37
|
- lib/circe/version.rb
|
@@ -52,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
54
|
- !ruby/object:Gem::Version
|
53
55
|
version: '0'
|
54
56
|
requirements: []
|
55
|
-
rubygems_version: 3.
|
57
|
+
rubygems_version: 3.5.9
|
56
58
|
signing_key:
|
57
59
|
specification_version: 4
|
58
60
|
summary: Face and object recognition
|
Binary file
|
data/ext/yunet.cpp
DELETED
@@ -1,132 +0,0 @@
|
|
1
|
-
#include <cmath>
|
2
|
-
#include <string>
|
3
|
-
#include <vector>
|
4
|
-
#include <numeric>
|
5
|
-
#include <algorithm>
|
6
|
-
|
7
|
-
#include <opencv2/dnn.hpp>
|
8
|
-
|
9
|
-
#include "yunet.h"
|
10
|
-
|
11
|
-
|
12
|
-
YuNet::YuNet(const std::string& model_filename)
|
13
|
-
{
|
14
|
-
net = cv::dnn::readNetFromONNX(model_filename);
|
15
|
-
net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
|
16
|
-
net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
|
17
|
-
}
|
18
|
-
|
19
|
-
|
20
|
-
void YuNet::process(const cv::Mat& img, std::vector<YuNet::Face>& faces)
|
21
|
-
{
|
22
|
-
/* -- Preparing for image size -- */
|
23
|
-
cv::Size model_size;
|
24
|
-
model_size.width = MODEL_WIDTH;
|
25
|
-
model_size.height = MODEL_WIDTH * img.rows / img.cols;
|
26
|
-
model_size.height = (model_size.height / 32) * 32;
|
27
|
-
|
28
|
-
std::pair<int32_t, int32_t> feature_map_2th = {
|
29
|
-
(model_size.height + 1) / 2 / 2,
|
30
|
-
(model_size.width + 1) / 2 / 2
|
31
|
-
};
|
32
|
-
|
33
|
-
std::vector<std::pair<int32_t, int32_t>> feature_map_list;
|
34
|
-
feature_map_list.push_back({ (feature_map_2th.first + 1) / 2 ,
|
35
|
-
(feature_map_2th.second + 1) / 2 });
|
36
|
-
|
37
|
-
for (int32_t i = 0; i < 3; i++) {
|
38
|
-
const auto& previous = feature_map_list.back();
|
39
|
-
feature_map_list.push_back({ (previous.first + 1) / 2 ,
|
40
|
-
(previous.second + 1) / 2 });
|
41
|
-
}
|
42
|
-
|
43
|
-
std::vector<std::vector<float>> prior_list;
|
44
|
-
for (int i = 0; i < static_cast<int32_t>(feature_map_list.size()); i++) {
|
45
|
-
const auto& min_sizes = MIN_SIZES[i];
|
46
|
-
const auto& feature_map = feature_map_list[i];
|
47
|
-
for (int y = 0; y < feature_map.first; y++) {
|
48
|
-
for (int x = 0; x < feature_map.second; x++) {
|
49
|
-
for (const auto& min_size : min_sizes) {
|
50
|
-
float s_kx = static_cast<float>(min_size) / model_size.width;
|
51
|
-
float s_ky = static_cast<float>(min_size) / model_size.height;
|
52
|
-
float cx = (x + 0.5f) * STEPS[i] / model_size.width;
|
53
|
-
float cy = (y + 0.5f) * STEPS[i] / model_size.height;
|
54
|
-
prior_list.push_back({ cx, cy, s_kx, s_ky });
|
55
|
-
}
|
56
|
-
}
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
|
-
|
61
|
-
/* -- Pre-process -- */
|
62
|
-
cv::Mat blob;
|
63
|
-
cv::dnn::blobFromImage(img, blob, 1.0, model_size);
|
64
|
-
|
65
|
-
/* -- Inference -- */
|
66
|
-
std::vector<cv::Mat> outputs;
|
67
|
-
net.setInput(blob);
|
68
|
-
net.forward(outputs, { "conf", "iou", "loc" });
|
69
|
-
|
70
|
-
/* -- Post Process -- */
|
71
|
-
const cv::Mat& mat_conf = outputs[0];
|
72
|
-
const cv::Mat& mat_iou = outputs[1];
|
73
|
-
const cv::Mat& mat_loc = outputs[2];
|
74
|
-
const cv::Size image_size = img.size();
|
75
|
-
|
76
|
-
// Get score list
|
77
|
-
std::vector<float> cls_score;
|
78
|
-
for (int32_t row = 0; row < mat_conf.rows; row++) {
|
79
|
-
float val = mat_conf.at<float>(cv::Point(1, row));
|
80
|
-
cls_score.push_back(std::clamp(val, 0.0f, 1.0f));
|
81
|
-
}
|
82
|
-
|
83
|
-
std::vector<float> iou_score;
|
84
|
-
for (int32_t row = 0; row < mat_iou.rows; row++) {
|
85
|
-
float val = mat_conf.at<float>(cv::Point(0, row));
|
86
|
-
iou_score.push_back(std::clamp(val, 0.0f, 1.0f));
|
87
|
-
}
|
88
|
-
|
89
|
-
std::vector<float> score;
|
90
|
-
for (int32_t row = 0; row < mat_conf.rows; row++) {
|
91
|
-
score.push_back(std::sqrt(cls_score[row] * iou_score[row]));
|
92
|
-
}
|
93
|
-
|
94
|
-
// All bbox
|
95
|
-
std::vector<cv::Rect> bbox_all;
|
96
|
-
for (int row = 0; row < mat_loc.rows; row++) {
|
97
|
-
float cx = mat_loc.at<float>(cv::Point(0, row));
|
98
|
-
float cy = mat_loc.at<float>(cv::Point(1, row));
|
99
|
-
float w = mat_loc.at<float>(cv::Point(2, row));
|
100
|
-
float h = mat_loc.at<float>(cv::Point(3, row));
|
101
|
-
|
102
|
-
cx = prior_list[row][0] + cx * VARIANCES[0] * prior_list[row][2];
|
103
|
-
cy = prior_list[row][1] + cy * VARIANCES[0] * prior_list[row][3];
|
104
|
-
w = prior_list[row][2] * std::exp(w * VARIANCES[0]);
|
105
|
-
h = prior_list[row][3] * std::exp(h * VARIANCES[1]);
|
106
|
-
|
107
|
-
bbox_all.push_back({
|
108
|
-
static_cast<int32_t>((cx - w / 2) * image_size.width),
|
109
|
-
static_cast<int32_t>((cy - h / 2) * image_size.height),
|
110
|
-
static_cast<int32_t>(w * image_size.width),
|
111
|
-
static_cast<int32_t>(h * image_size.height) });
|
112
|
-
}
|
113
|
-
|
114
|
-
// Non-Maximum Suppression
|
115
|
-
std::vector<int> indices;
|
116
|
-
cv::dnn::NMSBoxes(bbox_all, score, CONF_THRESHOLD, NMS_THRESHOLD, indices);
|
117
|
-
|
118
|
-
// Get valid bbox and landmark
|
119
|
-
faces.clear();
|
120
|
-
for (int idx : indices) {
|
121
|
-
Landmark landmark; // (landmark is 5 points)
|
122
|
-
for (int i = 0; i < static_cast<int>(landmark.size()); i++) {
|
123
|
-
cv::Point& p = landmark[i];
|
124
|
-
float x = mat_loc.at<float>(cv::Point(4 + i * 2, idx));
|
125
|
-
float y = mat_loc.at<float>(cv::Point(4 + i * 2 + 1, idx));
|
126
|
-
p.x = static_cast<int32_t>((prior_list[idx][0] + x * VARIANCES[0] * prior_list[idx][2]) * image_size.width);
|
127
|
-
p.y = static_cast<int32_t>((prior_list[idx][1] + y * VARIANCES[0] * prior_list[idx][3]) * image_size.height);
|
128
|
-
}
|
129
|
-
|
130
|
-
faces.push_back({ bbox_all[idx], landmark });
|
131
|
-
}
|
132
|
-
}
|