37 #ifndef VIGRA_TV_FILTER_HXX
38 #define VIGRA_TV_FILTER_HXX
44 #include "separableconvolution.hxx"
45 #include "multi_array.hxx"
46 #include "multi_math.hxx"
47 #include "eigensystem.hxx"
48 #include "convolution.hxx"
49 #include "fixedpoint.hxx"
50 #include "project2ellipse.hxx"
52 #ifndef VIGRA_MIXED_2ND_DERIVATIVES
53 #define VIGRA_MIXED_2ND_DERIVATIVES 1
56 #define setZeroX(A) A.subarray(Shape2(width-1,0),Shape2(width,height))*=0;
57 #define setZeroY(A) A.subarray(Shape2(0,height-1),Shape2(width,height))*=0;
141 template <
class str
ide1,
class str
ide2>
142 void totalVariationFilter(MultiArrayView<2,double,stride1> data,MultiArrayView<2,double,stride2> out,
double alpha,
int steps,
double eps=0){
144 using namespace multi_math;
145 int width=data.shape(0),height=data.shape(1);
147 MultiArray<2,double> temp1(data.shape()),temp2(data.shape()),vx(data.shape()),vy(data.shape()),u_bar(data.shape());
148 Kernel1D<double> Lx,LTx;
149 Lx.initExplicitly(-1,0)=1,-1;
150 Lx.setBorderTreatment(BORDER_TREATMENT_REFLECT);
151 LTx.initExplicitly(0,1)=-1,1;
152 LTx.setBorderTreatment(BORDER_TREATMENT_ZEROPAD);
157 double tau=1.0 / std::max(alpha,1.) /
std::sqrt(8.0) * 0.06;
158 double sigma=1.0 /
std::sqrt(8.0) / 0.06;
160 for (
int i=0;i<steps;i++){
162 separableConvolveX(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroX(temp1);
164 separableConvolveY(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroY(temp1);
168 for (
int y=0;y<data.shape(1);y++){
169 for (
int x=0;x<data.shape(0);x++){
170 double l=
hypot(vx(x,y),vy(x,y));
181 out-=tau*(out-data+alpha*(temp1+temp2));
190 double f_primal=0,f_dual=0;
191 for (
int y=0;y<data.shape(1);y++){
192 for (
int x=0;x<data.shape(0);x++){
193 f_primal+=.5*(out(x,y)-data(x,y))*(out(x,y)-data(x,y))+alpha*
hypot(temp1(x,y),temp2(x,y));
198 for (
int y=0;y<data.shape(1);y++){
199 for (
int x=0;x<data.shape(0);x++){
200 double divv=temp1(x,y)+temp2(x,y);
201 f_dual+=-.5*alpha*alpha*(divv*divv)+alpha*data(x,y)*divv;
204 if (f_primal>0 && (f_primal-f_dual)/f_primal<eps){
211 template <
class str
ide1,
class str
ide2,
class str
ide3>
212 void totalVariationFilter(MultiArrayView<2,double,stride1> data,MultiArrayView<2,double,stride2> weight, MultiArrayView<2,double,stride3> out,
double alpha,
int steps,
double eps=0){
214 using namespace multi_math;
215 int width=data.shape(0),height=data.shape(1);
217 MultiArray<2,double> temp1(data.shape()),temp2(data.shape()),vx(data.shape()),vy(data.shape()),u_bar(data.shape());
218 Kernel1D<double> Lx,LTx;
219 Lx.initExplicitly(-1,0)=1,-1;
220 Lx.setBorderTreatment(BORDER_TREATMENT_REFLECT);
221 LTx.initExplicitly(0,1)=-1,1;
222 LTx.setBorderTreatment(BORDER_TREATMENT_ZEROPAD);
227 double tau=1.0 / std::max(alpha,1.) /
std::sqrt(8.0) * 0.06;
228 double sigma=1.0 /
std::sqrt(8.0) / 0.06;
230 for (
int i=0;i<steps;i++){
231 separableConvolveX(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroX(temp1);
233 separableConvolveY(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroY(temp1);
237 for (
int y=0;y<data.shape(1);y++){
238 for (
int x=0;x<data.shape(0);x++){
239 double l=
hypot(vx(x,y),vy(x,y));
250 out-=tau*(weight*(out-data)+alpha*(temp1+temp2));
259 double f_primal=0,f_dual=0;
260 for (
int y=0;y<data.shape(1);y++){
261 for (
int x=0;x<data.shape(0);x++){
262 f_primal+=.5*weight(x,y)*(out(x,y)-data(x,y))*(out(x,y)-data(x,y))+alpha*
hypot(temp1(x,y),temp2(x,y));
267 for (
int y=0;y<data.shape(1);y++){
268 for (
int x=0;x<data.shape(0);x++){
269 double divv=temp1(x,y)+temp2(x,y);
270 f_dual+=-.5*alpha*alpha*(weight(x,y)*divv*divv)+alpha*data(x,y)*divv;
273 if (f_primal>0 && (f_primal-f_dual)/f_primal<eps){
340 template <
class str
ide1,
class str
ide2,
class str
ide3,
class str
ide4>
341 void getAnisotropy(MultiArrayView<2,double,stride1> data,MultiArrayView<2,double,stride2> phi,
342 MultiArrayView<2,double,stride3> alpha, MultiArrayView<2,double,stride4> beta,
343 double alpha_par,
double beta_par,
double sigma_par,
double rho_par,
double K_par){
345 using namespace multi_math;
347 MultiArray<2,double> smooth(data.shape()),tmp(data.shape());
355 MultiArray<2,double> stxx(data.shape()),stxy(data.shape()),styy(data.shape());
360 gauss.initGaussian(rho_par);
368 MultiArray<2,double> matrix(Shape2(2,2)),ev(Shape2(2,2)),ew(Shape2(2,1));
370 for (
int y=0;y<data.shape(1);y++){
371 for (
int x=0;x<data.shape(0);x++){
373 matrix(0,0)=stxx(x,y);
374 matrix(1,1)=styy(x,y);
375 matrix(0,1)=stxy(x,y);
376 matrix(1,0)=stxy(x,y);
380 double coherence=ew(0,0)-ew(1,0);
381 double c=std::min(K_par*coherence,1.);
382 alpha(x,y)=alpha_par*c+(1-c)*beta_par;
468 template <
class str
ide1,
class str
ide2,
class str
ide3,
class str
ide4,
class str
ide5,
class str
ide6>
470 MultiArrayView<2,double,stride3> phi,MultiArrayView<2,double,stride4> alpha,
471 MultiArrayView<2,double,stride5> beta,MultiArrayView<2,double,stride6> out,
474 using namespace multi_math;
475 int width=data.shape(0),height=data.shape(1);
477 MultiArray<2,double> temp1(data.shape()),temp2(data.shape()),vx(data.shape()),vy(data.shape()),u_bar(data.shape());
478 MultiArray<2,double> rx(data.shape()),ry(data.shape());
480 Kernel1D<double> Lx,LTx;
481 Lx.initExplicitly(-1,0)=1,-1;
482 Lx.setBorderTreatment(BORDER_TREATMENT_REFLECT);
483 LTx.initExplicitly(0,1)=-1,1;
484 LTx.setBorderTreatment(BORDER_TREATMENT_ZEROPAD);
489 for (
int y=0;y<data.shape(1);y++){
490 for (
int x=0;x<data.shape(0);x++){
491 m=std::max(m,alpha(x,y));
492 m=std::max(m,beta (x,y));
500 for (
int i=0;i<steps;i++){
501 separableConvolveX(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroX(temp1);
503 separableConvolveY(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroY(temp1);
507 for (
int y=0;y<data.shape(1);y++){
508 for (
int x=0;x<data.shape(0);x++){
509 double e1,e2,skp1,skp2;
513 skp1=vx(x,y)*e1+vy(x,y)*e2;
514 skp2=vx(x,y)*(-e2)+vy(x,y)*e1;
515 vigra::detail::projectEllipse2D (skp1,skp2,alpha(x,y),beta(x,y),0.001,100);
517 vx(x,y)=skp1*e1-skp2*e2;
518 vy(x,y)=skp1*e2+skp2*e1;
525 out-=tau*(weight*(out-data)+(temp1+temp2));
622 template <
class str
ide1,
class str
ide2,
class str
ide3,
class str
ide4,
class str
ide5,
class str
ide6,
class str
ide7,
class str
ide8,
class str
ide9>
624 MultiArrayView<2,double,stride2> weight,MultiArrayView<2,double,stride3> phi,
625 MultiArrayView<2,double,stride4> alpha,MultiArrayView<2,double,stride5> beta,
626 MultiArrayView<2,double,stride6>
gamma,
627 MultiArrayView<2,double,stride7> xedges,MultiArrayView<2,double,stride8> yedges,
628 MultiArrayView<2,double,stride9> out,
631 using namespace multi_math;
632 int width=data.shape(0),height=data.shape(1);
634 MultiArray<2,double> temp1(data.shape()),temp2(data.shape()),vx(data.shape()),vy(data.shape()),u_bar(data.shape());
635 MultiArray<2,double> rx(data.shape()),ry(data.shape());
636 MultiArray<2,double> wx(data.shape()),wy(data.shape()),wz(data.shape());
639 Kernel1D<double> Lx,LTx;
640 Lx.initExplicitly(-1,0)=1,-1;
641 Lx.setBorderTreatment(BORDER_TREATMENT_REFLECT);
642 LTx.initExplicitly(0,1)=-1,1;
643 LTx.setBorderTreatment(BORDER_TREATMENT_ZEROPAD);
648 for (
int y=0;y<data.shape(1);y++){
649 for (
int x=0;x<data.shape(0);x++){
650 m=std::max(m,alpha(x,y));
651 m=std::max(m,beta (x,y));
652 m=std::max(m,
gamma(x,y));
661 for (
int i=0;i<steps;i++){
663 separableConvolveX(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroX(temp1);
665 separableConvolveY(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroY(temp1);
670 separableConvolveX(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroX(temp1);
676 separableConvolveY(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroY(temp1);
683 #if (VIGRA_MIXED_2ND_DERIVATIVES)
684 separableConvolveY(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroY(temp1);
689 separableConvolveX(srcImageRange(u_bar),destImage(temp1),kernel1d(Lx));setZeroX(temp1);
698 for (
int y=0;y<data.shape(1);y++){
699 for (
int x=0;x<data.shape(0);x++){
700 double e1,e2,skp1,skp2;
705 skp1=vx(x,y)*e1+vy(x,y)*e2;
706 skp2=vx(x,y)*(-e2)+vy(x,y)*e1;
707 vigra::detail::projectEllipse2D (skp1,skp2,alpha(x,y),beta(x,y),0.001,100);
708 vx(x,y)=skp1*e1-skp2*e2;
709 vy(x,y)=skp1*e2+skp2*e1;
712 double l=
sqrt(wx(x,y)*wx(x,y)+wy(x,y)*wy(x,y)+wz(x,y)*wz(x,y));
714 wx(x,y)=
gamma(x,y)*wx(x,y)/l;
715 wy(x,y)=
gamma(x,y)*wy(x,y)/l;
716 #if (VIGRA_MIXED_2ND_DERIVATIVES)
717 wz(x,y)=
gamma(x,y)*wz(x,y)/l;
727 out-=tau*(weight*(out-data)+temp1+temp2);
744 #if (VIGRA_MIXED_2ND_DERIVATIVES)
766 #endif // VIGRA_TV_FILTER_HXX
FixedPoint16< 2, OverflowHandling > atan2(FixedPoint16< IntBits, OverflowHandling > y, FixedPoint16< IntBits, OverflowHandling > x)
Arctangent. Accuracy better than 1/3 degree (9 significant bits).
Definition: fixedpoint.hxx:1654
Generic 1 dimensional convolution kernel.
Definition: separableconvolution.hxx:52
linalg::TemporaryMatrix< T > sin(MultiArrayView< 2, T, C > const &v)
void initGaussian(double std_dev, value_type norm, double windowRatio=0.0)
Definition: separableconvolution.hxx:2253
void getAnisotropy(...)
Sets up directional data for anisotropic regularization.
bool symmetricEigensystemNoniterative(MultiArrayView< 2, T, C1 > const &a, MultiArrayView< 2, T, C2 > &ew, MultiArrayView< 2, T, C3 > &ev)
Definition: eigensystem.hxx:1152
void separableConvolveX(...)
Performs a 1 dimensional convolution in x direction.
FixedPoint16< IntBits, OverflowHandling > hypot(FixedPoint16< IntBits, OverflowHandling > v1, FixedPoint16< IntBits, OverflowHandling > v2)
Length of hypotenuse.
Definition: fixedpoint.hxx:1640
void anisotropicTotalVariationFilter(...)
Performs Anisotropic Total Variation Regularization.
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
double gamma(double x)
The gamma function.
Definition: mathutil.hxx:1587
void structureTensor(...)
Calculate the Structure Tensor for each pixel of and image, using Gaussian (derivative) filters...
void totalVariationFilter(...)
Performs standard Total Variation Regularization.
image import and export functions
linalg::TemporaryMatrix< T > cos(MultiArrayView< 2, T, C > const &v)
void separableConvolveY(...)
Performs a 1 dimensional convolution in y direction.
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616
void secondOrderTotalVariationFilter(...)
Performs Anisotropic Total Variation Regularization.