---
milena/mln/inpainting/inpaint.hh | 98 +++++++++++++++++++++++
milena/mln/inpainting/lpde.hh | 146 ++++++++++++++++++++++++++++++++++
milena/mln/inpainting/metric/psnr.hh | 51 ++++++++++++
3 files changed, 295 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/inpainting/inpaint.hh
create mode 100644 milena/mln/inpainting/lpde.hh
create mode 100644 milena/mln/inpainting/metric/psnr.hh
diff --git a/milena/mln/inpainting/inpaint.hh b/milena/mln/inpainting/inpaint.hh
new file mode 100644
index 0000000..44f20a8
--- /dev/null
+++ b/milena/mln/inpainting/inpaint.hh
@@ -0,0 +1,98 @@
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/fill.hh>
+#include <mln/data/paste.hh>
+
+#include <mln/literal/colors.hh>
+
+#include <mln/core/alias/box2d.hh>
+#include <mln/accu/shape/bbox.hh>
+#include <mln/value/label_8.hh>
+#include <mln/labeling/compute.hh>
+
+#include <mln/pw/value.hh>
+#include <mln/draw/box.hh>
+
+#include <mln/util/timer.hh>
+
+namespace mln
+{
+ namespace inpainting
+ {
+ /*
+ * Interface
+ */
+
+ template <template <typename> class I, typename T, typename F>
+ I<T> inpaint(const Image<I<T> >& src_,
+ const Image<I<bool> >& mask_,
+ F inpaint_method,
+ unsigned inpaint_radius);
+
+ /*
+ * Implem
+ */
+
+ template <template <typename> class I, typename T, typename F>
+ I<T> inpaint(const Image<I<T> >& inpaint_src_,
+ const Image<I<bool> >& inpaint_mask_,
+ F inpaint_method,
+ unsigned inpaint_radius)
+ {
+ const I<T>& inpaint_src = exact(inpaint_src_);
+ const I<bool>& inpaint_mask = exact(inpaint_mask_);
+
+ box2d roi;
+ { // Compute the region of interest
+ I<value::label_8> lbl(inpaint_mask.domain());
+
+ data::fill(lbl, 1);
+ data::fill((lbl | pw::value(inpaint_mask)).rw(), 0);
+
+ value::label_8 nlabels = 2;
+
+ util::array<box2d> roi_bboxes =
+ labeling::compute(accu::meta::shape::bbox(),
+ lbl,
+ nlabels);
+
+ roi = roi_bboxes[0];
+ roi.enlarge(inpaint_radius);
+ roi.crop_wrt(inpaint_src.domain());
+ }
+
+ I<mln_sum(T)> new_src(roi);
+ { // paste inpaint_src to new_src
+ mln_piter(I<T>) p(roi);
+ mln_pixter(I<mln_sum(T)>) p_new(new_src);
+
+ for_all_2(p, p_new)
+ p_new.val() = inpaint_src(p);
+ }
+
+ I<bool> new_mask(roi);
+ data::paste(inpaint_mask | roi, new_mask);
+
+ mln::util::timer t;
+ t.start();
+
+ inpaint_method(new_src, new_mask);
+
+ t.stop();
+ std::cout << "inpaint time = " << t << std::endl;
+
+ I<T> output(inpaint_src);
+ { // paste new_src to output
+ mln_piter(I<T>) p(roi);
+ mln_pixter(const I<mln_sum(T)>) p_new(new_src);
+
+ for_all_2(p, p_new)
+ output(p) = p_new.val();
+ }
+
+ return output;
+ }
+
+ } /* mln::inpainting */
+
+} /* mln*/
diff --git a/milena/mln/inpainting/lpde.hh b/milena/mln/inpainting/lpde.hh
new file mode 100644
index 0000000..1f754d8
--- /dev/null
+++ b/milena/mln/inpainting/lpde.hh
@@ -0,0 +1,146 @@
+#include <algorithm>
+#include <vector>
+
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/fill.hh>
+#include <mln/literal/colors.hh>
+#include <mln/literal/zero.hh>
+
+#include <mln/linear/convolve.hh>
+#include <mln/linear/gaussian.hh>
+#include <mln/core/alias/w_window2d_float.hh>
+
+#include <mln/pw/value.hh>
+
+#include <mln/value/int_u.hh>
+#include <mln/algebra/vec.hh>
+
+#include <mln/data/paste.hh>
+
+#include <mln/core/alias/vec2d.hh>
+
+namespace mln
+{
+ namespace inpainting
+ {
+ struct lpde
+ {
+ public:
+ lpde(float dt = 1.0f, float dx = 1.0f, float t_f = 20.0);
+
+ template <template <typename> class I, typename T>
+ void operator()(I<T>& src,
+ I<bool>& mask);
+
+ void set(const std::vector<float>& w);
+
+ private:
+ std::vector<float> w;
+ float dt;
+ float dx;
+ float t_f;
+ };
+
+ lpde::lpde(float dt, float dx, float t_f)
+ {
+ this->dt = dt;
+ this->dx = dx;
+ this->t_f = t_f;
+ }
+
+ template <typename I>
+ void compute_diff_invariants(const I& u,
+ std::vector<I>& invs,
+ const std::vector<float>& w)
+ {
+ const float sigma = 0.8;
+
+ invs[0] = linear::gaussian_1st_derivative(u, sigma, 1);
+ invs[1] = linear::gaussian_1st_derivative(u, sigma, 0);
+ invs[2] = linear::gaussian_2nd_derivative(u, sigma, 1);
+ invs[3] = linear::gaussian_2nd_derivative(u, sigma, 0);
+ invs[4] = linear::gaussian_2nd_derivative(u, sigma);
+
+ { // TV regularization term div ( \nabla u / | \nabla u | )
+
+ I u_xnx( invs[5].domain() );
+ I u_yny( invs[5].domain() );
+
+ {
+ mln_piter(I) p( invs[5].domain() );
+
+ for_all(p)
+ {
+ for (unsigned i = 0; i < mln_dim(mln_value(I)); ++i)
+ {
+ float norm;
+ {
+ vec2d_f v;
+
+ v[0] = invs[0](p)[i];
+ v[1] = invs[1](p)[i];
+
+ norm = norm::l2(v);
+ }
+
+ u_xnx(p)[i] = invs[0](p)[i] / norm;
+ u_yny(p)[i] = invs[1](p)[i] / norm;
+ }
+ }
+ }
+
+ u_xnx = linear::gaussian_1st_derivative(u_xnx, sigma, 1);
+ u_yny = linear::gaussian_1st_derivative(u_yny, sigma, 0);
+
+ mln_piter(I) p( invs[5].domain() );
+ for_all(p)
+ {
+ invs[5](p) = u_xnx(p) + u_yny(p);
+ }
+ }
+ }
+
+ template <template <typename> class I, typename T>
+ void lpde::operator()(I<T>& src,
+ I<bool>& mask)
+ {
+
+ data::fill((src | pw::value(mask)).rw(), literal::zero);
+
+ std::vector<I<T> > invs(w.size(), src.domain());
+
+ I<T>& u_t = src;
+
+ float r = this->dt / (this->dx * this->dx);
+
+ for (float t = 0; t < this->t_f; t += dt)
+ {
+ compute_diff_invariants(u_t, invs, this->w);
+
+ mln_piter(I<T>) p(u_t.domain());
+
+ for_all(p)
+ {
+ if (mask(p))
+ {
+ T contribution = literal::zero;
+
+ for (unsigned k = 0; k < w.size(); ++k)
+ {
+ contribution += this->w[k] * invs[k](p);
+ }
+
+ u_t(p) += r * contribution;
+ }
+ }
+ }
+ }
+
+ void lpde::set(const std::vector<float>& w)
+ {
+ this->w = w;
+ }
+ } /* mln::inpainting */
+
+} /* mln*/
diff --git a/milena/mln/inpainting/metric/psnr.hh b/milena/mln/inpainting/metric/psnr.hh
new file mode 100644
index 0000000..4998b4a
--- /dev/null
+++ b/milena/mln/inpainting/metric/psnr.hh
@@ -0,0 +1,51 @@
+#ifndef MLN_INPAINTING_METRIC_PSNR_HH
+# define MLN_INPAINTING_METRIC_PSNR_HH
+
+# include <cmath>
+
+# include <mln/core/concept/image.hh>
+# include <mln/norm/l1.hh>
+# include <mln/trait/value_.hh>
+# include <mln/algebra/vec.hh>
+
+namespace mln
+{
+ namespace inpainting
+ {
+ namespace metric
+ {
+ template <typename I>
+ double psnr(const Image<I>& original_,
+ const Image<I>& altered_)
+ {
+ const I& original = exact(original_);
+ const I& altered = exact(altered_);
+
+ mln_piter(I) p( altered.domain() );
+
+ double mse = 0;
+
+ const unsigned dim = mln_dim(mln_value(I));
+
+ for_all(p)
+ {
+ const mln_sum(mln_value(I)) diff = original(p) - altered(p);
+
+ if (dim == 1)
+ mse += diff * diff;
+ else
+ for (unsigned i = 0; i < dim; ++i)
+ mse += diff[i] * diff[i];
+ }
+
+ mse /= ( altered.ncols() * altered.nrows() * dim);
+
+ const unsigned max = pow(2, mln_nbits(mln_value(I)) / dim) - 1;
+
+ return 20 * log10( max ) - 10 * log10(mse);
+ }
+ }
+ }
+}
+
+#endif
--
1.7.2.5