1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-27 21:24:47 +01:00

Replace the fuzzy NAN fill algorithm with a propper (but slower) one

This commit is contained in:
Martin Tůma 2024-08-28 22:47:10 +02:00
parent 96a24339c5
commit 29863da32c
2 changed files with 28 additions and 78 deletions

View File

@ -95,95 +95,44 @@ static void gaussBlur4(MatrixD &src, MatrixD &dst, int r)
boxBlur4(src, dst, (bxs.at(2) - 1) / 2); boxBlur4(src, dst, (bxs.at(2) - 1) / 2);
} }
static double avg(const MatrixD &m, int pi, int pj, int r) static int hasNANs(const MatrixD &m)
{
int col, row, cnt = 0;
double sum = 0;
if (r >= qMax(m.h(), m.w()))
return NAN;
row = pi - r;
if (row >= 0) {
for (int j = qMax(pj - r, 0); j < qMin(pj + r, m.w()); j++) {
if (!std::isnan(m.at(row, j))) {
sum += m.at(row, j);
cnt++;
}
}
}
row = pi + r;
if (row < m.h()) {
for (int j = qMax(pj - r, 0); j < qMin(pj + r, m.w()); j++) {
if (!std::isnan(m.at(row, j))) {
sum += m.at(row, j);
cnt++;
}
}
}
col = pj - r;
if (col >= 0) {
for (int i = qMax(pi - r + 1, 0); i < qMin(pi + r - 1, m.h()); i++) {
if (!std::isnan(m.at(i, col))) {
sum += m.at(i, col);
cnt++;
}
}
}
col = pj + r;
if (col < m.w()) {
for (int i = qMax(pi - r + 1, 0); i < qMin(pi + r - 1, m.h()); i++) {
if (!std::isnan(m.at(i, col))) {
sum += m.at(i, col);
cnt++;
}
}
}
if (cnt)
return sum / cnt;
else
return avg(m, pi, pj, r + 1);
}
static bool fillNANs(const MatrixD &m, MatrixD &src)
{
bool hasNAN = false;
for (int i = 0; i < m.h(); i++) {
for (int j = 0; j < m.w(); j++) {
if (std::isnan(m.at(i, j))) {
hasNAN = true;
double val = avg(src, i, j, 1);
if (std::isnan(val))
return false;
else
src.at(i, j) = val;
}
}
}
return hasNAN;
}
static void revertNANs(const MatrixD &m, MatrixD &dst)
{ {
for (int i = 0; i < m.size(); i++) for (int i = 0; i < m.size(); i++)
if (std::isnan(m.at(i))) if (std::isnan(m.at(i)))
dst.at(i) = NAN; return i;
return -1;
} }
MatrixD Filter::blur(const MatrixD &m, int radius) MatrixD Filter::blur(const MatrixD &m, int radius)
{ {
MatrixD src(m); MatrixD src(m);
MatrixD dst(m.h(), m.w()); MatrixD dst(m.h(), m.w());
bool hasNAN = fillNANs(m, src); int firstNAN = hasNANs(m);
gaussBlur4(src, dst, radius); if (firstNAN >= 0) {
// https://stackoverflow.com/a/36307291
MatrixD z(m.h(), m.w(), 1);
MatrixD zdst(m.h(), m.w());
if (hasNAN) for (int i = firstNAN; i < m.size(); i++) {
revertNANs(m, dst); if (std::isnan(m.at(i))) {
z.at(i) = 0;
src.at(i) = 0;
}
}
gaussBlur4(z, zdst, radius);
gaussBlur4(src, dst, radius);
for (int i = 0; i < m.size(); i++)
dst.at(i) = dst.at(i) / zdst.at(i);
for (int i = firstNAN; i < m.size(); i++)
if (std::isnan(m.at(i)))
dst.at(i) = NAN;
} else
gaussBlur4(src, dst, radius);
return dst; return dst;
} }

View File

@ -33,6 +33,7 @@ class MatrixD : public Matrix<double>
public: public:
MatrixD() : Matrix<double>() {} MatrixD() : Matrix<double>() {}
MatrixD(int h, int w) : Matrix<double>(h, w) {} MatrixD(int h, int w) : Matrix<double>(h, w) {}
MatrixD(int h, int w, double val) : Matrix<double>(h, w, val) {}
bool eliminate(double epsilon = DBL_EPSILON); bool eliminate(double epsilon = DBL_EPSILON);
MatrixD augemented(const MatrixD &M) const; MatrixD augemented(const MatrixD &M) const;