49#include <QRegularExpression>
62MatrixXf
Warp::calculate(
const MatrixXf& sLm,
const MatrixXf& dLm,
const MatrixXf& sVert)
64 MatrixXf warpWeight, polWeight;
65 calcWeighting(sLm, dLm, warpWeight, polWeight);
66 MatrixXf wVert = warpVertices(sVert, sLm, warpWeight, polWeight);
72void Warp::calculate(
const MatrixXf& sLm,
const MatrixXf& dLm, QList<MatrixXf>& vertList)
74 MatrixXf warpWeight, polWeight;
75 calcWeighting(sLm, dLm, warpWeight, polWeight);
77 for (
int i = 0; i < vertList.size(); i++) {
78 vertList.replace(i, warpVertices(vertList.at(i), sLm, warpWeight, polWeight));
85bool Warp::calcWeighting(
const MatrixXf& sLm,
const MatrixXf& dLm, MatrixXf& warpWeight, MatrixXf& polWeight)
87 MatrixXf K = MatrixXf::Zero(sLm.rows(), sLm.rows());
88 for (
int i = 0; i < sLm.rows(); i++)
89 K.col(i) = ((sLm.rowwise() - sLm.row(i)).rowwise().norm());
93 MatrixXf P(sLm.rows(), 4);
94 P << MatrixXf::Ones(sLm.rows(), 1), sLm;
97 MatrixXf L((sLm.rows() + 4), (sLm.rows() + 4));
99 P.transpose(), MatrixXf::Zero(4, 4);
102 MatrixXf
Y((dLm.rows() + 4), 3);
104 MatrixXf::Zero(4, 3);
110 MatrixXf W((dLm.rows() + 4), 3);
111 Eigen::FullPivLU<MatrixXf> Lu(L);
115 warpWeight = W.topRows(sLm.rows());
116 polWeight = W.bottomRows(4);
123MatrixXf Warp::warpVertices(
const MatrixXf& sVert,
const MatrixXf& sLm,
const MatrixXf& warpWeight,
const MatrixXf& polWeight)
125 MatrixXf wVert = sVert * polWeight.bottomRows(3);
126 wVert.rowwise() += polWeight.row(0);
131 MatrixXf K = MatrixXf::Zero(sVert.rows(), sLm.rows());
132 for (
int i = 0; i < sVert.rows(); i++)
133 K.row(i) = ((sLm.rowwise() - sVert.row(i)).rowwise().norm().transpose());
136 wVert += K * warpWeight;
146 QFile file(electrodeFileName);
148 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
149 qDebug() <<
"Error opening file";
154 double numberElectrodes;
155 QTextStream in(&file);
158 while (!in.atEnd()) {
159 QString line = in.readLine();
160 QStringList fields = line.split(QRegularExpression(
"\\s+"));
163 if (fields.at(fields.size() - 1) ==
"")
168 numberElectrodes = fields.at(fields.size() - 1).toDouble();
169 electrodes = MatrixXf::Zero(numberElectrodes, 3);
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();
187 std::ifstream inFile(electrodeFileName);
189 if (!inFile.is_open()) {
190 qDebug() <<
"Error opening file";
196 double numberElectrodes;
200 while (std::getline(inFile, line)) {
201 std::vector<std::string> fields;
202 std::stringstream stream{line};
206 while (stream >> element) {
207 fields.push_back(std::move(element));
213 numberElectrodes = std::stod(fields.at(fields.size() - 1));
214 electrodes = MatrixXf::Zero(numberElectrodes, 3);
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();
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)
Eigen::MatrixXf calculate(const Eigen::MatrixXf &sLm, const Eigen::MatrixXf &dLm, const Eigen::MatrixXf &sVert)