300W数据集测试MTCNN的landmark效果,用提取其中afw数据集337张图片的预测关键点并写入到txt中,再用测试程序和标注landmark做对比。
处理得到的预测landmark格式如下:
1051618982(图片名)
1(landmark个数)
543 267 643 268 594 322 542 359 643 360
111076519
2
1095 624 1161 635 1125 668 1084 696 1146 706
1172 764 1238 767 1211 806 1168 830 1233 833
1130084326
程序如下:
#include "network.h" #include "mtcnn.h" #include <time.h> #include <fstream> #include <opencv2/opencv.hpp> #pragma comment(lib, "libopenblas.dll.a") using namespace cv; std::vector<std::string> split(std::string& str, std::string& pattern); void str2int(int &int_temp, const string &string_temp); int main() { //因为执行目录被设置到openblas/x64下了,保证dll能正常载入,这时候图片路径就相对要提上去2级 //Mat im = imread("../../test10.jpg"); int i = 0; string img_dir = "E:/face_alignment/data/300W_test_5points/afw/"; string name, s="_"; ifstream infile; ofstream outfile; infile.open("E:/face_alignment/data/300W_test_5points/afw_mtcnn_test_V2_2.txt"); outfile.open("E:/face_alignment/data/300W_test_5points/MTCNN_V2_2_test/afw_test.txt"); while (infile) { infile >> name; vector<string> result = split(name, s); cout << i << endl; i++; //cout << "name: " << result[0] << " s: " << result[1] << endl; string shot_name = result[0]; int decide; str2int(decide, result[1]); if (decide == 1) { string image_name = name + ".jpg"; outfile << shot_name << endl; string image_name_dir = img_dir + image_name; cout << image_name_dir << endl; Mat im = imread(image_name_dir); vector<vector<Point2f>> key_points; mtcnn find(im.cols, im.rows); vector<Rect> objs = find.detectObject(im, key_points); //outfile << objs.size() << endl; for (int i = 0; i < objs.size(); ++i) { rectangle(im, objs[i], Scalar(0, 255), 2); //outfile << objs[i].x << " " << objs[i].y << " " << objs[i].width << " " << objs[i].height << endl; } //cout << "num of key_points: " << key_points.size() << endl; outfile << key_points.size() << endl; for (int i = 0; i < key_points.size(); i++) { for (int j = 0; j < key_points[i].size(); j++) { cv::circle(im, key_points[i][j], 1, cv::Scalar(255, 255, 0), 2); outfile << key_points[i][j].x << " " << key_points[i][j].y << " "; } outfile << endl; } string outdir = "E:/face_alignment/data/300W_test_5points/MTCNN_V2_2_test/afw/"; string out_image = outdir + shot_name + ".jpg"; imwrite(out_image, im); //imshow("demo", im); //waitKey(0); } } infile.close(); outfile.close(); return 0; } //字符串分割函数 std::vector<std::string> split(std::string& str, std::string& pattern) { std::string::size_type pos; std::vector<std::string> result; //str += pattern;//扩展字符串以方便操作 int size = str.size(); pos = str.find(pattern, 0); if (pos<size) { std::string s1 = str.substr(0, pos); std::string s2 = str.substr(pos + 1, size - 1); result.push_back(s1); result.push_back(s2); } return result; } void str2int(int &int_temp, const string &string_temp) { stringstream stream(string_temp); stream >> int_temp; }
用我们自己得到的预测txt,与作者提供的标注pts文件进行计算。 算5个landmark的欧式距离之和,除以左上角和右下角欧式距离,除以5。
#include <iostream> #include <stdlib.h> #include <fstream> #include <sstream> #include <string> #include <vector> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; std::vector<std::string> split(std::string& str, std::string& pattern); void str2int(int &int_temp, const string &string_temp); float computer_error(vector<float> pts_gt, vector<vector<float>> pts_pre); int main() { int count = 0, pos = 0; float acc, thread=0.1; string name_list, s = "_"; string pts_dir = "E:/face_alignment/data/300W_test_5points/afw/"; ifstream infile_list, infile_pre; infile_list.open("E:/face_alignment/data/300W_test_5points/afw_mtcnn_test_V1.txt"); infile_pre.open("E:/face_alignment/data/300W_test_5points/MTCNN_V1_test/afw_test.txt"); infile_list >> name_list; while (infile_pre) { string name_pre; int num_pre; vector<vector<float> > pts_pre; infile_pre >> name_pre; infile_pre >> num_pre; pts_pre.resize(num_pre); for (int i = 0; i < num_pre; i++) { pts_pre[i].resize(10); } for (int j = 0; j < num_pre; j++) { infile_pre >> pts_pre[j][0] >> pts_pre[j][1] >> pts_pre[j][2] >> pts_pre[j][3] >> pts_pre[j][4] >> pts_pre[j][5] >> pts_pre[j][6] >> pts_pre[j][7] >> pts_pre[j][8] >> pts_pre[j][9]; } //for (int i = 0; i < num_pre; i++) //{ // for (int j = 0; j < 10; j++) // { // cout << pts_pre[i][j] << " "; // } // cout << endl; //} // read gt file while (infile_list) { vector<string> result = split(name_list, s); string name_gt = result[0]; if (name_gt.compare(name_pre) == 0) { count++; cout << count << endl; vector<float> pts_gt; pts_gt.resize(10); string pts_dir_name = pts_dir + name_list + ".pts"; ifstream infile_pts; infile_pts.open(pts_dir_name); string ss; int yy; infile_pts >> ss >> yy; infile_pts >> ss >> yy; infile_pts >> ss; for (int i = 0; i < 5; i++) { infile_pts >> pts_gt[i*2] >> pts_gt[i*2+1]; } infile_pts.close(); float error = computer_error(pts_gt, pts_pre); error = error / 5.0; if (error <= thread) pos++; cout << error << " " << endl; infile_list >> name_list; //cout << name_list << endl; } else break; } } acc = float(pos) / float(count); cout << "accury: " << acc << endl; infile_list.close(); infile_pre.close(); } // computer alinment loss float computer_error(vector<float> pts_gt, vector<vector<float>> pts_pre) { if (pts_pre.size() == 0) return 10; float RMSE, d_outer, align_loss; d_outer = sqrt((pts_gt[0] - pts_gt[8])*(pts_gt[0] - pts_gt[8]) + (pts_gt[1] - pts_gt[9])*(pts_gt[1] - pts_gt[9])); for (int i = 0; i < pts_pre.size(); i++) { RMSE = 0; for (int j = 0; j < 5; j++) { RMSE += sqrt((pts_gt[2 * j] - pts_pre[i][2 * j])*(pts_gt[2 * j] - pts_pre[i][2 * j]) + (pts_gt[2 * j + 1] - pts_pre[i][2 * j + 1])*(pts_gt[2 * j + 1] - pts_pre[i][2 * j + 1])); } RMSE = RMSE / d_outer; if (i == 0) { align_loss = RMSE; } else { if (align_loss > RMSE) align_loss = RMSE; } } return align_loss; } //字符串分割函数 std::vector<std::string> split(std::string& str, std::string& pattern) { std::string::size_type pos; std::vector<std::string> result; //str += pattern;//扩展字符串以方便操作 int size = str.size(); pos = str.find(pattern, 0); if (pos<size) { std::string s1 = str.substr(0, pos); std::string s2 = str.substr(pos + 1, size - 1); result.push_back(s1); result.push_back(s2); } return result; } void str2int(int &int_temp, const string &string_temp) { stringstream stream(string_temp); stream >> int_temp; }