访问网址查看 人脸对齐的发展
https://max.book118.com/html/2017/1111/139651668.shtm
1.准备数据集:UMD 把 21个关键点 提取出5个。
2.Loss 函数使用 absloss ,如何添加 caffe absloss 查看我的其他博文。
C:\WorkSpace\SoftWare\caffe\convert_multilabel_imageset.exe --shuffle D:\UMD\result_img_96\ D:\UMD\result_img_96\new_shutter_96_5_train.txt E:\work\face_alignment\lanmark_5\model\umd_96_5\lmdb2\train_data_npd E:\work\face_alignment\lanmark_5\model\umd_96_5\lmdb2\train_label_npd 15
C:\WorkSpace\SoftWare\caffe\convert_multilabel_imageset.exe D:\UMD\result_img_96\ D:\UMD\result_img_96\shutter_96_5_val.txt E:\work\face_alignment\lanmark_5\model\umd_96_5\lmdb2\test_data_npd E:\work\face_alignment\lanmark_5\model\umd_96_5\lmdb2\test_label_npd 15
pause
# The train/test net protocol buffer definition
net: "train_5_op_abs.prototxt"
# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
test_iter: 48
# Carry out testing every 500 training iterations.
test_interval: 1000
# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.0004
#base_lr:0.0002
#加快梯度下降的速度
momentum: 0.95
#momentum2: 0.999
weight_decay: 0.0001
# The learning rate policy
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# Display every 100 iterations
display: 1000
# The maximum number of iterations
max_iter: 300000
# snapshot intermediate results
snapshot: 10000
snapshot_prefix: "save_path_abs/"
# solver mode: CPU or GPU
solver_mode: GPU
#type:"Adam"
name: "Faceregressions"
layer {
name: "landmark_5"
type: "Data"
top: "data"
include {
phase: TRAIN
}
transform_param {
mean_value: 104
mean_value: 117
mean_value: 124
scale: 0.0078125
}
data_param {
source: "lmdb/train_data_npd"
batch_size: 64
backend: LMDB
}
}
layer {
name: "landmark_5"
type: "Data"
top: "label"
include {
phase: TRAIN
}
data_param {
source: "lmdb/train_label_npd"
batch_size: 64
backend: LMDB
}
}
layer {
name: "landmark_5"
type: "Data"
top: "data"
include {
phase: TEST
}
#transform_param {
# scale: 0.00390625
#}
transform_param {
mean_value: 104
mean_value: 117
mean_value: 124
scale: 0.0078125
}
data_param {
source: "lmdb/test_data_npd"
batch_size: 64
backend: LMDB
}
}
layer {
name: "landmark_5"
type: "Data"
top: "label"
include {
phase: TEST
}
data_param {
source: "lmdb/test_label_npd"
batch_size: 64
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 32
kernel_size: 3
pad:1
stride: 2
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "conv1"
top: "conv1"
}
layer {
name: "conv2"
type: "Convolution"
bottom: "conv1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 64
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu2"
type: "ReLU"
bottom: "conv2"
top: "conv2"
}
layer {
name: "conv3"
type: "Convolution"
bottom: "conv2"
top: "conv3"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 128
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu3"
type: "ReLU"
bottom: "conv3"
top: "conv3"
}
layer {
name: "conv4"
type: "Convolution"
bottom: "conv3"
top: "conv4"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 128
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu4"
type: "ReLU"
bottom: "conv4"
top: "conv4"
}
layer {
name: "conv5"
type: "Convolution"
bottom: "conv4"
top: "conv5"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 128
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu5"
type: "ReLU"
bottom: "conv5"
top: "conv5"
}
layer {
name: "conv6"
type: "Convolution"
bottom: "conv5"
top: "conv6"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 128
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "conv6"
top: "conv6"
}
layer {
name: "ip1"
type: "InnerProduct"
bottom: "conv6"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 256
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "slice"
type: "Slice"
bottom: "label"
top: "label1"
top: "label2"
slice_param {
axis: 1
slice_point: 10
}
}
# 5个 visible 信息暂时没用 label2
layer {
name: "accuracy"
type: "AbsoluteLoss"
bottom: "ip2"
bottom: "label1"
top: "accuracy"
include {
phase: TEST
}
}
layer {
name: "loss"
type: "AbsoluteLoss"
bottom: "ip2"
bottom: "label1"
top: "loss"
}
name: "Faceregressions"
layer
{
name: "data"
type: "MemoryData"
top: "data"
top: "label"
memory_data_param
{
batch_size: 1
channels: 3
height: 96
width: 96
}
transform_param {
mean_value: 104
mean_value: 117
mean_value: 124
scale: 0.0078125
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 32
kernel_size: 3
pad:1
stride: 2
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "conv1"
top: "conv1"
}
layer {
name: "conv2"
type: "Convolution"
bottom: "conv1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 64
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu2"
type: "ReLU"
bottom: "conv2"
top: "conv2"
}
layer {
name: "conv3"
type: "Convolution"
bottom: "conv2"
top: "conv3"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 128
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu3"
type: "ReLU"
bottom: "conv3"
top: "conv3"
}
layer {
name: "conv4"
type: "Convolution"
bottom: "conv3"
top: "conv4"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 128
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu4"
type: "ReLU"
bottom: "conv4"
top: "conv4"
}
layer {
name: "conv5"
type: "Convolution"
bottom: "conv4"
top: "conv5"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 128
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu5"
type: "ReLU"
bottom: "conv5"
top: "conv5"
}
layer {
name: "conv6"
type: "Convolution"
bottom: "conv5"
top: "conv6"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 128
kernel_size: 3
stride: 2
pad:1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "conv6"
top: "conv6"
}
layer {
name: "ip1"
type: "InnerProduct"
bottom: "conv6"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 256
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
#include "Util.h"
#include
#include
#include
#include //使用stringstream需要引入这个头文件
#include
#include
#include
#include
#include
#include "../../../../SoftWare/libsvm-3.22/svm.h"
using namespace std;
using namespace glasssix;
using namespace cv;
const int LEFT_EYE = 0;
const int RIGHT_EYE = 9;
const int NOSE = 34;
const int LEFT_MOUTH = 46;
const int RIGHT_MOUTH = 47;
const int ALL = 95;
template
Type stringToNum(const string& str)
{
istringstream iss(str);
Type num;
iss >> num;
return num;
}
void getFiles(string path, vector& files, vector& filenames, const string & tail)
{
//文件句柄
intptr_t hFile = 0;
//文件信息
struct _finddata_t fileinfo;
string p;
if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
{
do
{
//如果是目录,迭代之
//如果不是,加入列表
if ((fileinfo.attrib & _A_SUBDIR))
{
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
{
getFiles(p.assign(path).append("\\").append(fileinfo.name), files, filenames, tail);
}
}
else
{
string filename = fileinfo.name;
size_t found = filename.find(tail);
if (found != string::npos)
{
files.push_back(p.assign(path).append("\\").append(filename));
filenames.push_back(filename);
}
}
} while (_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
void splitString(const string& s, vector& v, const string& c)
{
string::size_type pos1, pos2;
pos2 = s.find(c);
pos1 = 0;
while (string::npos != pos2)
{
v.push_back(s.substr(pos1, pos2 - pos1));
pos1 = pos2 + c.size();
pos2 = s.find(c, pos1);
}
if (pos1 != s.length()) {
v.push_back(s.substr(pos1));
}
}
void parseData_5(string buf, LandMark& mark)
{
vector result1;
splitString(buf, result1, "\t");
mark.fileName = result1[0];
vector result2;
splitString(result1[1], result2, ",");
mark.points[0].x = stringToNum(result2[2 * LEFT_EYE]);
mark.points[0].y = stringToNum(result2[2 * LEFT_EYE + 1]);
mark.points[1].x = stringToNum(result2[2 * RIGHT_EYE]);
mark.points[1].y = stringToNum(result2[2 * RIGHT_EYE + 1]);
mark.points[2].x = stringToNum(result2[2 * NOSE]);
mark.points[2].y = stringToNum(result2[2 * NOSE + 1]);
mark.points[3].x = stringToNum(result2[2 * LEFT_MOUTH]);
mark.points[3].y = stringToNum(result2[2 * LEFT_MOUTH + 1]);
mark.points[4].x = stringToNum(result2[2 * RIGHT_MOUTH]);
mark.points[4].y = stringToNum(result2[2 * RIGHT_MOUTH + 1]);
}
void parseKey_26_Data(string buf, LandMark& mark)
{
vector result1;
splitString(buf, result1, "\t");
mark.fileName = result1[0];
vector result2;
splitString(result1[1], result2, ",");
mark.points[0].x = stringToNum(result2[2 * LEFT_EYE]);
mark.points[0].y = stringToNum(result2[2 * LEFT_EYE + 1]);
mark.points[1].x = stringToNum(result2[2 * RIGHT_EYE]);
mark.points[1].y = stringToNum(result2[2 * RIGHT_EYE + 1]);
mark.points[2].x = stringToNum(result2[2 * NOSE]);
mark.points[2].y = stringToNum(result2[2 * NOSE + 1]);
mark.points[3].x = stringToNum(result2[2 * LEFT_MOUTH]);
mark.points[3].y = stringToNum(result2[2 * LEFT_MOUTH + 1]);
mark.points[4].x = stringToNum(result2[2 * RIGHT_MOUTH]);
mark.points[4].y = stringToNum(result2[2 * RIGHT_MOUTH + 1]);
int j = 5;
for (int i = 74; i < ALL; i++)
{
if (i >= 74 && i < 95) {
mark.points[j].x = stringToNum(result2[2 * i]);
mark.points[j].y = stringToNum(result2[2 * i + 1]);
j++;
}
}
}
void parseKey_68_Data(string buf, LandMark& mark)
{
vector result1;
splitString(buf, result1, "\t");
mark.fileName = result1[0];
vector result2;
splitString(result1[1], result2, ",");
int j = 0;
//add left eye 18个
for (int i = 0; i < 37; i++)
{
if ((i >= 0 && i < 9) || (i >= 18 && i < 26) || (i == 36)) {
mark.points[j].x = stringToNum(result2[2 * i]);
mark.points[j].y = stringToNum(result2[2 * i + 1]);
j++;
}
}
//add right eye 18个
for (int i = 9; i < 38; i++)
{
if ((i >= 9 && i < 18) || (i >= 26 && i < 34) || (i == 37)) {
mark.points[j].x = stringToNum(result2[2 * i]);
mark.points[j].y = stringToNum(result2[2 * i + 1]);
j++;
}
}
//add nose eye 10个
for (int i = 34; i < 46; i++)
{
if ((i >= 34 && i < 36) || (i >= 38 && i < 46)) {
mark.points[j].x = stringToNum(result2[2 * i]);
mark.points[j].y = stringToNum(result2[2 * i + 1]);
j++;
}
}
//add mouth eye 22个
for (int i = 46; i < 68; i++)
{
if (i >= 46 && i < 68) {
mark.points[j].x = stringToNum(result2[2 * i]);
mark.points[j].y = stringToNum(result2[2 * i + 1]);
j++;
}
}
}
void parseData(string buf, LandMark& mark, int num_mark)
{
vector result1;
splitString(buf, result1, " ");
mark.fileName = result1[0];
for (int i = 0; i < num_mark; i++)
{
mark.points[i].x = stringToNum(result1[2 * i + 1]);
mark.points[i].y = stringToNum(result1[2 * (i + 1)]);
}
}
void parseData(string buf, LandMark& mark)
{
vector result1;
splitString(buf, result1, "\t");
mark.fileName = result1[0];
vector result2;
splitString(result1[1], result2, ",");
for (int i = 0; i < LANDMARK_NUM; i++)
{
mark.points[i].x = stringToNum(result2[2 * i]);
mark.points[i].y = stringToNum(result2[2 * i + 1]);
}
}
void DataPrepareUtil::clearFileData(string filePath)
{
if (filePath == "")
{
return;
}
ofstream in;
in.open(filePath, ios::trunc);
in.close();
}
void DataPrepareUtil::readallFile(std::string dir, vector & files, vector& filenames, string const & tail)
{
getFiles(dir, files, filenames, tail);
}
int DataPrepareUtil::getpts(string filename, LandMark & landmark)
{
if (filename != "")
{
vector result;
splitString(filename, result, ".");
string file = result[0] + ".pts";
ifstream fileA(file);
if (!fileA)
{
cout << "没有找到需要读取的 " << file << " 请将文件放到指定位置再次运行本程序。" << endl;
return -1;
}
//landmark.fileName = filename;
for (int i = 0; !fileA.eof(); i++)
{
string buf;
getline(fileA, buf, '\n');
if (buf == "")
{
//cout << "buf is empty." << endl;
continue;
}
if (i >= 3 && i < 71)
{
vector point;
splitString(buf, point, " ");
landmark.points[i - 3].x = stringToNum(point[0]);
landmark.points[i - 3].y = stringToNum(point[1]);
}
}
fileA.close();
return 0;
}
else
{
cout << "file name is null." << endl;
return -1;
}
}
void DataPrepareUtil::readLabelData(string filePath, std::vector
#include
#include "../CascadRegression/MCLC.h"
#include
#include "../CascadRegression/util/Util.h"
#include
#include
#include
using namespace caffe;
using namespace cv;
using namespace glasssix;
using namespace std;
#define DEVICE 0
#define RESIZE 96
#define IMAGESIZE 96
#define NEED_LANDMARK 5
double predict(Mat &img, MCLC & mclc, int net_id, LandMark & landmark, int mark_num)
{
double time = 0;
double t0 = (double)cvGetTickCount();
vector imgdata;
imgdata.push_back(img);
unordered_map result = mclc.Forward(imgdata, net_id);
double t1 = (double)cvGetTickCount();
time = (t1 - t0) / ((double)cvGetTickFrequency() * 1000);
//cout << "time is:" << time << " ms" << endl;
for (unordered_map::iterator iter = result.begin(); iter != result.end(); iter++) {
string key = iter->first;
DataBlob result1 = iter->second;
vector mt = result1.size;
if (result1.name == "ip2")
{
for (int i = 0; i < mark_num; i++)
{
float x = *(result1.data);
float y = *(++result1.data);
landmark.points[i].x = x;
landmark.points[i].y = y;
(result1.data)++;
}
}
else if (result1.name == "ip3")
{
for (int i = 0; i < mark_num; i++)
{
landmark.visiable[i] = *(result1.data);
(result1.data)++;
}
}
}
return time;
}
void showError(vector &label, vector & predictRe, int mark_num)
{
int size = label.size();
float ave_error = 0, eye_error = 0;
cout << label.size() << " " << predictRe.size() << endl;
for (int i = 0; i < size; i++)
{
float sum = 0, sum_eye = 0;
for (int j = 0; j < mark_num; j++)
{
if (j == 0)
{
sum_eye += pow((label[i].points[j].x - predictRe[i].points[j].x), 2) + pow((label[i].points[j].y - predictRe[i].points[j].y), 2);
}
sum += pow((label[i].points[j].x - predictRe[i].points[j].x), 2) + pow((label[i].points[j].y - predictRe[i].points[j].y), 2);
}
eye_error += sum_eye;
float distance = sqrt(pow((label[i].points[0].x - label[i].points[1].x), 2) + pow((label[i].points[0].y - label[i].points[1].y), 2));
ave_error += 1 / distance * sqrt(sum);
}
cout << "eye-error is:" << eye_error / size << endl;
cout << "all error is:" << ave_error / size << endl;
}
void showVisibleError(vector &label, vector & predictRe, int mark_num)
{
int size = label.size();
float error1 = 0, error2 = 0;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < mark_num; j++)
{
if (label[i].visiable[j] == 0)
{
error2++;
if (predictRe[i].visiable[j] > 0.5)
{
error1++;
}
}
}
}
cout << "visiable error is:" << error1 / error2 << endl;
}
void switchPointSize(DataPrepareUtil &dpu)
{
//switch point size
string shutter_train = "D:\\face_new\\landmark_5\\shutter_train.txt";
string shutter_test = "D:\\face_new\\landmark_5\\shutter_test.txt";
string shutter_val = "D:\\face_new\\landmark_5\\shutter_val.txt";
vector data_96, data_96_test, data_96_val;
data_96 = dpu.readStageOneData(shutter_train, NEED_LANDMARK);
data_96_test = dpu.readStageOneData(shutter_test, NEED_LANDMARK);
data_96_val = dpu.readStageOneData(shutter_val, NEED_LANDMARK);
dpu.switchSizePoint(data_96, NEED_LANDMARK, Size(96, 96), Size(128, 128));
dpu.switchSizePoint(data_96_test, NEED_LANDMARK, Size(96, 96), Size(128, 128));
dpu.switchSizePoint(data_96_val, NEED_LANDMARK, Size(96, 96), Size(128, 128));
/*for (int i = 0; i < 10; i++)
{
Mat img = imread("D:\\face_new\\landmark_5\\result_img_128\\" + data_96[i].fileName);
for (int j = 0; j < NEED_LANDMARK; j++)
{
circle(img, Point(data_96[i].points[j]), 2, Scalar(255, 0, 0));
}
imshow("img", img);
waitKey(0);
}*/
dpu.writeDatatoFile("D:\\face_new\\landmark_5\\result_img_128\\shutter_train.txt", data_96, NEED_LANDMARK);
dpu.writeDatatoFile("D:\\face_new\\landmark_5\\result_img_128\\shutter_test.txt", data_96_test, NEED_LANDMARK);
dpu.writeDatatoFile("D:\\face_new\\landmark_5\\result_img_128\\shutter_val.txt", data_96_val, NEED_LANDMARK);
}
void Test300WError(DataPrepareUtil &dpu, MCLC &mclc, int id_68)
{
// 300W 错误
string img_300w = "D:\\face\\face_alignment\\300W_resize\\";
string text_300w = "D:\\face\\face_alignment\\300W_resize\\result_point_96_68.txt";
double time1 = 0;
vector data_68;
data_68 = dpu.readStageOneData(text_300w, LANDMARK_NUM);
vector data_5;
vector pre_data_5;
dpu.switch68to5landmark(data_68, data_5);
int size = data_5.size();
for (int j = 0; j < size; j++)
{
LandMark landmark;
landmark.fileName = data_5[j].fileName;
Mat img = imread(img_300w + data_5[j].fileName);
time1 += predict(img, mclc, id_68, landmark, NEED_LANDMARK);
pre_data_5.push_back(landmark);
}
cout << "300W test result" << endl;
showError(data_5, pre_data_5, NEED_LANDMARK);
cout << "average time is :" << time1 / size << endl;
//dpu.writeDatatoFile("D:\\face\\face_alignment\\300W_resize\\result_point_96_5.txt", data_5, NEED_LANDMARK);
}
void L2LossPre(vector &preRe)
{
string base = "E:\\work\\face_alignment\\lanmark_5\\model\\regression_96_5\\";
string prototext = base + "test_5_op.prototxt";
string mode_path = base + "save_path\\_iter_150000.caffemodel";
string img_path = "D:\\face_new\\landmark_5\\result_img_96\\";
string text_label = img_path + "shutter_test.txt";
MCLC mclc;
int id_68 = mclc.AddNet(prototext, mode_path, DEVICE);
DataPrepareUtil dpu;
vector data;
data = dpu.readStageOneData(text_label, NEED_LANDMARK);
cout << "data length is:" << data.size() << endl;
int length = data.size();
double time1 = 0;
for (int i = 0; i < length; i++)
{
LandMark landmark;
landmark.fileName = data[i].fileName;
Mat img = imread(img_path + data[i].fileName);
time1 += predict(img, mclc, id_68, landmark, NEED_LANDMARK);
preRe.push_back(landmark);
//for (int j = 0; j < NEED_LANDMARK; j++)
//{
// circle(img, Point(landmark.points[j]), 2, Scalar(255, 0, 0));
//}
//imshow("img", img);
//waitKey(0);
}
cout << "average time1 is:" << time1 / length << " ms" << endl;
showError(data, preRe, NEED_LANDMARK);
}
void absLossPre(string img_path, string text_label, MCLC &mclc, vector &preRe, DataPrepareUtil &dpu, vector & data)
{
string base = "E:\\work\\face_alignment\\lanmark_5\\model\\umd_96_5\\";
string prototext = base + "test_5_op_change_abs.prototxt";
string mode_path = base + "save_path_abs\\_iter_200000.caffemodel";
int id_68 = mclc.AddNet(prototext, mode_path, DEVICE);
data = dpu.readPointVisibleData(text_label, NEED_LANDMARK);
cout << "data length is:" << data.size() << endl;
int length = data.size();
double time1 = 0;
for (int i = 0; i < length; i++)
{
LandMark landmark;
landmark.fileName = data[i].fileName;
Mat img = imread(img_path + data[i].fileName);
time1 += predict(img, mclc, id_68, landmark, NEED_LANDMARK);
preRe.push_back(landmark);
}
cout << "average time1 is:" << time1 / length << " ms" << endl;
showError(data, preRe, NEED_LANDMARK);
}
void pointVisibleLossPre(string img_path, string text_label, MCLC &mclc, vector &preRe, DataPrepareUtil &dpu, vector & data)
{
string base = "E:\\work\\face_alignment\\lanmark_5\\model\\umd_128_5\\";
string prototext = base + "test_5_op_loss.prototxt";
string mode_path = base + "save_path1\\_iter_200000.caffemodel";
int id_68 = mclc.AddNet(prototext, mode_path, DEVICE);
data = dpu.readPointVisibleData(text_label, NEED_LANDMARK);
cout << "data length is:" << data.size() << endl;
int length = data.size();
double time1 = 0;
for (int i = 0; i < length; i++)
{
LandMark landmark;
landmark.fileName = data[i].fileName;
Mat img = imread(img_path + data[i].fileName);
time1 += predict(img, mclc, id_68, landmark, NEED_LANDMARK);
preRe.push_back(landmark);
//for (int j = 0; j < NEED_LANDMARK; j++)
//{
// Scalar scalar;
// if (landmark.visiable[j] < 0.5)
// {
// scalar = Scalar(255, 0, 0);
// }
// else {
// scalar = Scalar(0, 0, 255);
// }
// circle(img, Point(landmark.points[j]), 2, scalar, -1);
//}
//imshow("img", img);
//waitKey(0);
}
cout << "average time1 is:" << time1 / length << " ms" << endl;
showError(data, preRe, NEED_LANDMARK);
}
void smoothLossPre(string img_path, string text_label, MCLC &mclc, vector &preRe, DataPrepareUtil &dpu, vector & data)
{
string base = "E:\\work\\face_alignment\\lanmark_5\\model\\regression_96_5\\";
string prototext = base + "test_5_op_loss.prototxt";
string mode_path = base + "save_path_smooth\\_iter_200000.caffemodel";
int id_68 = mclc.AddNet(prototext, mode_path, DEVICE);
data = dpu.readStageOneData(text_label, NEED_LANDMARK);
cout << "data length is:" << data.size() << endl;
int length = data.size();
double time1 = 0;
for (int i = 0; i < length; i++)
{
LandMark landmark;
landmark.fileName = data[i].fileName;
Mat img = imread(img_path + data[i].fileName);
time1 += predict(img, mclc, id_68, landmark, NEED_LANDMARK);
preRe.push_back(landmark);
}
cout << "average time1 is:" << time1 / length << " ms" << endl;
showError(data, preRe, NEED_LANDMARK);
}
void size64Pre()
{
string base = "E:\\work\\face_alignment\\lanmark_5\\model\\regression_64_5\\";
string prototext = base + "test_5_op.prototxt";
string mode_path = base + "save_path\\_iter_150000.caffemodel";
string img_path = "D:\\face_new\\landmark_5\\result_img_64\\";
string text_label = img_path + "shutter_test.txt";
MCLC mclc;
int id_68 = mclc.AddNet(prototext, mode_path, DEVICE);
DataPrepareUtil dpu;
vector data;
data = dpu.readStageOneData(text_label, NEED_LANDMARK);
cout << "data length is:" << data.size() << endl;
int length = data.size();
vector preRe;
double time1 = 0;
for (int i = 0; i < length; i++)
{
LandMark landmark;
landmark.fileName = data[i].fileName;
Mat img = imread(img_path + data[i].fileName);
time1 += predict(img, mclc, id_68, landmark, NEED_LANDMARK);
preRe.push_back(landmark);
//for (int j = 0; j < NEED_LANDMARK; j++)
//{
// circle(img, Point(landmark.points[j]), 2, Scalar(255, 0, 0));
//}
//imshow("img", img);
//waitKey(0);
}
cout << "average time1 is:" << time1 / length << " ms" << endl;
showError(data, preRe, NEED_LANDMARK);
}
//size: brow, eye, nose, mouth, face
const float four_size[] = { 24,24, 28,28, 48,32 };
string mark_4_img_dir[] = { "eye\\", "nose\\", "mouth\\" };
string mark_4_img_train[] = { "eye_train.txt", "nose_train.txt", "mouth_train.txt" };
string mark_4_img_test[] = { "eye_test.txt", "nose_test.txt", "mouth_test.txt" };
void getRect(LandMark landmark, int flag, vector &rects, int cols, int rows)
{
Rect rect, rect1;
Point p1;
if (flag == 0)
{
p1 = landmark.points[0];
}
else if (flag == 1)
{
p1 = landmark.points[2];
}
else if (flag == 2)
{
p1 = landmark.points[3];
}
float x, y, width, height;
rect.width = four_size[2 * flag];
rect.height = four_size[2 * flag + 1];
x = p1.x;
y = p1.y;
rect.x = min(max(x - four_size[2 * flag] * 0.5f, 0.0f), (float)(IMAGESIZE - four_size[2 * flag]));
rect.y = min(max(y - four_size[2 * flag + 1] * 0.5f, 0.0f), (float)(IMAGESIZE - four_size[2 * flag + 1]));
rects.push_back(rect);
}
void resetRect(Rect & rect, int cols, int rows)
{
if (rect.x < 0)
{
rect.x = 0;
}
if (rect.y < 0)
{
rect.y = 0;
}
if (rect.x + rect.width > cols)
{
rect.x = cols - rect.width;
}
if (rect.y + rect.height > rows)
{
rect.y = rows - rect.height;
}
}
void addRect(vector & rects)
{
srand((unsigned)time(NULL));
int dir[] = { 1,1, 1,-1, 1,0, -1,1, -1,-1, -1,0, 0,1, 0,-1 };
if (rects.size() == 1)
{
for (int i = 0; i < 8; i++)
{
Rect r(rects[0]);
r.x += dir[2 * i] * (rand() % 4 + 1);
r.y += dir[2 * i + 1] * (rand() % 4 + 1);
resetRect(r, IMAGESIZE, IMAGESIZE);
rects.push_back(r);
}
}
}
void createPatchFile(string base, vector &data, vector &preRe, DataPrepareUtil &dpu)
{
const int path_size = 1;
vector landmark_four[path_size][2];
int istd = 0;
for (int j = 0; j < path_size; j++)
{
dpu.clearFileData(base + mark_4_img_dir[j] + mark_4_img_train[j]);
dpu.clearFileData(base + mark_4_img_dir[j] + mark_4_img_test[j]);
}
int length = preRe.size();
for (int i = 0; i < length; i++)
{
if (i >= 12000)
{
istd = 1;
}
for (int j = 0; j < path_size; j++)
{
Mat img = imread(base + preRe[i].fileName);
vector rects;
getRect(preRe[i], j, rects, img.cols, img.rows);
//cout << rect.x << " " << rect.y << " " << rect.width << " " << rect.height << endl;
addRect(rects);
for (int n = 0; n < rects.size(); n++)
{
Mat roi = img(rects[n]);
string dir = base + mark_4_img_dir[j];
if (_access(dir.c_str(), 0) == -1)
{
_mkdir(dir.c_str());
}
imwrite(dir + to_string(n) + "_" + preRe[i].fileName, roi);
//坐标转换
LandMark mark;
mark.fileName = to_string(n) + "_" + preRe[i].fileName;
float offsetX = (data[i].points[0].x - rects[n].x) * four_size[2 * j] / rects[n].width;
float offsetY = (data[i].points[0].y - rects[n].y) * four_size[2 * j + 1] / rects[n].height;
mark.points[0].x = offsetX;
mark.points[0].y = offsetY;
landmark_four[j][istd].push_back(mark);
}
}
if (landmark_four[0][0].size() > 1000)
{
for (int j = 0; j < path_size; j++)
{
dpu.writeDatatoFile(base + mark_4_img_dir[j] + mark_4_img_train[j], landmark_four[j][0], 1);
(landmark_four[j][0]).clear();
}
}
if (landmark_four[0][1].size() > 1000)
{
for (int j = 0; j < path_size; j++)
{
dpu.writeDatatoFile(base + mark_4_img_dir[j] + mark_4_img_test[j], landmark_four[j][1], 1);
(landmark_four[j][1]).clear();
}
}
}
for (int j = 0; j < path_size; j++)
{
dpu.writeDatatoFile(base + mark_4_img_dir[j] + mark_4_img_train[j], landmark_four[j][0], 1);
增加验证集数据 数据平衡
//dpu.writeDatatoFile(base + mark_4_img_dir[j] + mark_4_img_train[j], landmark_four[j][1], mark_num[j]);
//dpu.writeDatatoFile(base + mark_4_img_dir[j] + mark_4_img_train[j], landmark_four[j][1], mark_num[j]);
//dpu.writeDatatoFile(base + mark_4_img_dir[j] + mark_4_img_train[j], landmark_four[j][1], mark_num[j]);
dpu.writeDatatoFile(base + mark_4_img_dir[j] + mark_4_img_test[j], landmark_four[j][1], 1);
}
}
void stageTwoPredict(string img_path, MCLC &mclc, vector &label, vector &preRe)
{
string base = "E:\\work\\face_alignment\\lanmark_5\\model\\regression_stage_two\\eye\\";
string prototext_eye = base + "test_eye_op.prototxt";
string mode_path_eye = base + "save_path\\_iter_150000.caffemodel";
int id_eye = mclc.AddNet(prototext_eye, mode_path_eye, DEVICE);
double time_four = 0;
int length = preRe.size();
for (int i = 0; i < length; i++)
{
LandMark landmark;
landmark.fileName = preRe[i].fileName;
Mat img = imread(img_path + preRe[i].fileName);
vector rects;
getRect(preRe[i], 0, rects, img.cols, img.rows);
Mat roi = img(rects[0]);
time_four += predict(roi, mclc, id_eye, landmark, 1);
preRe[i].points[0].x = landmark.points[0].x * (rects[0].width / four_size[0]) + rects[0].x;
preRe[i].points[0].y = landmark.points[0].y * (rects[0].height / four_size[1]) + rects[0].y;
}
showError(label, preRe, NEED_LANDMARK);
cout << "stage two ........................................................." << endl;
cout << "average time is :" << time_four / length << " ms" << endl;
}
void showMeanShape()
{
string shape_text = "D:\\face_new\\landmark_5\\result_img_128\\landmark_128_5.txt";
vectordata;
DataPrepareUtil dpu;
data = dpu.readStageOneData(shape_text, NEED_LANDMARK);
cout << "data length is:" << data.size() << endl;
LandMark landmark;
int length = data.size();
for (int i = 0; i < length; i++)
{
for (int j = 0; j < NEED_LANDMARK; j++)
{
landmark.points[j].x += data[i].points[j].x;
landmark.points[j].y += data[i].points[j].y;
}
}
for (int j = 0; j < NEED_LANDMARK; j++)
{
landmark.points[j].x = landmark.points[j].x / length;
landmark.points[j].y = landmark.points[j].y / length;
cout << "shape j:" << j << " ( " << landmark.points[j].x << " , " << landmark.points[j].y << " )" << endl;
}
}
int main(int argc, const char** argv) {
//L2LossPre();
//AbsLossPre();
//size64Pre();
DataPrepareUtil dpu;
vector preRe;
vector data;
string img_path = "D:\\UMD\\result_img_96\\";
string text_label = img_path + "shutter_96_5_test.txt";
MCLC mclc;
//showMeanShape();
absLossPre(img_path, text_label, mclc, preRe, dpu, data);
//smoothLossPre(img_path, text_label, mclc, preRe, dpu, data);
//string base = "D:\\face_new\\landmark_5\\result_img_96\\";
//pointVisibleLossPre(img_path, text_label, mclc, preRe, dpu, data);
//showVisibleError(data, preRe, NEED_LANDMARK);
std::system("PAUSE");
return 0;
}
Prepare data
#include "../data300w/util/Util.h"
#include "cunpd.hpp"
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
using namespace glasssix;
#define ZOOM 1.0
#define RESIZE 96
#define NEED_LANDMARK 5
#define CURRENT_LANDMARK 21
string search_base = "H:\\UMD\\";
string search_dir_[] = { search_base + "umdfaces_batch1", search_base + "umdfaces_batch2", search_base + "umdfaces_batch3"};
string text_file[] = { search_base +"umdfaces_batch1\\umdfaces_batch1_ultraface.csv", search_base + "umdfaces_batch2\\umdfaces_batch2_ultraface.csv", search_base + "umdfaces_batch3\\umdfaces_batch3_ultraface.csv" };
string text_pre[] = { "batch1_", "batch2_", "batch3_"};
string tail_[] = { ".jpg", ".jpg" , ".jpg" };
string base = search_base + "landmark_5\\";
string result_img = base + "result_img4_" + to_string(RESIZE) + "\\";
string result_txt = base + "landmark4_" + to_string(RESIZE) + "_5.txt";
const int five_point[5] = { 7, 10, 14, 17, 19};
int main11() {
// prepare data code.
cunpd *pd = new cunpd();
vector result_five_point;
int model_id = pd->AddNpdModel(0);
int faceNum = 0;
DataPrepareUtil dpUtil;
dpUtil.clearFileData(result_txt);
string base_dir = base;
if (_access(base_dir.c_str(), 0) == -1)
{
_mkdir(base_dir.c_str());
}
long count = 0;
for (int temp = 0; temp < 3; temp++)
{
long countNum = 0;
vector result_point;
dpUtil.readFileData(text_file[temp], result_point, CURRENT_LANDMARK);
for (vector::iterator itor = result_point.begin(); itor != result_point.end();)
{
if (count % 500 == 0)
{
cout << "prepare count is: " << count << " current img path is :" << result_point[0].fileName << endl;
}
count++;
Mat img;
int widths = 0, heights = 0;
Mat dstImg;
try {
string img_path = search_dir_[temp] + "\\" + result_point[0].fileName;
if (_access(img_path.c_str(), 0) == -1)
{
cout << "coun't found filename" << search_dir_[temp] + result_point[0].fileName << endl;
result_point.erase(itor);
continue;
}
img = imread(search_dir_[temp] + "\\" + result_point[0].fileName);
widths = img.cols;
heights = img.rows;
dstImg.create(heights, widths, CV_8UC1);
cvtColor(img, dstImg, CV_BGR2GRAY);
}
catch (Exception e)
{
cout << "exception:" << " current file:" << result_point[0].fileName << endl;
system("PAUSE");
}
//for (int k = 0; k < CURRENT_LANDMARK; k++)
//{
// circle(img, Point(result_point[0].points[k]), 2, Scalar(255, 0, 0));
// putText(img, to_string(k), Point(Point(result_point[0].points[k])), 0.3, 0.3, Scalar(255, 0, 0));
//}
//imshow("img", img);
//waitKey(0);
vector face = pd->detect(dstImg, model_id, 48);
LandMark landmark;
int length = face.size();
if (length == 0)
{
cout << "not found face ." << endl;
}
for (int j = 0; j < length; j++)
{
if (face[j].score > 15)
{
Rect rect = face[j].rect;
if (result_point[0].points[0].x > rect.x && result_point[0].points[0].x < rect.x + rect.width
&& result_point[0].points[0].y > rect.y && result_point[0].points[0].y < rect.y + rect.height
&&result_point[0].points[12].x > rect.x && result_point[0].points[12].x < rect.x + rect.width
&& result_point[0].points[12].y > rect.y && result_point[0].points[12].y < rect.y + rect.height
&&result_point[0].points[16].x > rect.x && result_point[0].points[16].x < rect.x + rect.width
&& result_point[0].points[16].y > rect.y && result_point[0].points[16].y < rect.y + rect.height
&&result_point[0].points[20].x > rect.x && result_point[0].points[20].x < rect.x + rect.width
&& result_point[0].points[20].y > rect.y && result_point[0].points[20].y < rect.y + rect.height
&& (abs(result_point[0].points[7].y - result_point[0].points[17].y) > (rect.height / 6.0)))
{
int rect_w = rect.width;
int rect_h = rect.height;
rect.width = rect_w * ZOOM;
rect.height = rect_h * ZOOM;
rect.x = max(rect.x - (ZOOM - 1.0) * rect_w / 2.0, 0.0);
rect.y = max(rect.y - (ZOOM - 1.0) * rect_h / 2.0, 0.0);
if (rect.x + rect.width > widths)
{
rect.width = widths - rect.x;
//rect.height = rect_h * rect.width / rect_w;
}
if (rect.y + rect.height > heights)
{
rect.height = heights - rect.y;
//rect.width = rect_w * rect.height / rect_h;
}
Mat roi_face, result_face;
roi_face = img(rect);
result_face.create(RESIZE, RESIZE, CV_8UC3);
cv::resize(roi_face, result_face, Size(RESIZE, RESIZE));
string dir = result_img;
if (_access(dir.c_str(), 0) == -1)
{
_mkdir(dir.c_str());
}
imwrite(dir + text_pre[temp] + to_string(countNum) + ".png", result_face);
landmark.fileName = text_pre[temp] + to_string(countNum) + ".png";
countNum++;
//坐标转换
//double t0 = (double)cvGetTickCount();
//#pragma omp parallel for num_threads(4)
for (int k = 0; k < NEED_LANDMARK; k++)
{
landmark.visible[k] = result_point[0].visible[five_point[k]];
if (result_point[0].points[five_point[k]].x == -1 || result_point[0].points[five_point[k]].y == -1) {
cout << "this points is NULL" << endl;
continue;
}
landmark.points[k].x = ((float)RESIZE / rect.width) * (result_point[0].points[five_point[k]].x - rect.x);
landmark.points[k].y = ((float)RESIZE / rect.height) * (result_point[0].points[five_point[k]].y - rect.y);
}
faceNum++;
result_five_point.push_back(landmark);
if (result_five_point.size() >= 1000)
{
dpUtil.writePointVisibletoFile(result_txt, result_five_point, NEED_LANDMARK);
result_five_point.clear();
}
//for (int k = 0; k < 5; k++)
//{
// circle(result_face, Point(landmark.points[k]), 2, Scalar(255, 0, 0));
//}
//imshow("img", result_face);
//waitKey(0);
break;
}
}
}
result_point.erase(itor);
}
}
if (result_five_point.size() > 0)
{
dpUtil.writePointVisibletoFile(result_txt, result_five_point, NEED_LANDMARK);
result_five_point.clear();
}
std::system("PAUSE");
delete pd;
return 0;
}
Argument data
#include
#include
#include "../data300w/util/Util.h"
#include "cunpd.hpp"
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
using namespace glasssix;
#define ZOOM_ 1.0
#define SIZE 96
extern void splitString(const string& s, vector& v, const string& c);
template
Type stringToNum(const string& str)
{
istringstream iss(str);
Type num;
iss >> num;
return num;
}
void writeHistoFile(std::string filePath, vector & densi_data)
{
if (filePath == "" || densi_data.size() == 0)
{
return;
}
ofstream in;
in.open(filePath, ios::app); //ios::trunc
int length = densi_data.size();
for (int i = 0; i < length; i++)
{
string dataline = to_string(densi_data[i]);
in << dataline << "\n";
}
in.close();
}
float getHorizontal(LandMark &landmark)
{
float tan_theta = (landmark.points[1].y - landmark.points[0].y) / (landmark.points[1].x - landmark.points[0].x);
float theta = atan(tan_theta);
return theta * 180 / 3.1415926;
}
void showHistogram(vector & hor_data)
{
int densi[60] = { 0 };
int length = hor_data.size();
for (int i = 0; i < length; i++)
{
if (floor((hor_data[i] + 30)) >= 0 && floor((hor_data[i] + 30)) < 60)
{
densi[(int)floor((hor_data[i] + 30))]++;
}
if (floor((hor_data[i] + 30)) < 0)
{
densi[0]++;
}
else if (floor((hor_data[i] + 30)) >= 60)
{
densi[60]++;
}
}
string density_text = "D:\\UMD\\density_text.txt";
vectordensity_data(densi, densi + 60);
writeHistoFile(density_text, density_data);
Mat histImg;
histImg.create(1000, 1600, CV_8UC3);
histImg.setTo(0);
int offset = 10;
for (int i = 0; i < 60; i++)
{
double tmpCount = densi[i];
rectangle(histImg, Point2f(offset + i * 25, 1000), Point2f(offset + i * 25, 1000 - tmpCount / 15.0), Scalar::all(255), -1); //画出直方图
putText(histImg, to_string(i - 29), Point2f(offset + i * 25 + 3, 1000 - 3), 0.3, 0.3, Scalar(0, 0, 255));
Point2f pt0;
pt0.x = offset + i * 25;
pt0.y = 1000 - densi[i] / 15.0;
Point2f pt1;
pt1.x = offset + (i + 1) * 25;
pt1.y = 1000 - densi[i + 1] / 15.0;
line(histImg, pt0, pt1, Scalar(255, 0, 0), 1); //连接直方图的顶点
}
imshow("hist", histImg);
waitKey(0);
}
void getDatahor(string file1, vector & hor_data)
{
int mark_num = 5;
DataPrepareUtil dpu;
vector data;
dpu.readFileData(file1, data, mark_num);
int length = data.size();
for (int i = 0; i < length; i++)
{
float hor = getHorizontal(data[i]);
hor_data.emplace_back(hor);
}
}
void rotation(float theta, Mat &img, Mat &dst, Size img_size, LandMark &landmark, int mark_num)
{
//rotation
Mat mat = img;
Point2f center(img_size.width / 2, img_size.height / 2);
double angle = theta;
Mat rot = getRotationMatrix2D(center, angle, 1);
Rect bbox = RotatedRect(center, mat.size(), angle).boundingRect();
cv::warpAffine(mat, dst, rot, bbox.size());
for (int j = 0; j < mark_num; j++)
{
float theta = -3.1415926 / (180 / angle);
float x1 = landmark.points[j].x - rot.at(1, 2);
float y1 = landmark.points[j].y - rot.at(0, 2);
landmark.points[j].x = x1 * cos(theta) - y1 * sin(theta);
landmark.points[j].y = x1 * sin(theta) + y1 * cos(theta);
//circle(dst, Point(x, y), 2, Scalar(255, 0, 0));
}
//cv::imshow("dst", dst);
//cv::waitKey(0);
}
void augment_data(string img_path, string img_text, string result_path, string result_text)
{
DataPrepareUtil dpu;
int mark_num = 5;
srand((unsigned)time(NULL));
vector data;
dpu.readFileData(img_text, data, mark_num);
vector rotation_data;
vector hor_data;
getDatahor(img_text, hor_data);
int length = hor_data.size();
for (int i = 0; i < length; i++)
{
if (hor_data[i] > 0 && hor_data[i] < 3)
{
Mat dst;
Mat img = imread(img_path + data[i].fileName);
LandMark landmark(data[i]);
rotation(25, img, dst, Size(96, 96), landmark, mark_num);
rotation_data.push_back(landmark);
}
}
}
bool getFaceRect(cunpd &pd, int model_id, Mat &dstImg, LandMark & landmark, Rect & rect)
{
const int widths = dstImg.cols;
const int heights = dstImg.rows;
vector face = pd.detect(dstImg, model_id, 48);
int length = face.size();
if (length == 0)
{
cout << "not found face ." << endl;
}
for (int j = 0; j < length; j++)
{
if (face[j].score > 15)
{
rect = face[j].rect;
if (landmark.points[0].x > rect.x && landmark.points[0].x < rect.x + rect.width
&& landmark.points[0].y > rect.y && landmark.points[0].y < rect.y + rect.height
&&landmark.points[12].x > rect.x && landmark.points[12].x < rect.x + rect.width
&& landmark.points[12].y > rect.y && landmark.points[12].y < rect.y + rect.height
&&landmark.points[16].x > rect.x && landmark.points[16].x < rect.x + rect.width
&& landmark.points[16].y > rect.y && landmark.points[16].y < rect.y + rect.height
&&landmark.points[20].x > rect.x && landmark.points[20].x < rect.x + rect.width
&& landmark.points[20].y > rect.y && landmark.points[20].y < rect.y + rect.height
&& (abs(landmark.points[7].y - landmark.points[17].y) > (rect.height / 6.0)))
{
int rect_w = rect.width;
int rect_h = rect.height;
rect.width = rect_w * ZOOM_;
rect.height = rect_h * ZOOM_;
rect.x = max(rect.x - (ZOOM_ - 1.0) * rect_w / 2.0, 0.0);
rect.y = max(rect.y - (ZOOM_ - 1.0) * rect_h / 2.0, 0.0);
if (rect.x + rect.width > widths)
{
rect.width = widths - rect.x;
}
if (rect.y + rect.height > heights)
{
rect.height = heights - rect.y;
}
return true;
}
}
}
return false;
}
void getoffsetRect(Rect & rect, vector & all_rect, int cols, int rows, int max_offset)
{
srand((unsigned)time(NULL));
Rect rect0(rect), rect1(rect);
int offsetx = rand() % max_offset + 1;
int offsety = rand() % max_offset + 1;
if (rect.x > offsetx && rect.y > offsety)
{
rect0.x = rect.x - offsetx;
rect0.y = rect.y - offsety;
}
offsetx = rand() % max_offset + 1;
offsety = rand() % max_offset + 1;
if (rect.x + rect.width + offsetx < cols && rect.y + rect.height + offsety < rows)
{
rect1.x = rect.x + offsetx;
rect1.y = rect.y + offsety;
}
all_rect.push_back(rect0);
all_rect.push_back(rect1);
}
#define NEED_LANDMARK 5
#define CURRENT_LANDMARK 21
const int five_points[5] = { 7, 10, 14, 17, 19 };
string search_base = "H:\\UMD\\";
string search_dir_[] = { search_base + "umdfaces_batch1", search_base + "umdfaces_batch2", search_base + "umdfaces_batch3" };
string text_file[] = { search_base + "umdfaces_batch1\\umdfaces_batch1_ultraface.csv", search_base + "umdfaces_batch2\\umdfaces_batch2_ultraface.csv", search_base + "umdfaces_batch3\\umdfaces_batch3_ultraface.csv" };
string text_pre[] = { "batch1_aug_", "batch2_aug_", "batch3_aug_" };
string tail_[] = { ".jpg", ".jpg" , ".jpg" };
string base = search_base + "landmark_5\\augment_img\\";
string result_img = base + "result_img_" + to_string(SIZE) + "\\";
string result_txt = base + "landmark_" + to_string(SIZE) + "_5.txt";
const int theta_offset = 5;
const int theta_max = 20;
vector rotation_point;
int countNum = 0;
bool ready = false;
std::mutex mtx_syn;
std::condition_variable cv_syn;
void roll_yaw_pitch_data(LandMark result_mark, int temp, cunpd &pd, int model_id, DataPrepareUtil &dpu)
{
float roll = result_mark.direct[2];
string img_path = search_dir_[temp] + "\\" + result_mark.fileName;
if (_access(img_path.c_str(), 0) == -1)
{
cout << "coun't found filename" << img_path << endl;
return;
}
Mat img = imread(img_path);
Mat dstImg; //dstImg.create(heights, widths, CV_8UC1);
cvtColor(img, dstImg, CV_BGR2GRAY);
//yaw 增强 pitch 增强
for (int j = 0; j < 2; j++)
{
if (result_mark.direct[j] > -theta_offset && result_mark.direct[j] < theta_offset)
{
Rect rect;
LandMark landmark(result_mark);
bool success = getFaceRect(pd, model_id, dstImg, landmark, rect);
if (success)
{
vector all_rect;
getoffsetRect(rect, all_rect, img.cols, img.rows, 4);
for (int i = 0; i < 2; i++)
{
LandMark dst_landmark;
//vector filenames;
//splitString(landmark.fileName, filenames, "/");
//string filename = filenames[filenames.size()-1];
std::unique_lock lck(mtx_syn);
dst_landmark.fileName = text_pre[temp] + to_string(countNum++) + ".png";
lck.unlock();
//cout << img.rows << " " << rotat_img.cols << " " << rect.x << " " << rect.y << " " << rect.width << " " << rect.height << endl;
Mat roi_face = img(all_rect[i]);
cv::resize(roi_face, roi_face, Size(SIZE, SIZE));
//坐标转换
for (int k = 0; k < 5; k++)
{
dst_landmark.visible[k] = landmark.visible[five_points[k]];
dst_landmark.points[k].x = ((float)SIZE / all_rect[i].width) * (landmark.points[five_points[k]].x - all_rect[i].x);
dst_landmark.points[k].y = ((float)SIZE / all_rect[i].height) * (landmark.points[five_points[k]].y - all_rect[i].y);
}
imwrite(result_img + dst_landmark.fileName, roi_face);
std::unique_lock lck1(mtx_syn);
rotation_point.push_back(dst_landmark);
lck1.unlock();
}
}
}
}
// roll 增强
if (roll > -theta_offset && roll < theta_offset)
{
for (int i = -1; i < 2; i = i + 2)
{
Mat rotat_img;
LandMark landmark(result_mark);
int theta = (rand() % theta_max + theta_offset) * i;
rotation(theta, img, rotat_img, Size(SIZE, SIZE), landmark, CURRENT_LANDMARK);
Mat dstImg; //dstImg.create(heights, widths, CV_8UC1);
cvtColor(rotat_img, dstImg, CV_BGR2GRAY);
//for (int j = 0; j < CURRENT_LANDMARK; j++)
//{
// circle(rotat_img, Point(landmark.points[j]), 2, Scalar(255, 0, 0));
//}
//imshow("img", rotat_img);
//waitKey(0);
LandMark dst_landmark;
//vector filenames;
//splitString(landmark.fileName, filenames, "/");
//string filename = filenames[filenames.size()-1];
std::unique_lock lck(mtx_syn);
dst_landmark.fileName = text_pre[temp] + to_string(countNum++) + ".png";
lck.unlock();
Rect rect;
bool success = getFaceRect(pd, model_id, dstImg, landmark, rect);
if (success)
{
//cout << rotat_img.rows << " " << rotat_img.cols << " " << rect.x << " " << rect.y << " " << rect.width << " " << rect.height << endl;
Mat roi_face = rotat_img(rect);
cv::resize(roi_face, roi_face, Size(SIZE, SIZE));
//坐标转换
for (int k = 0; k < 5; k++)
{
dst_landmark.visible[k] = landmark.visible[five_points[k]];
dst_landmark.points[k].x = ((float)SIZE / rect.width) * (landmark.points[five_points[k]].x - rect.x);
dst_landmark.points[k].y = ((float)SIZE / rect.height) * (landmark.points[five_points[k]].y - rect.y);
}
imwrite(result_img + dst_landmark.fileName, roi_face);
std::unique_lock lck(mtx_syn);
rotation_point.push_back(dst_landmark);
if (rotation_point.size() > 500)
{
dpu.writePointVisibletoFile(result_txt, rotation_point, NEED_LANDMARK);
rotation_point.clear();
}
if (countNum % 500 == 0)
{
cout << "prepare data:" << countNum << endl;
}
lck.unlock();
}
}
}
}
vector result_point;
void deal_thread(int temp, int model_id, DataPrepareUtil &dpu, cunpd &pd)
{
while (true)
{
std::unique_lock lck(mtx_syn);
while (!ready) {
cv_syn.wait(lck);
}
//
auto itor = result_point.begin();
auto itor2 = result_point.end();
if (itor == itor2)
{
break;
}
LandMark landmark(result_point[0]);
result_point.erase(itor);
// cout << "landmark.fileName is:"< lck(mtx_syn);
ready = true;
cv_syn.notify_all();
}
int main()
{
cunpd pd;
int model_id = pd.AddNpdModel(0);
// 查看数据分布
//string file1 = "D:\\UMD\\landmark_128_5.txt";
//vector hor_data;
//getDatahor(file1, hor_data);
//showHistogram(hor_data);
/*string img_path = "D:\\UMD\\result_img_96\\";
string result_path = "D:\\UMD\\arguement_data\\";
string img_text = img_path + "shutter_96_5_train.txt";
string result_text = result_path + "augment_96_5_train.txt";
augment_data(img_path, img_text, result_path, result_text);*/
string base_dir = base;
if (_access(base_dir.c_str(), 0) == -1)
{
_mkdir(base_dir.c_str());
}
string dir = result_img;
if (_access(dir.c_str(), 0) == -1)
{
_mkdir(dir.c_str());
}
srand((unsigned)time(NULL));
DataPrepareUtil dpUtil;
dpUtil.clearFileData(result_txt);
long count = 0;
vector rotation_point;
for (int temp = 0; temp < 3; temp++)
{
long countNum = 0;
//vector result_point;
dpUtil.readFileData(text_file[temp], result_point, CURRENT_LANDMARK);
std::thread threads[4];
for (int i = 0; i < 4; i++)
{
threads[i] = std::thread(deal_thread, temp, model_id, dpUtil, pd);
//threads[i] = std::thread(threadA, i, result_point, temp, model_id, dpUtil, pd);
}
cout << "temp start:" << temp << endl;
go();
for (auto &th : threads) {
th.join();
}
cout << "temp end:" << temp << endl;
//for (vector::iterator itor = result_point.begin(); itor != result_point.end();)
//{
// if (count % 500 == 0)
// {
// cout << "prepare count is: " << count << " current img path is :" << result_point[0].fileName << endl;
// }
// count++;
/*
float yaw = result_point[0].direct[0];
float pitch = result_point[0].direct[1];
float roll = result_point[0].direct[2];
string img_path = search_dir_[temp] + "\\" + result_point[0].fileName;
if (_access(img_path.c_str(), 0) == -1)
{
cout << "coun't found filename" << img_path << endl;
result_point.erase(itor);
continue;
}
Mat img = imread(img_path);
Mat dstImg; //dstImg.create(heights, widths, CV_8UC1);
cvtColor(img, dstImg, CV_BGR2GRAY);
//yaw 增强 pitch 增强
for (int j = 0; j < 2; j++)
{
if (result_point[0].direct[j] > -theta_offset && result_point[0].direct[j] < theta_offset)
{
Rect rect;
LandMark landmark(result_point[0]);
bool success = getFaceRect(pd, model_id, dstImg, landmark, rect);
if (success)
{
vector all_rect;
getoffsetRect(rect, all_rect, img.cols, img.rows, 4);
for (int i = 0; i < 2; i++)
{
LandMark dst_landmark;
//vector filenames;
//splitString(landmark.fileName, filenames, "/");
//string filename = filenames[filenames.size()-1];
dst_landmark.fileName = text_pre[temp] + to_string(countNum) + ".png";
//cout << img.rows << " " << rotat_img.cols << " " << rect.x << " " << rect.y << " " << rect.width << " " << rect.height << endl;
Mat roi_face = img(all_rect[i]);
cv::resize(roi_face, roi_face, Size(SIZE, SIZE));
//坐标转换
for (int k = 0; k < 5; k++)
{
dst_landmark.visible[k] = landmark.visible[five_points[k]];
dst_landmark.points[k].x = ((float)SIZE / all_rect[i].width) * (landmark.points[five_points[k]].x - all_rect[i].x);
dst_landmark.points[k].y = ((float)SIZE / all_rect[i].height) * (landmark.points[five_points[k]].y - all_rect[i].y);
}
imwrite(result_img + dst_landmark.fileName, roi_face);
rotation_point.push_back(dst_landmark);
countNum++;
}
}
}
}
// roll 增强
if (roll > -theta_offset && roll < theta_offset)
{
for (int i = -1; i < 2; i = i + 2)
{
Mat rotat_img;
LandMark landmark(result_point[0]);
int theta = (rand() % theta_max + theta_offset) * i;
rotation(theta, img, rotat_img, Size(SIZE, SIZE), landmark, CURRENT_LANDMARK);
Mat dstImg; //dstImg.create(heights, widths, CV_8UC1);
cvtColor(rotat_img, dstImg, CV_BGR2GRAY);
//for (int j = 0; j < CURRENT_LANDMARK; j++)
//{
// circle(rotat_img, Point(landmark.points[j]), 2, Scalar(255, 0, 0));
//}
//imshow("img", rotat_img);
//waitKey(0);
LandMark dst_landmark;
//vector filenames;
//splitString(landmark.fileName, filenames, "/");
//string filename = filenames[filenames.size()-1];
dst_landmark.fileName = text_pre[temp] + to_string(countNum) + ".png";
Rect rect;
bool success = getFaceRect(pd, model_id, dstImg, landmark, rect);
if (success)
{
//cout << rotat_img.rows << " " << rotat_img.cols << " " << rect.x << " " << rect.y << " " << rect.width << " " << rect.height << endl;
Mat roi_face = rotat_img(rect);
cv::resize(roi_face, roi_face, Size(SIZE, SIZE));
//坐标转换
for (int k = 0; k < 5; k++)
{
dst_landmark.visible[k] = landmark.visible[five_points[k]];
dst_landmark.points[k].x = ((float)SIZE / rect.width) * (landmark.points[five_points[k]].x - rect.x);
dst_landmark.points[k].y = ((float)SIZE / rect.height) * (landmark.points[five_points[k]].y - rect.y);
}
imwrite(result_img + dst_landmark.fileName, roi_face);
rotation_point.push_back(dst_landmark);
countNum++;
}
}
}
*/
//}
}
if (rotation_point.size() > 0)
{
dpUtil.writePointVisibletoFile(result_txt, rotation_point, NEED_LANDMARK);
rotation_point.clear();
}
system("PAUSE");
return 0;
}