circe 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
}
|