* lazzara/irm/hsl_grad_and_wst.cc: perform a gradient on a HSL image
and compute the watershed.
* lazzara/irm/wst_rag.cc: Improve output and add a usage.
* lazzara/irm/wst_rag_hsl.cc: new. Similar code to wst_rag.cc but
the graph values are computed thanks to the HSL image.
---
milena/sandbox/ChangeLog | 12 ++
milena/sandbox/lazzara/irm/hsl_grad_and_wst.cc | 97 ++++++++++++++
milena/sandbox/lazzara/irm/wst_rag.cc | 70 +++++++---
.../lazzara/irm/{wst_rag.cc => wst_rag_hsl.cc} | 140 +++++++++++++-------
4 files changed, 254 insertions(+), 65 deletions(-)
create mode 100644 milena/sandbox/lazzara/irm/hsl_grad_and_wst.cc
copy milena/sandbox/lazzara/irm/{wst_rag.cc => wst_rag_hsl.cc} (72%)
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index b90be00..d96c70e 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,3 +1,15 @@
+2009-02-12 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Update code related to Region Adjacency Graph.
+
+ * lazzara/irm/hsl_grad_and_wst.cc: perform a gradient on a HSL image
+ and compute the watershed.
+
+ * lazzara/irm/wst_rag.cc: Improve output and add a usage.
+
+ * lazzara/irm/wst_rag_hsl.cc: new. Similar code to wst_rag.cc but
+ the graph values are computed thanks to the HSL image.
+
2009-02-11 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Cleanup pseudo-tree computation.
diff --git a/milena/sandbox/lazzara/irm/hsl_grad_and_wst.cc
b/milena/sandbox/lazzara/irm/hsl_grad_and_wst.cc
new file mode 100644
index 0000000..f7b0335
--- /dev/null
+++ b/milena/sandbox/lazzara/irm/hsl_grad_and_wst.cc
@@ -0,0 +1,97 @@
+#include <mln/essential/2d.hh>
+#include <mln/value/hsl.hh>
+#include <mln/core/image/violent_cast_image.hh>
+#include <mln/extract/all.hh>
+#include <mln/value/label_16.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/morpho/closing_area.hh>
+#include <mln/io/dump/save.hh>
+
+mln::value::int_u8 foo(unsigned u)
+{
+ return u == 0 ?
+ 0 : // wshed line
+ 1 + (u - 1) % 255; // basin
+}
+
+
+namespace mln
+{
+
+ struct hsl2rgb : Function_v2v<hsl2rgb>
+ {
+ typedef value::rgb8 result;
+
+ value::rgb8 operator()(const value::hsl_f& v) const
+ {
+ value::rgb8 res((v.hue() / 360.0f) * 255.0f,
+ v.sat() * 255.0f,
+ v.lum());
+ return res;
+ }
+ };
+
+}
+
+
+
+int main(int, char *argv[])
+{
+ using namespace mln;
+
+ using value::rgb8;
+ using value::hsl_f;
+ using value::int_u8;
+ using value::label_16;
+
+ typedef value::hsl_<short, short, short> hsl_s;
+ typedef image2d<rgb8> I;
+ typedef image2d<hsl_f> J;
+
+ I input_;
+ io::ppm::load(input_, argv[1]);
+ J input = level::convert(hsl_f(), input_);
+
+ std::cout << "input_rgb(p) = " << input_(point2d(310,0)) <<
" - input_hsl(p) = " << input(point2d(310,0))
+ << " hsl2rgb(p) = " << hsl2rgb()(input(point2d(310,0)))
+ << std::endl;
+ std::cout << "input_rgb(p) = " << input_(point2d(311,0)) <<
" - input_hsl(p) = " << input(point2d(311,0))
+ << " hsl2rgb(p) = " << hsl2rgb()(input(point2d(311,0)))
+ << std::endl;
+
+ /// Compute the gradient on each component of the HSL image.
+ /// Then keep the max values in the three images.
+ image2d<float> grad_hue;
+ initialize(grad_hue, input);
+ data::fill(grad_hue, extract::hue(input));
+ image2d<float> grad_sat;
+ initialize(grad_sat, input);
+ data::fill(grad_sat, extract::sat(input));
+ image2d<float> grad_lum;
+ initialize(grad_lum, input);
+ data::fill(grad_lum, extract::lum(input));
+ grad_hue = morpho::gradient(grad_hue, win_c4p());
+ grad_sat = morpho::gradient(grad_sat, win_c4p());
+ grad_lum = morpho::gradient(grad_lum, win_c4p());
+
+ image2d<value::int_u8> grad;
+ initialize(grad, grad_hue);
+ mln_piter_(image2d<value::int_u8>) p(grad.domain());
+ for_all(p)
+ grad(p) = math::max(grad_hue(p), math::max(grad_sat(p), grad_lum(p)));
+ io::pgm::save(grad, "hsl2rgb_grad.pgm");
+
+ image2d<int_u8> clo = morpho::closing_area(grad, c4(), 10);
+ io::pgm::save(clo, "hsl2rgb_clo_a100.pgm");
+
+ label_16 nbasins;
+ image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+ io::dump::save(wshed, "hsl2rgb_wshed.dump");
+ std::cout << "nbasins = " << nbasins << std::endl;
+ io::pgm::save(level::transform(wshed, convert::to_fun(foo)),
+ "hsl2rgb_wshed.pgm");
+
+ I out = level::transform(input, hsl2rgb());
+ io::ppm::save(out, "hsl2rgb_out.ppm");
+
+}
diff --git a/milena/sandbox/lazzara/irm/wst_rag.cc
b/milena/sandbox/lazzara/irm/wst_rag.cc
index 3aa0935..e397ba7 100644
--- a/milena/sandbox/lazzara/irm/wst_rag.cc
+++ b/milena/sandbox/lazzara/irm/wst_rag.cc
@@ -20,6 +20,10 @@
#include <mln/extract/all.hh>
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a RGB image.
+
namespace mln
{
@@ -92,12 +96,13 @@ namespace mln
}
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
template <typename I>
inline
- pw::image<fun::i2v::array<value::int_u8>, p_edges<util::graph,
fun::i2v::array<mln_site(I)> > >
- make_edge_graph_image(const I& ima_v, const util::graph& g) // image on graph
vertices; value = mean color per vertex (watershed basin)
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
{
-
// edge sites.
typedef fun::i2v::array<mln_site(I)> edge_site_t;
edge_site_t edge_site(g.e_nmax(), literal::origin);
@@ -129,9 +134,9 @@ namespace mln
// Cf. sandbox/theo/color/segment_rgb_pixels.cc
util::array<vec3d_f> m_3f =
labeling::compute(accu::mean<mln_value(I)>(),
- input, // input color image
- w, // watershed labeling
- nbasins);
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
m_3f[0] = literal::zero;
util::array<mln_value(I)> m;
@@ -145,14 +150,17 @@ namespace mln
return m;
}
+
template <typename I, typename J>
- pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph,
fun::i2v::array<mln_site(I)> > >
+ pw::image<fun::i2v::array<mln_value(I)>,
+ p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
make_vertex_graph_image(const util::graph& g, const I&input,
const J& w, const mln_value(J)& nbasins)
{
typedef util::array<mln_site(I)> vertex_sites_t;
vertex_sites_t site_values;
- convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
site_values);
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
typedef fun::i2v::array<mln_site(J)> f_sites_t;
f_sites_t sites;
@@ -165,7 +173,8 @@ namespace mln
typedef fun::i2v::array<mln_value(I)> vertex_values_t;
vertex_values_t vertex_values;
- convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+ convert::from_to(mean_color_values(input, w, nbasins),
+ vertex_values);
mln_VAR(ima_v, (vertex_values | pv));
@@ -207,7 +216,9 @@ namespace mln
template <typename I, typename V, typename E>
inline
image2d<mln_value(I)>
- make_debug_graph_image(const I& input, const V& ima_v, const E& ima_e,
unsigned box_size)
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size)
{
image2d<mln_value(I)> ima;
initialize(ima, input);
@@ -233,7 +244,7 @@ namespace mln
}
-int main(int, char *argv[])
+int main(int argc, char *argv[])
{
using namespace mln;
@@ -247,7 +258,19 @@ int main(int, char *argv[])
typedef image2d<rgb8> I;
typedef image2d<label_16> J;
- unsigned box_size = atoi(argv[3]);
+ if (argc < 5)
+ {
+ std::cout << argv[0] << " <input.ppm> <wsh-label16.dump>
<nbasins> <box_size> <dist_max>"
+ << std::endl << std::endl;
+
+ std::cout << "box_size: size of the component mean color box."
<< std::endl;
+ std::cout << "dist_max: merge two vertices if the associted edge value
<= dist_max"
+ << std::endl;
+
+ return 1;
+ }
+
+ unsigned box_size = atoi(argv[4]);
I input;
io::ppm::load(input, argv[1]);
@@ -256,16 +279,18 @@ int main(int, char *argv[])
J vol;
io::dump::load(vol, argv[2]);
- label_16 nbasins = 898;
+ label_16 nbasins = atoi(argv[3]);
std::cout << "nbasins = " << nbasins << std::endl;
util::graph g = make_graph(vol, c4(), nbasins);
+ // Compute value distances with a RGB image.
mln_VAR(ima_v, make_vertex_graph_image(g, input, vol, nbasins));
mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
//DEBUG
-// io::ppm::save(make_debug_graph_image(input, ima_v, ima_e, box_size),
"wst_rag_graph_image.ppm");
+// io::ppm::save(make_debug_graph_image(input, ima_v, ima_e, box_size),
+// "wst_rag_graph_image.ppm");
mln_piter_(ima_e_t) e(ima_e.domain());
@@ -277,7 +302,7 @@ int main(int, char *argv[])
{
unsigned v1 = e.element().v1();
unsigned v2 = e.element().v2();
- if (ima_e(e) <= (unsigned)(atoi(argv[4]))
+ if (ima_e(e) <= (unsigned)(atoi(argv[5]))
&& find_root(parent, v1) != find_root(parent, v2))
parent[find_root(parent, v1)] = find_root(parent, v2);
}
@@ -298,10 +323,19 @@ int main(int, char *argv[])
J vol2 = level::transform(vol, f);
util::graph g2 = make_graph(vol2, c4(), nbasins2);
+ // Compute value distances with a RGB image.
mln_VAR(ima_v2, make_vertex_graph_image(g2, input, vol2, nbasins2));
mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
- J vol2_ = morpho::elementary::dilation(vol2, c4());
- io::ppm::save(labeling::mean_values(input, vol2_, nbasins2),
"wst_rag_mean_colors.ppm");
- io::ppm::save(make_debug_graph_image(input, ima_v2, ima_e2, box_size),
"wst_rag_graph_image2.ppm");
+ mln_VAR(vol2_,
+ morpho::elementary::dilation(extend(vol2 | (pw::value(vol2) == 0u),
+ vol2),
+ c8()));
+
+ data::fill((vol2 | (pw::value(vol2) == 0u)).rw(), vol2_);
+
+ io::ppm::save(labeling::mean_values(input, vol2, nbasins2),
+ "wst_rag_mean_colors.ppm");
+ io::ppm::save(make_debug_graph_image(input, ima_v2, ima_e2, box_size),
+ "wst_rag_graph_image2.ppm");
}
diff --git a/milena/sandbox/lazzara/irm/wst_rag.cc
b/milena/sandbox/lazzara/irm/wst_rag_hsl.cc
similarity index 72%
copy from milena/sandbox/lazzara/irm/wst_rag.cc
copy to milena/sandbox/lazzara/irm/wst_rag_hsl.cc
index 3aa0935..156f1b3 100644
--- a/milena/sandbox/lazzara/irm/wst_rag.cc
+++ b/milena/sandbox/lazzara/irm/wst_rag_hsl.cc
@@ -1,24 +1,44 @@
#include <mln/essential/2d.hh>
+
+
+#include <mln/core/alias/dpoint2d.hh>
#include <mln/core/alias/vec3d.hh>
-#include <mln/debug/draw_graph.hh>
-#include <mln/util/graph.hh>
+#include <mln/core/image/line_graph_elt_neighborhood.hh>
+
#include <mln/accu/center.hh>
-#include <mln/io/dump/all.hh>
-#include <mln/value/label_16.hh>
-#include <mln/value/label_8.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/value/rgb16.hh>
#include <mln/accu/compute.hh>
-#include <mln/core/alias/dpoint2d.hh>
-#include <mln/draw/box.hh>
-#include <mln/level/stretch.hh>
+
#include <mln/canvas/morpho/algebraic_union_find.hh>
+
+#include <mln/debug/draw_graph.hh>
+
+#include <mln/draw/box.hh>
+
+#include <mln/extract/all.hh>
+
#include <mln/fun/v2v/id.hh>
-#include <mln/core/image/line_graph_elt_neighborhood.hh>
-#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/io/dump/all.hh>
+
#include <mln/labeling/mean_values.hh>
-#include <mln/extract/all.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/value/label_16.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb16.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/value/hsl.hh>
+
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a HSL image.
+
namespace mln
{
@@ -77,25 +97,24 @@ namespace mln
}
-
-
- template <typename V>
- value::int_u8 dist(const V& c1, const V& c2)
+ value::int_u8 dist(const value::hsl_f& c1, const value::hsl_f& c2)
{
unsigned d = 0;
- d += (math::diff_abs(c1.red(), c2.red()) + 2) / 3;
- d += (math::diff_abs(c1.green(), c2.green()) + 2) / 3;
- d += (math::diff_abs(c1.blue(), c2.blue()) + 2) / 3;
+ d += (math::diff_abs(c1.hue(), c2.hue()) + 2) / 3;
+ d += (math::diff_abs(c1.sat(), c2.sat()) + 2) / 3;
+ d += (math::diff_abs(c1.lum(), c2.lum()) + 2) / 3;
if (d > 255)
d = 255;
return d;
}
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
template <typename I>
inline
- pw::image<fun::i2v::array<value::int_u8>, p_edges<util::graph,
fun::i2v::array<mln_site(I)> > >
- make_edge_graph_image(const I& ima_v, const util::graph& g) // image on graph
vertices; value = mean color per vertex (watershed basin)
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
{
// edge sites.
@@ -128,31 +147,29 @@ namespace mln
{
// Cf. sandbox/theo/color/segment_rgb_pixels.cc
- util::array<vec3d_f> m_3f =
labeling::compute(accu::mean<mln_value(I)>(),
- input, // input color image
- w, // watershed labeling
- nbasins);
- m_3f[0] = literal::zero;
+ util::array<value::hsl_f> m_3f =
labeling::compute(accu::mean<mln_value(I)>(),
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
+ m_3f[0] = value::hsl_f(0,0,0);;
util::array<mln_value(I)> m;
convert::from_to(m_3f, m);
- m[0] = literal::yellow;
-
- io::ppm::save(level::transform(w,
- convert::to< fun::i2v::array<mln_value(I)> >(m)),
- "wst_rag_wshd_color.ppm");
+ m[0] = value::hsl_f(360,0.5,255);
return m;
}
template <typename I, typename J>
- pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph,
fun::i2v::array<mln_site(I)> > >
+ pw::image<fun::i2v::array<mln_value(I)>,
+ p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
make_vertex_graph_image(const util::graph& g, const I&input,
const J& w, const mln_value(J)& nbasins)
{
typedef util::array<mln_site(I)> vertex_sites_t;
vertex_sites_t site_values;
- convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
site_values);
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
typedef fun::i2v::array<mln_site(J)> f_sites_t;
f_sites_t sites;
@@ -207,7 +224,9 @@ namespace mln
template <typename I, typename V, typename E>
inline
image2d<mln_value(I)>
- make_debug_graph_image(const I& input, const V& ima_v, const E& ima_e,
unsigned box_size)
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size)
{
image2d<mln_value(I)> ima;
initialize(ima, input);
@@ -233,7 +252,7 @@ namespace mln
}
-int main(int, char *argv[])
+int main(int argc, char *argv[])
{
using namespace mln;
@@ -243,20 +262,35 @@ int main(int, char *argv[])
using value::label_8;
using value::rgb16;
using value::rgb8;
+ using value::hsl_f;
- typedef image2d<rgb8> I;
+// typedef image2d<rgb8> I;
+ typedef image2d<rgb8> K;
+ typedef image2d<hsl_f> I;
typedef image2d<label_16> J;
- unsigned box_size = atoi(argv[3]);
+ if (argc < 5)
+ {
+ std::cout << argv[0] << " <input.ppm> <wsh-label16.dump>
<nbasins> <box_size> <dist_max>"
+ << std::endl << std::endl;
+
+ std::cout << "box_size: size of the component mean color box."
<< std::endl;
+ std::cout << "dist_max: merge two vertices if the associted edge value
<= dist_max"
+ << std::endl;
- I input;
- io::ppm::load(input, argv[1]);
-// image2d<rgb16> input = level::convert(rgb16(), input_);
+ return 1;
+ }
+
+ unsigned box_size = atoi(argv[4]);
+
+ K input_;
+ io::ppm::load(input_, argv[1]);
+ I input = level::convert(hsl_f(), input_);
J vol;
io::dump::load(vol, argv[2]);
- label_16 nbasins = 898;
+ label_16 nbasins = atoi(argv[3]);
std::cout << "nbasins = " << nbasins << std::endl;
util::graph g = make_graph(vol, c4(), nbasins);
@@ -265,7 +299,8 @@ int main(int, char *argv[])
mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
//DEBUG
-// io::ppm::save(make_debug_graph_image(input, ima_v, ima_e, box_size),
"wst_rag_graph_image.ppm");
+ io::ppm::save(make_debug_graph_image(input, ima_v, ima_e, box_size),
+ "wst_rag_graph_image.ppm");
mln_piter_(ima_e_t) e(ima_e.domain());
@@ -277,7 +312,7 @@ int main(int, char *argv[])
{
unsigned v1 = e.element().v1();
unsigned v2 = e.element().v2();
- if (ima_e(e) <= (unsigned)(atoi(argv[4]))
+ if (ima_e(e) <= (unsigned)(atoi(argv[5]))
&& find_root(parent, v1) != find_root(parent, v2))
parent[find_root(parent, v1)] = find_root(parent, v2);
}
@@ -298,10 +333,21 @@ int main(int, char *argv[])
J vol2 = level::transform(vol, f);
util::graph g2 = make_graph(vol2, c4(), nbasins2);
+
+ // Compute values distance on the HSL Image.
mln_VAR(ima_v2, make_vertex_graph_image(g2, input, vol2, nbasins2));
mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
- J vol2_ = morpho::elementary::dilation(vol2, c4());
- io::ppm::save(labeling::mean_values(input, vol2_, nbasins2),
"wst_rag_mean_colors.ppm");
- io::ppm::save(make_debug_graph_image(input, ima_v2, ima_e2, box_size),
"wst_rag_graph_image2.ppm");
+ mln_VAR(vol2_,
+ morpho::elementary::dilation(extend(vol2 | (pw::value(vol2) == 0u),
+ vol2),
+ c8()));
+
+ data::fill((vol2 | (pw::value(vol2) == 0u)).rw(), vol2_);
+
+ io::ppm::save(labeling::mean_values(input_, vol2, nbasins2),
+ "wst_rag_mean_colors.ppm");
+ io::ppm::save(make_debug_graph_image(input_, ima_v2, ima_e2, box_size),
+ "wst_rag_graph_image2.ppm");
+
}
--
1.5.6.5