-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathutils.cpp
164 lines (140 loc) · 6.38 KB
/
utils.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include "utils.h"
using namespace std;
using namespace cv;
namespace FaceFusionUtils {
float GetIoU(const Bbox box1, const Bbox box2)
{
float x1 = max(box1.xmin, box2.xmin);
float y1 = max(box1.ymin, box2.ymin);
float x2 = min(box1.xmax, box2.xmax);
float y2 = min(box1.ymax, box2.ymax);
float w = max(0.f, x2 - x1);
float h = max(0.f, y2 - y1);
float over_area = w * h;
if (over_area == 0)
return 0.0;
float union_area = (box1.xmax - box1.xmin) * (box1.ymax - box1.ymin) + (box2.xmax - box2.xmin) * (box2.ymax - box2.ymin) - over_area;
return over_area / union_area;
}
vector<int> nms(vector<Bbox> boxes, vector<float> confidences, const float nms_thresh)
{
sort(confidences.begin(), confidences.end(), [&confidences](size_t index_1, size_t index_2)
{ return confidences[index_1] > confidences[index_2]; });
const int num_box = confidences.size();
vector<bool> isSuppressed(num_box, false);
for (int i = 0; i < num_box; ++i)
{
if (isSuppressed[i])
{
continue;
}
for (int j = i + 1; j < num_box; ++j)
{
if (isSuppressed[j])
{
continue;
}
float ovr = GetIoU(boxes[i], boxes[j]);
if (ovr > nms_thresh)
{
isSuppressed[j] = true;
}
}
}
vector<int> keep_inds;
for (size_t i = 0; i < isSuppressed.size(); i++)
{
if (!isSuppressed[i])
{
keep_inds.emplace_back(i);
}
}
return keep_inds;
}
Mat warp_face_by_face_landmark_5(const Mat temp_vision_frame, Mat &crop_img, const vector<Point2f> face_landmark_5, const vector<Point2f> normed_template, const Size crop_size)
{
vector<uchar> inliers(face_landmark_5.size(), 0);
Mat affine_matrix = cv::estimateAffinePartial2D(face_landmark_5, normed_template, cv::noArray(), cv::RANSAC, 100.0);
warpAffine(temp_vision_frame, crop_img, affine_matrix, crop_size, cv::INTER_AREA, cv::BORDER_REPLICATE);
return affine_matrix;
}
vector<Point2f> scale_face_landmark_5(const vector<Point2f> face_landmark_5, const float scale)
{
vector<Point2f> face_landmark_5_scale(face_landmark_5.size());
for (size_t i = 0; i < face_landmark_5.size(); i++)
{
face_landmark_5_scale[i] = face_landmark_5[i] - face_landmark_5[2];
face_landmark_5_scale[i] *= scale;
face_landmark_5_scale[i] += face_landmark_5[2];
}
return face_landmark_5_scale;
}
Mat create_static_box_mask(const int *crop_size, const float face_mask_blur, const int *face_mask_padding)
{
const float blur_amount = int(crop_size[0] * 0.5 * face_mask_blur);
const int blur_area = max(int(blur_amount / 2), 1);
Mat box_mask = Mat::ones(crop_size[0], crop_size[1], CV_32FC1);
int sub = max(blur_area, int(crop_size[1] * face_mask_padding[0] / 100));
// Mat roi = box_mask(cv::Rect(0,0,sub,crop_size[1]));
box_mask(cv::Rect(0, 0, crop_size[1], sub)).setTo(0);
sub = crop_size[0] - max(blur_area, int(crop_size[1] * face_mask_padding[2] / 100));
box_mask(cv::Rect(0, sub, crop_size[1], crop_size[0] - sub)).setTo(0);
sub = max(blur_area, int(crop_size[0] * face_mask_padding[3] / 100));
box_mask(cv::Rect(0, 0, sub, crop_size[0])).setTo(0);
sub = crop_size[1] - max(blur_area, int(crop_size[0] * face_mask_padding[1] / 100));
box_mask(cv::Rect(sub, 0, crop_size[1] - sub, crop_size[0])).setTo(0);
if (blur_amount > 0)
{
GaussianBlur(box_mask, box_mask, Size(0, 0), blur_amount * 0.25);
}
return box_mask;
}
Mat paste_back(Mat temp_vision_frame, Mat crop_vision_frame, Mat crop_mask, Mat affine_matrix)
{
Mat inverse_matrix;
cv::invertAffineTransform(affine_matrix, inverse_matrix);
Mat inverse_mask;
Size temp_size(temp_vision_frame.cols, temp_vision_frame.rows);
warpAffine(crop_mask, inverse_mask, inverse_matrix, temp_size);
inverse_mask.setTo(0, inverse_mask < 0);
inverse_mask.setTo(1, inverse_mask > 1);
Mat inverse_vision_frame;
warpAffine(crop_vision_frame, inverse_vision_frame, inverse_matrix, temp_size, cv::INTER_LINEAR, cv::BORDER_REPLICATE);
vector<Mat> inverse_vision_frame_bgrs(3);
split(inverse_vision_frame, inverse_vision_frame_bgrs);
vector<Mat> temp_vision_frame_bgrs(3);
split(temp_vision_frame, temp_vision_frame_bgrs);
for (int c = 0; c < 3; c++)
{
inverse_vision_frame_bgrs[c].convertTo(inverse_vision_frame_bgrs[c], CV_32FC1); ////注意数据类型转换,不然在下面的矩阵点乘运算时会报错的
temp_vision_frame_bgrs[c].convertTo(temp_vision_frame_bgrs[c], CV_32FC1); ////注意数据类型转换,不然在下面的矩阵点乘运算时会报错的
}
vector<Mat> channel_mats(3);
channel_mats[0] = inverse_mask.mul(inverse_vision_frame_bgrs[0]) + temp_vision_frame_bgrs[0].mul(1 - inverse_mask);
channel_mats[1] = inverse_mask.mul(inverse_vision_frame_bgrs[1]) + temp_vision_frame_bgrs[1].mul(1 - inverse_mask);
channel_mats[2] = inverse_mask.mul(inverse_vision_frame_bgrs[2]) + temp_vision_frame_bgrs[2].mul(1 - inverse_mask);
cv::Mat paste_vision_frame;
merge(channel_mats, paste_vision_frame);
paste_vision_frame.convertTo(paste_vision_frame, CV_8UC3);
return paste_vision_frame;
}
Mat blend_frame(Mat temp_vision_frame, Mat paste_vision_frame, const int FACE_ENHANCER_BLEND)
{
const float face_enhancer_blend = 1 - ((float)FACE_ENHANCER_BLEND / 100.f);
Mat dstimg;
cv::addWeighted(temp_vision_frame, face_enhancer_blend, paste_vision_frame, 1 - face_enhancer_blend, 0, dstimg);
return dstimg;
}
float dot_product(const std::vector<float>& vec1, const std::vector<float>& vec2) {
if (vec1.size() != vec2.size()) {
throw std::invalid_argument("Vectors must be of the same length");
}
vector<float> normed_vec1(vec1.size());
float norm1 = std::sqrt(std::inner_product(vec1.begin(), vec1.end(), vec1.begin(), 0.0f));
std::transform(vec1.begin(), vec1.end(), normed_vec1.begin(), [norm1](float val) { return val / norm1; });
vector<float> normed_vec2(vec1.size());
float norm2 = std::sqrt(std::inner_product(vec2.begin(), vec2.end(), vec2.begin(), 0.0f));
std::transform(vec2.begin(), vec2.end(), normed_vec2.begin(), [norm2](float val) { return val / norm2; });
return std::inner_product(normed_vec1.begin(), normed_vec1.end(), normed_vec2.begin(), 0.0f);
}
}