You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.9 KiB
112 lines
3.9 KiB
// David Eberly, Geometric Tools, Redmond WA 98052
|
|
// Copyright (c) 1998-2021
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// https://www.boost.org/LICENSE_1_0.txt
|
|
// https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
|
|
// Version: 4.0.2020.01.11
|
|
|
|
#pragma once
|
|
|
|
#include <Mathematics/PdeFilter2.h>
|
|
#include <Mathematics/Math.h>
|
|
|
|
namespace gte
|
|
{
|
|
template <typename Real>
|
|
class GradientAnisotropic2 : public PdeFilter2<Real>
|
|
{
|
|
public:
|
|
GradientAnisotropic2(int xBound, int yBound, Real xSpacing, Real ySpacing,
|
|
Real const* data, bool const* mask, Real borderValue,
|
|
typename PdeFilter<Real>::ScaleType scaleType, Real K)
|
|
:
|
|
PdeFilter2<Real>(xBound, yBound, xSpacing, ySpacing, data, mask,
|
|
borderValue, scaleType),
|
|
mK(K)
|
|
{
|
|
ComputeParameter();
|
|
}
|
|
|
|
virtual ~GradientAnisotropic2()
|
|
{
|
|
}
|
|
|
|
protected:
|
|
void ComputeParameter()
|
|
{
|
|
Real gradMagSqr = (Real)0;
|
|
for (int y = 1; y <= this->mYBound; ++y)
|
|
{
|
|
for (int x = 1; x <= this->mXBound; ++x)
|
|
{
|
|
Real ux = this->GetUx(x, y);
|
|
Real uy = this->GetUy(x, y);
|
|
gradMagSqr += ux * ux + uy * uy;
|
|
}
|
|
}
|
|
gradMagSqr /= (Real)this->mQuantity;
|
|
|
|
mParameter = (Real)1 / (mK * mK * gradMagSqr);
|
|
mMHalfParameter = (Real)-0.5 * mParameter;
|
|
}
|
|
|
|
virtual void OnPreUpdate() override
|
|
{
|
|
ComputeParameter();
|
|
}
|
|
|
|
virtual void OnUpdateSingle(int x, int y) override
|
|
{
|
|
this->LookUp9(x, y);
|
|
|
|
// one-sided U-derivative estimates
|
|
Real uxFwd = this->mInvDx * (this->mUpz - this->mUzz);
|
|
Real uxBwd = this->mInvDx * (this->mUzz - this->mUmz);
|
|
Real uyFwd = this->mInvDy * (this->mUzp - this->mUzz);
|
|
Real uyBwd = this->mInvDy * (this->mUzz - this->mUzm);
|
|
|
|
// centered U-derivative estimates
|
|
Real uxCenM = this->mHalfInvDx * (this->mUpm - this->mUmm);
|
|
Real uxCenZ = this->mHalfInvDx * (this->mUpz - this->mUmz);
|
|
Real uxCenP = this->mHalfInvDx * (this->mUpp - this->mUmp);
|
|
Real uyCenM = this->mHalfInvDy * (this->mUmp - this->mUmm);
|
|
Real uyCenZ = this->mHalfInvDy * (this->mUzp - this->mUzm);
|
|
Real uyCenP = this->mHalfInvDy * (this->mUpp - this->mUpm);
|
|
|
|
Real uxCenZSqr = uxCenZ * uxCenZ;
|
|
Real uyCenZSqr = uyCenZ * uyCenZ;
|
|
Real gradMagSqr;
|
|
|
|
// estimate for C(x+1,y)
|
|
Real uyEstP = (Real)0.5 * (uyCenZ + uyCenP);
|
|
gradMagSqr = uxCenZSqr + uyEstP * uyEstP;
|
|
Real cxp = std::exp(mMHalfParameter * gradMagSqr);
|
|
|
|
// estimate for C(x-1,y)
|
|
Real uyEstM = (Real)0.5 * (uyCenZ + uyCenM);
|
|
gradMagSqr = uxCenZSqr + uyEstM * uyEstM;
|
|
Real cxm = std::exp(mMHalfParameter * gradMagSqr);
|
|
|
|
// estimate for C(x,y+1)
|
|
Real uxEstP = (Real)0.5 * (uxCenZ + uxCenP);
|
|
gradMagSqr = uyCenZSqr + uxEstP * uxEstP;
|
|
Real cyp = std::exp(mMHalfParameter * gradMagSqr);
|
|
|
|
// estimate for C(x,y-1)
|
|
Real uxEstM = (Real)0.5 * (uxCenZ + uxCenM);
|
|
gradMagSqr = uyCenZSqr + uxEstM * uxEstM;
|
|
Real cym = std::exp(mMHalfParameter * gradMagSqr);
|
|
|
|
this->mBuffer[this->mDst][y][x] = this->mUzz + this->mTimeStep * (
|
|
cxp * uxFwd - cxm * uxBwd +
|
|
cyp * uyFwd - cym * uyBwd);
|
|
}
|
|
|
|
// These are updated on each iteration, since they depend on the
|
|
// current average of the squared length of the gradients at the
|
|
// pixels.
|
|
Real mK; // k
|
|
Real mParameter; // 1/(k^2*average(gradMagSqr))
|
|
Real mMHalfParameter; // -0.5*mParameter
|
|
};
|
|
}
|
|
|