olena: olena-2.0-597-gb783446 [SIFT] Start new implementation + Build Scale Space

--- milena/sandbox/anthony/{ => new-implem}/Makefile | 18 +- milena/sandbox/anthony/new-implem/src/main.cc | 63 +++++ .../sandbox/anthony/{ => new-implem}/src/matrix.cc | 0 .../sandbox/anthony/{ => new-implem}/src/matrix.hh | 3 +- .../sandbox/anthony/new-implem/src/scale-space.hh | 106 +++++++ milena/sandbox/anthony/new-implem/src/vrac/vrac.hh | 296 ++++++++++++++++++++ 6 files changed, 475 insertions(+), 11 deletions(-) copy milena/sandbox/anthony/{ => new-implem}/Makefile (53%) create mode 100644 milena/sandbox/anthony/new-implem/src/main.cc copy milena/sandbox/anthony/{ => new-implem}/src/matrix.cc (100%) copy milena/sandbox/anthony/{ => new-implem}/src/matrix.hh (99%) create mode 100644 milena/sandbox/anthony/new-implem/src/scale-space.hh create mode 100644 milena/sandbox/anthony/new-implem/src/vrac/vrac.hh diff --git a/milena/sandbox/anthony/Makefile b/milena/sandbox/anthony/new-implem/Makefile similarity index 53% copy from milena/sandbox/anthony/Makefile copy to milena/sandbox/anthony/new-implem/Makefile index 2953013..a4f63d9 100644 --- a/milena/sandbox/anthony/Makefile +++ b/milena/sandbox/anthony/new-implem/Makefile @@ -1,15 +1,15 @@ -CCACHE=ccache +CCACHE= CC=g++ -CFLAGS=-Wall -Werror -CLIBS=-I../../ -CLEAN=*.o output/* log +CFLAGS=-Wall -Wextra +CLIBS=-I../../../ +CLEAN=*.o output/* log debug_* -SRC=src/main.cc src/matrix.cc src/keypoint.cc -OUTPUT=a.out +SRC=src/main.cc src/matrix.cc +OUTPUT=new-implem -all: scale +all: new-implem -scale: clean +new-implem: clean $(CCACHE) $(CC) $(CFLAGS) -O3 -DNDEBUG $(CLIBS) $(SRC) -o $(OUTPUT) debug: mrproper @@ -21,4 +21,4 @@ clean: mrproper: clean rm -f $(OUTPUT) -.PHONY: scale clean mrproper +.PHONY: new-implem clean mrproper diff --git a/milena/sandbox/anthony/new-implem/src/main.cc b/milena/sandbox/anthony/new-implem/src/main.cc new file mode 100644 index 0000000..45a36ad --- /dev/null +++ b/milena/sandbox/anthony/new-implem/src/main.cc @@ -0,0 +1,63 @@ +#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 <mln/value/int_s8.hh> + +//#include <cmath> +#include <string> + +#include "scale-space.hh" +//#include "dog-space.hh" +//#include "keypoint.hh" +//#include "matrix.hh" + +int main(void) +{ + typedef image2d<value::int_u8> I; + typedef image2d<value::rgb8> C; + + // General parameters + std::string source("images/keith.pbm"); + const unsigned blur_level = 5; + const unsigned octave_level = 3; + const bool black = false; + + ScaleSpace<I> *ss = new ScaleSpace<I>(octave_level, blur_level); + //DoGSpace<C>* dog = new DogSpace(); + //std::vector<Keypoint>* keypoints = new std::vector<Keypoint>(); + + I original; + C extrema, improved; + + io::pgm::load(original, source.c_str()); + + if (black) + { + initialize(extrema, original); + initialize(improved, original); + } + else + { + extrema = data::convert(value::rgb8(), original); + improved = data::convert(value::rgb8(), original); + } + + // Localization + ss->build(original); + ss->save(); + //buildDifferenceOfGaussianSpace(scaleSpace, dogSpace); + //buildExtrema(extrema, dogSpace, keypoints); + //discardLowContrastKeypoints(dogSpace, keypoints, improved); + + // Processing + // TODO + + // Save + io::ppm::save(extrema, "output/extrema.ppm"); + io::ppm::save(improved, "output/extrema_improved.ppm"); + + return 0; +} diff --git a/milena/sandbox/anthony/src/matrix.cc b/milena/sandbox/anthony/new-implem/src/matrix.cc similarity index 100% copy from milena/sandbox/anthony/src/matrix.cc copy to milena/sandbox/anthony/new-implem/src/matrix.cc diff --git a/milena/sandbox/anthony/src/matrix.hh b/milena/sandbox/anthony/new-implem/src/matrix.hh similarity index 99% copy from milena/sandbox/anthony/src/matrix.hh copy to milena/sandbox/anthony/new-implem/src/matrix.hh index de83912..c42de59 100644 --- a/milena/sandbox/anthony/src/matrix.hh +++ b/milena/sandbox/anthony/new-implem/src/matrix.hh @@ -16,6 +16,7 @@ class Matrix bool inverse(Matrix& inversed); void absolute(); bool isMajorOffset(); + float determinant(); // Operators Matrix operator*(Matrix& right); @@ -31,8 +32,6 @@ class Matrix std::vector< std::vector<float> > m; unsigned height; unsigned width; - - float determinant(); }; #endif /* ! MATRIX_HH */ diff --git a/milena/sandbox/anthony/new-implem/src/scale-space.hh b/milena/sandbox/anthony/new-implem/src/scale-space.hh new file mode 100644 index 0000000..2fbb4fd --- /dev/null +++ b/milena/sandbox/anthony/new-implem/src/scale-space.hh @@ -0,0 +1,106 @@ +#ifndef SCALE_SPACE_HH +# define SCALE_SPACE_HH + +# include <string> +# include <vector> + +#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 <mln/value/int_s8.hh> + +#include "vrac/vrac.hh" + +using namespace mln; + +template<typename I> +class ScaleSpace +{ + public: + ScaleSpace(unsigned octave_level, unsigned gradient_level) + { + o = octave_level; + g = gradient_level; + } + + ~ScaleSpace() + { + typedef typename std::vector< std::vector<I> >::iterator PIT; + + for (PIT it = pyramid.begin(); it != pyramid.end(); ++it) + it->clear(); + + pyramid.clear(); + } + + std::vector<I>& getOctave(unsigned i) + { + return pyramid[i]; + } + + + void build(const I& original) + { + // Upscaled octave + I upscaled = vrac::upscaling2(original); + addOctave(upscaled); + + // 1st octave + addOctave(original); + + // 2nd octave + I downscaled = vrac::downscaling2(original); + addOctave(downscaled); + + for (unsigned i = 3; i < o; ++i) + { + downscaled = vrac::downscaling2(downscaled); + addOctave(downscaled); + } + } + + void save() + { + std::stringstream name; + + for (unsigned i = 0; i < pyramid.size(); ++i) + { + for (unsigned j = 0; j < pyramid[i].size(); ++j) + { + name << "output/ss-o" << i << "-" << j << ".pgm"; + io::pgm::save(pyramid[i][j], name.str()); + name.str(""); + } + } + } + + inline unsigned octave_count() { return pyramid.size(); } + inline unsigned gradient_count() { return pyramid[0].size(); } + + private: + unsigned o; + unsigned g; + std::vector< std::vector<I> > pyramid; + + void addOctave(const I& original) + { + I blured; + std::vector<I> octave; + //float variance = sqrt(2); + float variance = 0.84089642; + + for (unsigned i = 0; i < g; ++i) + { + blured = vrac::blur(original, variance); + variance *= sqrt(2); + octave.push_back(blured); + } + + pyramid.push_back(octave); + } +}; + +#endif /* ! SCALE_SPACE_HH */ diff --git a/milena/sandbox/anthony/new-implem/src/vrac/vrac.hh b/milena/sandbox/anthony/new-implem/src/vrac/vrac.hh new file mode 100644 index 0000000..fc9e3f2 --- /dev/null +++ b/milena/sandbox/anthony/new-implem/src/vrac/vrac.hh @@ -0,0 +1,296 @@ +#ifndef VRAC_HH +# define VRAC_HH + +# 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 <mln/value/int_s8.hh> + +# include <cmath> + +# include "../matrix.hh" + +//# include "keypoint.hh" +//# include "matrix.hh" + +using namespace mln; + +namespace vrac +{ + // Set the gaussian kernel + float *gaussian_kernel(float variance) + { + unsigned index = 0; + float *kernel = new float[49]; + Matrix matrix(7, 7); + float sum = 0; + + for (int i = -3; i < 4; ++i) + { + for (int j = -3; j < 4; ++j) + { + kernel[index] = exp(- (i*i + j*j) / (2.0 * variance * variance) ); + sum += kernel[index++]; + } + } + + sum = 1. / sum; + + for (int i = 0; i < 49; ++i) + kernel[i] *= sum; + + return kernel; + } + + // Apply the convolution of the image by the kernel + template<typename I> + void convolve(const I& original, I& filtered, float *kernel) + { + mln_piter(I) p(filtered.domain()); + window2d win; + + for (int i = -3; i < 4; ++i) + for (int j = -3; j < 4; ++j) + win.insert(i, j); + + // Iterate through all image sites + for_all(p) + { + // Create the window around the site + mln_qiter(window2d) q(win, p); + float sum = 0; + int index = 0; + + // Iterate through all window image sites + for_all(q) + { + if (filtered.has(q)) + sum += original(q) * kernel[index++]; + else + sum += 127 * kernel[index++]; + } + + filtered(p) = static_cast<int>(sum); + } + } + + // Blur the image thanks to a convolution matrix + template<typename I> + I blur(const I& original, float variance) + { + std::cout << "variance: " << variance << std::endl; + I filtered; + float *kernel = gaussian_kernel(variance); + + initialize(filtered, original); + convolve(original, filtered, kernel); + + return filtered; + } + + float *upscalingTL_kernel() + { + const static float one = 1.0 / 8.0; + const static float two = 2.0 / 8.0; + const static float three = 2.0 / 8.0; + const static float four = 3.0 / 8.0; + + float *kernel = new float[4]; + + kernel[0] = one; + kernel[1] = two; + kernel[2] = three; + kernel[3] = four; + + return kernel; + } + + float *upscalingTR_kernel() + { + const static float one = 2.0 / 8.0; + const static float two = 1.0 / 8.0; + const static float three = 3.0 / 8.0; + const static float four = 2.0 / 8.0; + + float *kernel = new float[4]; + + kernel[0] = one; + kernel[1] = two; + kernel[2] = three; + kernel[3] = four; + + return kernel; + } + + float *upscalingBL_kernel() + { + const static float one = 2.0 / 8.0; + const static float two = 3.0 / 8.0; + const static float three = 1.0 / 8.0; + const static float four = 2.0 / 8.0; + + float *kernel = new float[4]; + + kernel[0] = one; + kernel[1] = two; + kernel[2] = three; + kernel[3] = four; + + return kernel; + } + + float *upscalingBR_kernel() + { + const static float one = 3.0 / 8.0; + const static float two = 2.0 / 8.0; + const static float three = 2.0 / 8.0; + const static float four = 1.0 / 8.0; + + float *kernel = new float[4]; + + kernel[0] = one; + kernel[1] = two; + kernel[2] = three; + kernel[3] = four; + + return kernel; + } + + template<typename I> + unsigned upscalePixel(const I& original, int i, int j, int type) + { + float *kernel; + window2d win; + mln_psite(I) p(i, j); + float value = 0; + unsigned index = 0; + int iStart = 0; + int jStart = 0; + + if (type == 0) + { + kernel = upscalingTL_kernel(); + iStart = -1; + jStart = -1; + } + else if (type == 1) + { + kernel = upscalingTR_kernel(); + iStart = 0; + jStart = -1; + } + else if (type == 2) + { + kernel = upscalingBL_kernel(); + iStart = -1; + jStart = 0; + } + else + { + kernel = upscalingBR_kernel(); + iStart = 0; + jStart = 0; + } + + for (int ii = iStart; ii < iStart + 2; ++ii) + for (int jj = jStart; jj < jStart + 2; ++jj) + win.insert(ii, jj); + + mln_qiter(window2d) q(win, p); + + for_all(q) + { + if (original.has(q)) + { + value += original(q) * kernel[index]; + } + + ++index; + } + + return (static_cast<int>(value)); + } + // Downscale by 2 the image resolution + template<typename I> + I downscaling2(const I& original) + { + mln_piter(I) p(original.domain()); + window2d win; + int index = 0; + + // Initialize the rescaled image + box2d size(original.nrows() / 2, original.ncols() / 2); + I reduced(size); + + // Set the 2x2 window matrix + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 2; ++j) + win.insert(i, j); + + // Iterate through all image sites + for_all(p) + { + // Get 1/4 of total pixels + if (index % 2 == 0) + { + int i = (index % original.ncols()) / 2; + int j = (index / original.ncols()) / 2; + int count = 0; + int sum = 0; + mln_qiter(window2d) q(win, p); + + // Iterate through all window image sites + for_all(q) + { + if (original.has(q)) + { + sum += original(q); + ++count; + } + } + + if (reduced.has(point2d(j, i))) + opt::at(reduced, j, i) = sum / count; + } + + ++index; + } + + return reduced; + } + + // Upscale by 2 the image resolution + template<typename I> + I upscaling2(const I& original) + { + box2d size(original.nrows() * 2, original.ncols() * 2); + I upscaled(size); + + mln_piter(I) p(upscaled.domain()); + int index = 0; + + for_all(p) + { + int i = p.col(); + int j = p.row(); + + if (i % 2 == 0 && j % 2 == 0) // Top left + opt::at(upscaled, i, j) = upscalePixel(original, i / 2, j / 2, 0); + else if (i % 2 == 0) // Bottom left + opt::at(upscaled, i, j) = upscalePixel(original, i / 2, j / 2, 2); + else if (j % 2 == 0) // Top right + opt::at(upscaled, i, j) = upscalePixel(original, i / 2, j / 2, 1); + else // Bottom right + opt::at(upscaled, i, j) = upscalePixel(original, i / 2, j / 2, 3); + + ++index; + } + + return upscaled; + } +} + +#endif /* ! VRAC_HH */ -- 1.7.10.4
participants (1)
-
Anthony Seure