00001
00002 #include "sdet_denoise_mrf.h"
00003 #include <vcl_cstdlib.h>
00004 #include <vnl/vnl_math.h>
00005 #include <vil/vil_new.h>
00006 #include <vnl/vnl_numeric_traits.h>
00007 #include <vnl/algo/vnl_sparse_lu.h>
00008 #include <vul/vul_timer.h>
00009 #include <brip/brip_vil_float_ops.h>
00010 #include <brip/brip_line_generator.h>
00011
00012
00013
00014
00015
00016
00017 sdet_denoise_mrf::sdet_denoise_mrf(sdet_denoise_mrf_params& dmp)
00018 : sdet_denoise_mrf_params(dmp), output_valid_(false), in_resc_(0),
00019 var_resc_(0), out_resc_(0)
00020 {
00021 sigma_sq_inv_ = radius_/1.978;
00022 sigma_sq_inv_ *= sigma_sq_inv_;
00023 sigma_sq_inv_ = 1.0/sigma_sq_inv_;
00024 }
00025
00026
00027 sdet_denoise_mrf::~sdet_denoise_mrf()
00028 {
00029 }
00030
00031 double sdet_denoise_mrf::weight(unsigned i0, unsigned j0,
00032 unsigned i1, unsigned j1,
00033 vil_image_view<float> const& inv,
00034 vil_image_view<float> const& varv)
00035 {
00036 int ni = inv.ni(), nj = inv.nj();
00037
00038
00039 double dsq = (i1-i0)*(i1-i0) + (j1-j0)*(j1-j0);
00040 double d = vcl_sqrt(dsq);
00041 if (d>(vnl_math::sqrt2*radius_)) return 0.0;
00042
00043 bool init = true;
00044 float xs = static_cast<float>(i0), ys = static_cast<float>(j0);
00045 float xe = static_cast<float>(i1), ye = static_cast<float>(j1);
00046 float x=xs, y=ys;
00047 double min_var = vnl_numeric_traits<double>::maxval;
00048
00049 while (brip_line_generator::generate(init, xs, ys, xe, ye, x, y))
00050 {
00051 unsigned i = static_cast<unsigned>(x), j = static_cast<unsigned>(y);
00052 double v = varv(i, j);
00053 if (v<min_var)
00054 min_var = v;
00055 }
00056
00057
00058 double sum0=0.0, sum1=0.0;
00059 double n0 = 0.0, n1 = 0.0;
00060 int r = static_cast<int>(radius_);
00061 for (int kj = -r; kj<=r; ++kj) {
00062 int j0k = j0+kj, j1k = j1+kj;
00063 if (j0k<0||j0k>=nj||j1k<0||j1k>=nj) continue;
00064 for (int ki = -r; ki<=r; ++ki) {
00065 int i0k = i0+ki, i1k = i1+ki;
00066 if (i0k<0||i0k>=ni||i1k<0||i1k>=ni) continue;
00067 sum0 += inv(i0k, j0k);
00068 sum1 += inv(i1k, j1k);
00069 n0+=1.0;
00070 n1+=1.0;
00071 }
00072 }
00073 double v_avg0=0.0, v_avg1=0.0;
00074 if (n0>0.0)
00075 v_avg0 = sum0/n0;
00076 if (n1>0.0)
00077 v_avg1 = sum1/n1;
00078
00079 double Delta = (v_avg1-v_avg0)*(v_avg1-v_avg0);
00080 double w = vcl_exp(-dsq/sigma_sq_inv_ +
00081 kappa_*min_var -
00082 beta_*Delta);
00083 return w;
00084 }
00085
00086 void sdet_denoise_mrf::compute_incidence_matrix()
00087 {
00088 int ni = in_resc_->ni(), nj = in_resc_->nj();
00089 int npix = ni*nj;
00090 W_mat_.resize(npix, npix);
00091 D_mat_.set_size(npix, npix);
00092 D_inv_sqrt_.set_size(npix, npix);
00093 vil_image_view<float> inv = brip_vil_float_ops::convert_to_float(in_resc_);
00094 vil_image_view<float> varv = brip_vil_float_ops::convert_to_float(var_resc_);
00095 int r = static_cast<int>(radius_);
00096 for (int j = 0; j<nj; ++j) {
00097 for (int i = 0; i<ni; ++i) {
00098 double D = 0.0;
00099 unsigned indx = i + ni*j;
00100
00101 for ( int kj = -r; kj<=r; ++kj) {
00102 int joff = j+kj;
00103 if (joff<0||joff>=nj)
00104 continue;
00105 for ( int ki = -r; ki<=r; ++ki) {
00106 int ioff = i+ki;
00107 if (ioff<0||ioff>=ni)
00108 continue;
00109 int indx_nbr = (ioff) + ni*(joff);
00110 if (indx_nbr<0||indx_nbr>=npix)
00111 continue;
00112 if ((unsigned int)indx_nbr!=indx) {
00113 double w = weight(i, j, i+ki, j+kj, inv, varv);
00114 if (w>0.0) {
00115 W_mat_.put(indx, indx_nbr, w);
00116 D += w;
00117 }
00118 }
00119 else {
00120 W_mat_.put(indx, indx_nbr, 1.0);
00121 D += 1.0;
00122 }
00123 }
00124 }
00125 D_mat_.put(indx,indx, D) ;
00126 D_inv_sqrt_.put(indx,indx,1.0/vcl_sqrt(D));
00127 }
00128 }
00129 }
00130
00131 vil_image_resource_sptr sdet_denoise_mrf::Dimgr()
00132 {
00133 unsigned nr = D_mat_.rows();
00134 if (!nr||!in_resc_) return 0;
00135 unsigned ni = in_resc_->ni(), nj = in_resc_->nj();
00136 if (nr!=ni*nj) return 0;
00137 vil_image_view<float> out(ni, nj);
00138 for (unsigned j = 0; j<nj; ++j)
00139 for (unsigned i = 0; i<ni; ++i) {
00140 unsigned indx = i + ni*j;
00141 out(i,j)=static_cast<float>(D_mat_(indx,indx));
00142 }
00143 return vil_new_image_resource_of_view(out);
00144 }
00145
00146 void sdet_denoise_mrf::compute_laplacian_matrix()
00147 {
00148 L_mat_ = D_mat_-W_mat_;
00149 L_mat_ = D_inv_sqrt_*L_mat_*D_inv_sqrt_;
00150 }
00151
00152 void sdet_denoise_mrf::compute_F()
00153 {
00154 vil_image_view<float> in_view = in_resc_->get_view();
00155 unsigned ni = in_view.ni(), nj = in_view.nj();
00156
00157 vnl_vector<double> b(W_mat_.rows());
00158 for (unsigned j = 0; j<nj; ++j)
00159 for (unsigned i = 0; i<ni; ++i) {
00160 unsigned indx = i + j*ni;
00161 double dinsq = D_inv_sqrt_(indx, indx);
00162 b[indx]=dinsq*in_view(i,j);
00163 }
00164
00165
00166 W_mat_ = D_inv_sqrt_*D_inv_sqrt_;
00167
00168 W_mat_ += 2.0*L_mat_;
00169 vnl_sparse_lu lu(W_mat_, vnl_sparse_lu::estimate_condition);
00170 vnl_vector<double> R = lu.solve(b);
00171 F_.set_size(W_mat_.rows());
00172 for (unsigned r = 0; r<W_mat_.rows(); ++r)
00173 F_[r] = D_inv_sqrt_(r,r)*R[r];
00174 }
00175
00176 bool sdet_denoise_mrf::denoise()
00177 {
00178 if (!in_resc_) return false;
00179 if (!var_resc_) return false;
00180 unsigned area = in_resc_->ni()*in_resc_->nj();
00181 vcl_cout << " constructing mrf on " << area << " x " << area
00182 << " incidence matrix\n";
00183 vul_timer t;
00184 this->compute_incidence_matrix();
00185 this->compute_laplacian_matrix();
00186 vcl_cout << "formed incidence and auxiliary matrices in "
00187 << t.real()/1000.0 << " seconds\n";
00188 t.mark();
00189 this->compute_F();
00190 vcl_cout << "solved LU decomposition and back substitution in "
00191 << t.real()/1000.0 << " seconds\n";
00192 int ni = in_resc_->ni(), nj = in_resc_->nj();
00193 vil_image_view<float> out_view(ni, nj);
00194 out_view.fill(0.0f);
00195 for (int j = 0; j<nj; ++j)
00196 for (int i = 0; i<ni; ++i) {
00197 unsigned indx = i + ni*j;
00198 out_view(i,j) = static_cast<float>(F_[indx]);
00199 }
00200 out_resc_ = vil_new_image_resource_of_view(out_view);
00201 output_valid_ = true;
00202 return true;
00203 }
00204