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 vertList.replace(i, warpVertices(vertList.at(i), sLm, warpWeight, polWeight));
79 }
80 return;
81}
82
83//=============================================================================================================
84
85bool Warp::calcWeighting(const MatrixXf& sLm, const MatrixXf& dLm, MatrixXf& warpWeight, MatrixXf& polWeight)
86{
87 MatrixXf K = MatrixXf::Zero(sLm.rows(), sLm.rows()); //K(i,j)=||sLm(i)-sLm(j)||
88 for (int i = 0; i < sLm.rows(); i++)
89 K.col(i) = ((sLm.rowwise() - sLm.row(i)).rowwise().norm());
90
91 // std::cout << "Here is the matrix K:" << std::endl << K << std::endl;
92
93 MatrixXf P(sLm.rows(), 4); //P=[ones,sLm]
94 P << MatrixXf::Ones(sLm.rows(), 1), sLm;
95 // std::cout << "Here is the matrix P:" << std::endl << P << std::endl;
96
97 MatrixXf L((sLm.rows() + 4), (sLm.rows() + 4)); //L=Full Matrix of the linear eq.
98 L << K, P,
99 P.transpose(), MatrixXf::Zero(4, 4);
100 // std::cout << "Here is the matrix L:" << std::endl << L << std::endl;
101
102 MatrixXf Y((dLm.rows() + 4), 3); //Y=[dLm,Zero]
103 Y << dLm,
104 MatrixXf::Zero(4, 3);
105 // std::cout << "Here is the matrix Y:" << std::endl << Y << std::endl;
106
107 //
108 // calculate the weighting matrix (Y=L*W)
109 //
110 MatrixXf W((dLm.rows() + 4), 3); //W=[warpWeight,polWeight]
111 Eigen::FullPivLU<MatrixXf> Lu(L); //LU decomposition is one method to solve lin. eq.
112 W = Lu.solve(Y);
113 // std::cout << "Here is the matrix W:" << std::endl << W << std::endl;
114
115 warpWeight = W.topRows(sLm.rows());
116 polWeight = W.bottomRows(4);
117
118 return true;
119}
120
121//=============================================================================================================
122
123MatrixXf Warp::warpVertices(const MatrixXf& sVert, const MatrixXf& sLm, const MatrixXf& warpWeight, const MatrixXf& polWeight)
124{
125 MatrixXf wVert = sVert * polWeight.bottomRows(3); //Pol. Warp
126 wVert.rowwise() += polWeight.row(0); //Translation
127
128 //
129 // TPS Warp
130 //
131 MatrixXf K = MatrixXf::Zero(sVert.rows(), sLm.rows()); //K(i,j)=||sLm(i)-sLm(j)||
132 for (int i = 0; i < sVert.rows(); i++)
133 K.row(i) = ((sLm.rowwise() - sVert.row(i)).rowwise().norm().transpose());
134 // std::cout << "Here is the matrix K:" << std::endl << K << std::endl;
135
136 wVert += K * warpWeight;
137 // std::cout << "Here is the matrix wVert:" << std::endl << wVert << std::endl;
138 return wVert;
139}
140
141//=============================================================================================================
142
143MatrixXf Warp::readsLm(const QString& electrodeFileName)
144{
145 MatrixXf electrodes;
146 QFile file(electrodeFileName);
147
148 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
149 qDebug() << "Error opening file";
150 // return false;
151 }
152
153 //Start reading from file
154 double numberElectrodes;
155 QTextStream in(&file);
156 int i = 0;
157
158 while (!in.atEnd()) {
159 QString line = in.readLine();
160 QStringList fields = line.split(QRegularExpression("\\s+"));
161
162 //Delete last element if it is a blank character
163 if (fields.at(fields.size() - 1) == "")
164 fields.removeLast();
165
166 //Read number of electrodes
167 if (i == 0) {
168 numberElectrodes = fields.at(fields.size() - 1).toDouble();
169 electrodes = MatrixXf::Zero(numberElectrodes, 3);
170 }
171 //Read actual electrode positions
172 else {
173 Vector3f x;
174 x << fields.at(fields.size() - 3).toFloat(), fields.at(fields.size() - 2).toFloat(), fields.at(fields.size() - 1).toFloat();
175 electrodes.row(i - 1) = x.transpose();
176 }
177 i++;
178 }
179 return electrodes;
180}
181
182//=============================================================================================================
183
184MatrixXf Warp::readsLm(const std::string& electrodeFileName)
185{
186 MatrixXf electrodes;
187 std::ifstream inFile(electrodeFileName);
188
189 if (!inFile.is_open()) {
190 qDebug() << "Error opening file";
191 //Why are we not returning?
192 // return false;
193 }
194
195 //Start reading from file
196 double numberElectrodes;
197 int i = 0;
198
199 std::string line;
200 while (std::getline(inFile, line)) {
201 std::vector<std::string> fields;
202 std::stringstream stream{line};
203 std::string element;
204
205 stream >> std::ws;
206 while (stream >> element) {
207 fields.push_back(std::move(element));
208 stream >> std::ws;
209 }
210
211 //Read number of electrodes
212 if (i == 0) {
213 numberElectrodes = std::stod(fields.at(fields.size() - 1));
214 electrodes = MatrixXf::Zero(numberElectrodes, 3);
215 }
216
217 //Read actual electrode positions
218 else {
219 Vector3f x;
220 x << std::stof(fields.at(fields.size() - 3)), std::stof(fields.at(fields.size() - 2)), std::stof(fields.at(fields.size() - 1));
221 electrodes.row(i - 1) = x.transpose();
222 }
223 i++;
224 }
225
226 return electrodes;
227}
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:143
Eigen::MatrixXf calculate(const Eigen::MatrixXf &sLm, const Eigen::MatrixXf &dLm, const Eigen::MatrixXf &sVert)