3dmm计算特征向量,c++读写txt和二进制记录

头文件 read.h

#ifndef READ_H_
#define READ_H_ 

class Read {
public:
	Read();
	void cal();
	double** get_vec();
	double* get_val();
	double* get_M();
};

#endif

read.cpp

#include 
#include 
#include "Eigen/Dense"
#include "read.h"
using namespace std;
using namespace Eigen;
const int n = 11510 * 3, m = 150;
double **vec, *val, *M;

Read::Read() {

}

void Read::cal() {
	double tp;
	ifstream in("D:\\hx\\data\\result.dat", ios::in | ios::binary);
	vec = (double**)new double*[n];
	for (int i = 0; i < n; i++) {
		*(vec + i) = new double[m];
		for (int j = 0; j < m; j++) {
			in.read((char*)& tp, sizeof(tp));
			vec[i][j] = tp;
		}
	}

	val = new double[m];
	for (int i = 0; i < m; i++) {
		in.read((char*)& tp, sizeof(tp));
		
		val[i] = tp;
	}

	M = new double[n];
	for (int i = 0; i < n; i++) {
		in.read((char*)& tp, sizeof(tp));
		M[i] = tp;
	}
}

double** Read::get_vec() {
	return vec;
}

double* Read::get_val() {
	return val;
}

double* Read::get_M() {
	return M;
}

其他各个操作...

3dMM计算特征值特征向量存在二进制文件中,封装上面这个read类用来访问。read部分是测试读取,test部分是测试特征向量有没有设置对(随便取几组参数看看人脸形状)。

#include
#include
#include
#include
#include "Eigen/Dense"
#include 
#include 
#include "read.h"
using namespace std;
using namespace Eigen;
const int n = 11510*3, m = 150;
MatrixXd X(n, m), C(m, m);
VectorXd M,A,B;
MatrixXd vec, val;
double** ans_vec;
double *ans_val, *ans_M;

string s = "D:\\hx\\data\\FaceWarehouse_Data_0\\Tester_";
void featurenormalize(MatrixXd &X, VectorXd &M)
{
	
	//计算每一维度均值
	MatrixXd meanval = X.rowwise().mean();
    M = meanval; //VectorXd 就是列向量 RowVectorXd 是行向量
	//样本均值化为0
	X.colwise() -= M;
}
void computeCov(MatrixXd &X, MatrixXd &C)
{
	//计算协方差矩阵C = XTX / (m-1);
	C = X.adjoint() * X;
	C = C.array() / (m-1);
}
void computeEig(MatrixXd &C, MatrixXd &vec, MatrixXd &val)
{
	//计算特征值和特征向量,使用selfadjont按照对称矩阵的算法去计算,可以让产生的vec和val按照有序排列
	SelfAdjointEigenSolver eig(C);
 
	vec = eig.eigenvectors();
	val = eig.eigenvalues();
}

int main()
{
	clock_t start, finish;
	start = clock();
	//读取数据
	for (int i = 1; i <= m; i++) {
		stringstream ss;
		ss << i;
		string num = ss.str();
		string file = s + num + "\\Blendshape\\shape_0.obj";
		ifstream in(file);
		string a;
		double x,y,z;
		int k = 0;
		while (!in.eof()) {
			in >> a;
			if (a[0] == 'v' && a.length()==1) {
				in >> x;
				X(k++, i - 1) = x;
				in >> y;
				X(k++, i - 1) = y;
				in >> z;
				X(k++, i - 1) = z;
			}
		}
	}

	

	//零均值化
	featurenormalize(X, M);

	//计算协方差
	computeCov(X, C);

	//计算特征值和特征向量
	computeEig(C, vec, val);

	vec = X * vec;
	
	ofstream out("D:\\hx\\data\\result.dat", ios::out | ios::binary);
	for (int j = 0; j < n; j++) {
		for (int i = m-1; i >=0; i--) {
			out.write((char*)& vec(j,i), sizeof(double));
		}
	}
	for (int i = m-1; i>=0; i--) {
		out.write((char*)& val(i), sizeof(double));
	}
	for (int i = 0; i < n; i++) {
		out.write((char*)& M(i), sizeof(double));
	}
	cout << "finish" << endl;
	finish = clock();
	cout << "time:" << (double)(finish - start) / CLOCKS_PER_SEC << endl;

	//read
	
	Read r;
	r.cal();
	ans_val = r.get_val();
	for (int i = 0; i < m; i++) {
		cout << ans_val[i] << endl;
	}
	

	//test
	string obj_M = "D:\\hx\\data\\meanS.obj";
	string obj_A = "D:\\hx\\data\\A.obj";
	string obj_B = "D:\\hx\\data\\B.obj";
	ofstream out_objM(obj_M);
	ofstream out_objA(obj_A);
	

	for (int i = 0; i < n; i += 3) {
		out_objM << "v " << M(i) << " " << M(i + 1) << " " << M(i + 2) << endl;
	}

	int change = m - 5;
	A = M;

	for (int i = 0; i < n; i ++) {
		for (int j = 1; j < change; j++) {
			A(i) += (0.1/148)*vec(i, j);
		}
		A(i) += 0.9*vec(i, change);
		for (int k = change+1; k < m; k++) {
			A(i) += (0.1 / 148)*vec(i, k);
		}
	}

	for (int i = 0; i < n; i += 3) {
		out_objA << "v " << A(i) << " " << A(i + 1) << " " << A(i + 2) << endl;
	}

	string get_face = "D:\\hx\\data\\1.txt";
	ifstream read(get_face);
	while (!read.eof()) {
		string tmp;
		read >> tmp;
		char flag = tmp[0];
		out_objA << tmp <<" ";
		read >> tmp;
		out_objA << tmp << " ";
		read >> tmp;
		out_objA << tmp << " ";
		if (flag == 'f') {
			read >> tmp;
			out_objA << tmp << " ";
			read >> tmp;
			out_objA << tmp << " ";
		}
		out_objA << endl;
	}

	int K = 1;
	while (K++) {
		cin >> change;
		stringstream ss;
		ss << K;
		string num = ss.str();
		string s = "D:\\hx\\data\\B"+num+".obj";
		ofstream out_objB(s);

		B = M;
		for (int i = 0; i < n; i++) {
			for (int j = 1; j < change; j++) {
				B(i) += (0.1 / 148)*vec(i, j);
			}
			B(i) += 0.9*vec(i, change);
			for (int k = change + 1; k < m; k++) {
				B(i) += (0.1 / 148)*vec(i, k);
			}
		}

		for (int i = 0; i < n; i += 3) {
			out_objB << "v " << B(i) << " " << B(i + 1) << " " << B(i + 2) << endl;
		}

		ifstream read1(get_face);

		while (!read1.eof()) {
			string tmp;
			read1 >> tmp;
			char flag = tmp[0];
			out_objB << tmp << " ";
			read1 >> tmp;
			out_objB << tmp << " ";
			read1 >> tmp;
			out_objB << tmp << " ";
			if (flag == 'f') {
				read1 >> tmp;
				out_objB << tmp << " ";
				read1 >> tmp;
				out_objB << tmp << " ";
			}
			out_objB << endl;
		}
		read1.close();
		read1.clear();
		out_objB.close();
		cout << "done" << endl;

	}
	
	return 0;
}

 

你可能感兴趣的:(3DMM)