---
milena/sandbox/anthony/Makefile | 4 +-
milena/sandbox/anthony/src/scale_space.cc | 171 ++++++++++++++++++++++++++---
2 files changed, 157 insertions(+), 18 deletions(-)
diff --git a/milena/sandbox/anthony/Makefile b/milena/sandbox/anthony/Makefile
index 558bef5..e43db7f 100644
--- a/milena/sandbox/anthony/Makefile
+++ b/milena/sandbox/anthony/Makefile
@@ -9,10 +9,10 @@ OUTPUT=a.out
all: scale
-scale:
+scale: clean
$(CCACHE) $(CC) $(CFLAGS) -O3 -DNDEBUG $(CLIBS) $(SRC) -o $(OUTPUT)
-debug:
+debug: mrproper
$(CCACHE) $(CC) $(CFLAGS) -g -ggdb $(CLIBS) $(SRC) -o $(OUTPUT)
clean:
diff --git a/milena/sandbox/anthony/src/scale_space.cc
b/milena/sandbox/anthony/src/scale_space.cc
index 61308c4..0eca2b6 100644
--- a/milena/sandbox/anthony/src/scale_space.cc
+++ b/milena/sandbox/anthony/src/scale_space.cc
@@ -1,6 +1,9 @@
#include <mln/core/image/image2d.hh>
#include <mln/data/all.hh>
#include <mln/io/pgm/all.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/literal/all.hh>
#include <cmath>
@@ -36,13 +39,8 @@ void convolve(const I& original, I& filtered, double *kernel,
unsigned t)
window2d win;
for (int i = -(size / 2); i < (size / 2) + 1; ++i)
- {
for (int j = -(size / 2); j < (size / 2) + 1; ++j)
- {
win.insert(i, j);
- }
- }
-
// Iterate through all image sites
for_all(p)
@@ -139,7 +137,7 @@ void buildOctave(const I& original,
I blured;
initialize(blured, original);
- name << "output/o" << n << "b0.pgm";
+ name << "output/SS-o" << n << "-0.pgm";
io::pgm::save(original, name.str());
octave.push_back(original);
@@ -150,49 +148,190 @@ void buildOctave(const I& original,
octave.push_back(blured);
name.str("");
- name << "output/o" << n << "b" << i
<< ".pgm";
+ name << "output/SS-o" << n << "-" << i
<< ".pgm";
io::pgm::save(blured, name.str());
}
scaleSpace.push_back(octave);
}
+// Build n octaves on b blur levels
template<typename I>
void buildScaleSpace(std::vector< std::vector<I> >& scaleSpace,
const I& original,
- unsigned octave_level,
- unsigned blur_level)
+ unsigned n,
+ unsigned b)
{
- if (octave_level > 2)
+ if (n > 2)
{
// 1st octave
- buildOctave(original, 1, blur_level, scaleSpace);
+ buildOctave(original, 1, b, scaleSpace);
// 2nd octave
I reduced = downscaleResolution(original);
- buildOctave(reduced, 2, blur_level, scaleSpace);
+ buildOctave(reduced, 2, b, scaleSpace);
- for (unsigned i = 3; i <= octave_level; ++i)
+ for (unsigned i = 3; i <= n; ++i)
{
// i-th octave
reduced = downscaleResolution(reduced);
- buildOctave(reduced, i, blur_level, scaleSpace);
+ buildOctave(reduced, i, b, scaleSpace);
+ }
+ }
+ else
+ {
+ std::cerr << "ERROR: buildScaleSpace: Wrong level number (" <<
n << ")"
+ << std::endl;
+ }
+}
+
+// Build the DoG pyramid of the scale space
+template<typename I>
+void buildDifferenceOfGaussianSpace(std::vector< std::vector<I> >&
scaleSpace,
+ std::vector< std::vector<I> >&
dogSpace)
+{
+ for (unsigned i = 0; i < scaleSpace.size(); ++i)
+ {
+ std::vector<I> octave = scaleSpace.at(i);
+ std::vector<I> dogOctave;
+
+ for (unsigned j = 0; j < octave.size() - 1; ++j)
+ {
+ std::stringstream name;
+ I level1 = octave.at(j);
+ I level2 = octave.at(j + 1);
+ I dog;
+
+ initialize(dog, level1);
+
+ mln_piter(I) p(level1.domain());
+
+ for_all(p)
+ dog(p) = level1(p) - level2(p);
+
+ dogOctave.push_back(dog);
+ name << "output/DoG_o" << i << "-" << j
<< ".pgm";
+ io::pgm::save(dog, name.str());
}
+
+ dogSpace.push_back(dogOctave);
+ }
+}
+
+// Find the extremum value in the c8 neighborhood
+template<typename T, typename I, typename N>
+void find_extremum(T& min, T& max, const I& current, N n)
+{
+ for_all(n)
+ {
+ if (current(n) > max)
+ max = current(n);
+
+ if (current(n) < min)
+ min = current(n);
}
}
+// Find the minimum value in the upper and lower layers around p
+template<typename T, typename I, typename P>
+void find_min(T& min, const I& upper, const I& lower, const P& p)
+{
+ mln_niter(neighb2d) n(c8(), p);
+
+ for_all(n)
+ {
+ if (lower(n) < min)
+ min = lower(n);
+
+ if (upper(n) < min)
+ min = upper(n);
+ }
+}
+
+// Find the maximum value in the upper and lower layers around p
+template<typename T, typename I, typename P>
+void find_max(T& max, const I& upper, const I& lower, const P& p)
+{
+ mln_niter(neighb2d) n(c8(), p);
+
+ for_all(n)
+ {
+ if (lower(n) > max)
+ max = lower(n);
+
+ if (upper(n) > max)
+ max = upper(n);
+ }
+}
+
+// Build the extrema image
+template<typename I, typename C>
+void buildExtrema(C extrema,
+ I original,
+ std::vector< std::vector<I> >& dogSpace)
+{
+ extrema = data::convert(value::rgb8(), original);
+ value::int_u8 min = 255;
+ value::int_u8 max = 0;
+ value::int_u8 center = 0;
+
+ for (unsigned i = 0; i < dogSpace.size(); ++i)
+ {
+ std::vector<I> octave = dogSpace.at(i);
+
+ for (unsigned j = 1; j < octave.size() - 1; ++j)
+ {
+ I current = octave.at(j);
+ I upper = octave.at(j+1);
+ I lower = octave.at(j-1);
+
+ mln_piter(I) p(current.domain());
+
+ for_all(p)
+ {
+ mln_niter(neighb2d) n(c8(), p);
+ center = current(p);
+
+ find_extremum(min, max, current, n);
+
+ if (center <= min)
+ {
+ find_min(min, upper, lower, p);
+
+ if (center <= min)
+ extrema(p) = literal::blue;
+ }
+ else if (center >= max)
+ {
+ find_max(max, upper, lower, p);
+
+ if (center >= max)
+ extrema(p) = literal::red;
+ }
+ }
+ }
+ }
+ io::ppm::save(extrema, "output/extrema.ppm");
+}
+
// Main entry point
int main(int argc, char** argv)
{
typedef image2d<value::int_u8> I;
- const unsigned blur_level = 3;
+ typedef image2d<value::rgb8> C;
+
+ const unsigned blur_level = 4;
const unsigned octave_level = 4;
std::vector< std::vector<I> > scaleSpace;
+ std::vector< std::vector<I> > dogSpace;
I original;
+ C extrema;
- io::pgm::load(original, "images/flower.pgm");
+ io::pgm::load(original, "images/keith512.pgm");
buildScaleSpace(scaleSpace, original, octave_level, blur_level);
+ buildDifferenceOfGaussianSpace(scaleSpace, dogSpace);
+ buildExtrema(extrema, original, dogSpace);
return 0;
}
--
1.7.2.5