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.