v2.0.0
Loading...
Searching...
No Matches
warp.cpp
Go to the documentation of this file.
1//=============================================================================================================
26
27//=============================================================================================================
28// INCLUDES
29//=============================================================================================================
30
31#include "warp.h"
32
33#include <iostream>
34#include <fstream>
35
36//=============================================================================================================
37// EIGEN INCLUDES
38//=============================================================================================================
39
40#include <Eigen/LU>
41
42//=============================================================================================================
43// QT INCLUDES
44//=============================================================================================================
45
46#include <QDebug>
47#include <QFile>
48#include <QList>
49#include <QRegularExpression>
50
51//=============================================================================================================
52// USED NAMESPACES
53//=============================================================================================================
54
55using namespace UTILSLIB;
56using namespace Eigen;
57
58//=============================================================================================================
59// DEFINE MEMBER METHODS
60//=============================================================================================================
61
62MatrixXf Warp::calculate(const MatrixXf &sLm, const MatrixXf &dLm, const MatrixXf &sVert)
63{
64 MatrixXf warpWeight, polWeight;
65 calcWeighting(sLm, dLm, warpWeight, polWeight);
66 MatrixXf wVert = warpVertices(sVert, sLm, warpWeight, polWeight);
67 return wVert;
68}
69
70//=============================================================================================================
71
72void Warp::calculate(const MatrixXf & sLm, const MatrixXf &dLm, QList<MatrixXf> & vertList)
73{
74 MatrixXf warpWeight, polWeight;
75 calcWeighting(sLm, dLm, warpWeight, polWeight);
76
77 for (int i=0; i<vertList.size(); i++)
78 {
79 vertList.replace(i,warpVertices(vertList.at(i), sLm, warpWeight, polWeight));
80 }
81 return;
82}
83
84//=============================================================================================================
85
86bool Warp::calcWeighting(const MatrixXf &sLm, const MatrixXf &dLm, MatrixXf& warpWeight, MatrixXf& polWeight)
87{
88 MatrixXf K = MatrixXf::Zero(sLm.rows(),sLm.rows()); //K(i,j)=||sLm(i)-sLm(j)||
89 for (int i=0; i<sLm.rows(); i++)
90 K.col(i)=((sLm.rowwise()-sLm.row(i)).rowwise().norm());
91
92// std::cout << "Here is the matrix K:" << std::endl << K << std::endl;
93
94 MatrixXf P (sLm.rows(),4); //P=[ones,sLm]
95 P << MatrixXf::Ones(sLm.rows(),1),sLm;
96// std::cout << "Here is the matrix P:" << std::endl << P << std::endl;
97
98 MatrixXf L ((sLm.rows()+4),(sLm.rows()+4)); //L=Full Matrix of the linear eq.
99 L << K,P,
100 P.transpose(),MatrixXf::Zero(4,4);
101// std::cout << "Here is the matrix L:" << std::endl << L << std::endl;
102
103 MatrixXf Y ((dLm.rows()+4),3); //Y=[dLm,Zero]
104 Y << dLm,
105 MatrixXf::Zero(4,3);
106// std::cout << "Here is the matrix Y:" << std::endl << Y << std::endl;
107
108 //
109 // calculate the weighting matrix (Y=L*W)
110 //
111 MatrixXf W ((dLm.rows()+4),3); //W=[warpWeight,polWeight]
112 Eigen::FullPivLU <MatrixXf> Lu(L); //LU decomposition is one method to solve lin. eq.
113 W=Lu.solve(Y);
114// std::cout << "Here is the matrix W:" << std::endl << W << std::endl;
115
116 warpWeight = W.topRows(sLm.rows());
117 polWeight = W.bottomRows(4);
118
119 return true;
120}
121
122//=============================================================================================================
123
124MatrixXf Warp::warpVertices(const MatrixXf &sVert, const MatrixXf & sLm, const MatrixXf& warpWeight, const MatrixXf& polWeight)
125{
126 MatrixXf wVert = sVert * polWeight.bottomRows(3); //Pol. Warp
127 wVert.rowwise() += polWeight.row(0); //Translation
128
129 //
130 // TPS Warp
131 //
132 MatrixXf K = MatrixXf::Zero(sVert.rows(),sLm.rows()); //K(i,j)=||sLm(i)-sLm(j)||
133 for (int i=0; i<sVert.rows(); i++)
134 K.row(i)=((sLm.rowwise()-sVert.row(i)).rowwise().norm().transpose());
135// std::cout << "Here is the matrix K:" << std::endl << K << std::endl;
136
137 wVert += K*warpWeight;
138// std::cout << "Here is the matrix wVert:" << std::endl << wVert << std::endl;
139 return wVert;
140}
141
142//=============================================================================================================
143
144MatrixXf Warp::readsLm(const QString &electrodeFileName)
145{
146 MatrixXf electrodes;
147 QFile file(electrodeFileName);
148
149 if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
150 qDebug()<<"Error opening file";
151// return false;
152 }
153
154 //Start reading from file
155 double numberElectrodes;
156 QTextStream in(&file);
157 int i=0;
158
159 while(!in.atEnd())
160 {
161 QString line = in.readLine();
162 QStringList fields = line.split(QRegularExpression("\\s+"));
163
164 //Delete last element if it is a blank character
165 if(fields.at(fields.size()-1) == "")
166 fields.removeLast();
167
168 //Read number of electrodes
169 if(i == 0){
170 numberElectrodes = fields.at(fields.size()-1).toDouble();
171 electrodes = MatrixXf::Zero(numberElectrodes, 3);
172 }
173 //Read actual electrode positions
174 else{
175 Vector3f x;
176 x << fields.at(fields.size()-3).toFloat(),fields.at(fields.size()-2).toFloat(),fields.at(fields.size()-1).toFloat();
177 electrodes.row(i-1)=x.transpose();
178 }
179 i++;
180 }
181 return electrodes;
182}
183
184//=============================================================================================================
185
186MatrixXf Warp::readsLm(const std::string &electrodeFileName)
187{
188 MatrixXf electrodes;
189 std::ifstream inFile(electrodeFileName);
190
191 if(!inFile.is_open()) {
192 qDebug()<<"Error opening file";
193 //Why are we not returning?
194// return false;
195 }
196
197 //Start reading from file
198 double numberElectrodes;
199 int i = 0;
200
201 std::string line;
202 while(std::getline(inFile, line)){
203 std::vector<std::string> fields;
204 std::stringstream stream{line};
205 std::string element;
206
207 stream >> std::ws;
208 while(stream >> element){
209 fields.push_back(std::move(element));
210 stream >> std::ws;
211 }
212
213 //Read number of electrodes
214 if(i == 0){
215 numberElectrodes = std::stod(fields.at(fields.size()-1));
216 electrodes = MatrixXf::Zero(numberElectrodes, 3);
217 }
218
219 //Read actual electrode positions
220 else{
221 Vector3f x;
222 x << std::stof(fields.at(fields.size()-3)), std::stof(fields.at(fields.size()-2)), std::stof(fields.at(fields.size()-1));
223 electrodes.row(i-1)=x.transpose();
224 }
225 i++;
226 }
227
228 return electrodes;
229}
constexpr int Y
Thin-plate-spline 3-D warp from landmark correspondences.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Eigen::MatrixXf readsLm(const QString &electrodeFileName)
Definition warp.cpp:144
Eigen::MatrixXf calculate(const Eigen::MatrixXf &sLm, const Eigen::MatrixXf &dLm, const Eigen::MatrixXf &sVert)