---
milena/sandbox/anthony/Makefile | 2 +-
milena/sandbox/anthony/src/keypoint.cc | 39 +++++-
milena/sandbox/anthony/src/keypoint.hh | 29 +++--
milena/sandbox/anthony/src/main.cc | 226 ++++++++++++++++++++++++-------
milena/sandbox/anthony/src/matrix.cc | 30 ++++-
milena/sandbox/anthony/src/matrix.hh | 5 +-
6 files changed, 259 insertions(+), 72 deletions(-)
diff --git a/milena/sandbox/anthony/Makefile b/milena/sandbox/anthony/Makefile
index 83ee52b..2953013 100644
--- a/milena/sandbox/anthony/Makefile
+++ b/milena/sandbox/anthony/Makefile
@@ -4,7 +4,7 @@ CFLAGS=-Wall -Werror
CLIBS=-I../../
CLEAN=*.o output/* log
-SRC=src/matrix.cc src/keypoint.cc src/main.cc
+SRC=src/main.cc src/matrix.cc src/keypoint.cc
OUTPUT=a.out
all: scale
diff --git a/milena/sandbox/anthony/src/keypoint.cc
b/milena/sandbox/anthony/src/keypoint.cc
index bf0a5f5..937e78d 100644
--- a/milena/sandbox/anthony/src/keypoint.cc
+++ b/milena/sandbox/anthony/src/keypoint.cc
@@ -1,8 +1,8 @@
#include "keypoint.hh"
// Constructor
-Keypoint::Keypoint(unsigned i, unsigned j,
- unsigned scale, unsigned size, bool maximum)
+Keypoint::Keypoint(int i, int j,
+ int scale, int size, bool maximum)
{
this->i = i;
this->j = j;
@@ -11,8 +11,35 @@ Keypoint::Keypoint(unsigned i, unsigned j,
this->maximum = maximum;
}
+bool Keypoint::add(Matrix& offset, Keypoint& old)
+{
+ if (offset.get(0, 0) >= 1 || offset.get(0, 0) <= -1
+ || offset.get(1, 0) >= 1 || offset.get(1, 0) <= -1)
+ {
+ i += offset.get(0, 0);
+ j += offset.get(1, 0);
+ scale += offset.get(2, 0);
+
+ return (i != old.getI() && j != old.getJ());
+ }
+ else
+ return false;
+}
+
+//mln::point2d Keypoint::getPoint()
+//{
+ //mln::point2d p(i, j);
+
+ //return p;
+//}
+
// Getters
-unsigned Keypoint::getI() { return i; }
-unsigned Keypoint::getJ() { return j; }
-unsigned Keypoint::getScale() { return scale; }
-unsigned Keypoint::getSize() { return size; }
+int Keypoint::getI() { return i; }
+int Keypoint::getJ() { return j; }
+int Keypoint::getScale() { return scale; }
+int Keypoint::getSize() { return size; }
+
+// Setters
+void Keypoint::setI(int offsetI) { i = offsetI; }
+void Keypoint::setJ(int offsetJ) { j = offsetJ; }
+void Keypoint::setScale(int offsetScale) { scale = offsetScale; }
diff --git a/milena/sandbox/anthony/src/keypoint.hh
b/milena/sandbox/anthony/src/keypoint.hh
index 798a980..af24a4c 100644
--- a/milena/sandbox/anthony/src/keypoint.hh
+++ b/milena/sandbox/anthony/src/keypoint.hh
@@ -1,26 +1,35 @@
#ifndef KEYPOINT_HH
# define KEYPOINT_HH
+//# include <mln/core/alias/point2d.hh>
# include <ostream>
+# include "matrix.hh"
class Keypoint
{
public:
// Constructor
- Keypoint(unsigned i, unsigned j,
- unsigned scale, unsigned size, bool maximum);
+ Keypoint(int i, int j,
+ int scale, int size, bool maximum);
+
+ bool add(Matrix& k, Keypoint& old);
+ //mln::point2d getPoint();
// Getters
- unsigned getI();
- unsigned getJ();
- unsigned getScale();
- unsigned getSize();
+ int getI();
+ int getJ();
+ int getScale();
+ int getSize();
+
+ void setI(int offsetI);
+ void setJ(int offsetJ);
+ void setScale(int offsetScale);
private:
- unsigned i;
- unsigned j;
- unsigned scale;
- unsigned size;
+ int i;
+ int j;
+ int scale;
+ int size;
bool maximum;
};
diff --git a/milena/sandbox/anthony/src/main.cc b/milena/sandbox/anthony/src/main.cc
index 9cc956b..fae3c64 100644
--- a/milena/sandbox/anthony/src/main.cc
+++ b/milena/sandbox/anthony/src/main.cc
@@ -472,18 +472,11 @@ bool hasEdgeResponse(const I& dog, const P& p, const T&
center)
// Build the extrema image
template<typename I, typename C>
-void buildExtrema(C extrema,
- I original,
+void buildExtrema(C& extrema,
+ const I& original,
std::vector< std::vector<I> >& dogSpace,
std::vector<Keypoint>& keypoints)
{
- const bool black = false;
-
- if (black)
- initialize(extrema, original);
- else
- extrema = data::convert(value::rgb8(), original);
-
// Number of scales (gaussian meaning)
unsigned scales = dogSpace.at(0).size();
@@ -523,7 +516,7 @@ void buildExtrema(C extrema,
{
mln_psite(I) pOriginal(p.row() * pow(2, (j-1)),
p.col() * pow(2, (j-1)));
- extrema(pOriginal) = literal::green;
+ extrema(pOriginal) = literal::red;
keypoints.push_back(Keypoint(p.row(), p.col(), i, j, false));
}
}
@@ -543,75 +536,191 @@ void buildExtrema(C extrema,
}
}
}
-
- io::ppm::save(extrema, "output/extrema.ppm");
}
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-
+// Compute the first order matrix for interpolation
template<typename I>
-Matrix *computeFirstOrderMatrix(const std::vector< std::vector<I> >&
dogSpace,
- const Keypoint& k)
+void computeFirstOrderMatrix(const std::vector< std::vector<I> >&
dogSpace,
+ Keypoint& k,
+ Matrix& matrix)
{
- Matrix *matrix = new Matrix(3, 1);
+ matrix.initialize();
+
+ std::vector<I> current = dogSpace.at(1);
+ std::vector<I> upper = dogSpace.at(2);
+ std::vector<I> lower = dogSpace.at(0);
+
+ /* Point naming convention
+ * n1
+ * n2 c n3
+ * n4
+ */
+ point2d c(k.getI(), k.getJ());
+
+ point2d n1(k.getI(), k.getJ() - 1);
+ point2d n2(k.getI() - 1, k.getJ());
+ point2d n3(k.getI() + 1, k.getJ());
+ point2d n4(k.getI(), k.getJ() + 1);
+
+ point2d cupper(c.row() / 2, c.col() / 2);
+ point2d clower(c.row() * 2, c.col() * 2);
+
+ // Compute partial x
+ matrix.set(0, 0, (current.at(0)(n3) - current.at(0)(n2)) / 2.0);
- return matrix;
+ // Compute partial y
+ matrix.set(1, 0, (current.at(0)(n3) - current.at(0)(n2)) / 2.0);
+
+ // Compute partial scale
+ matrix.set(2, 0, (lower.at(0)(clower) - upper.at(0)(cupper)) / 2.0);
}
+// Compute the inversed second order matrix for interpolation
template<typename I>
-Matrix *computeSecondOrderMatrix(const std::vector< std::vector<I> >&
dogSpace,
- const Keypoint& k)
+void computeSecondOrderMatrix(const std::vector< std::vector<I> >&
dogSpace,
+ Keypoint& k,
+ Matrix& matrix)
{
- Matrix *matrix = new Matrix(3, 3);
+ matrix.initialize();
- return matrix;
-}
+ const static std::vector<I> current = dogSpace.at(1);
+ const static I upper = dogSpace.at(2).at(0);
+ const static I lower = dogSpace.at(0).at(0);
+ const static I main = current.at(0);
-bool isBetter(Matrix offset)
-{
- return (offset.get(0, 0) > 0.5
- || offset.get(0, 1) > 0.5
- || offset.get(0, 2) > 0.5);
-}
+ /* Point naming convention
+ * n5 n1 n6
+ * n2 c n3
+ * n7 n4 n8
+ */
+ point2d c(k.getI(), k.getJ());
-void changeKeypoint(Keypoint& k, Matrix& offset)
-{
+ point2d n1(k.getI(), k.getJ() - 1);
+ point2d n2(k.getI() - 1, k.getJ());
+ point2d n3(k.getI() + 1, k.getJ());
+ point2d n4(k.getI(), k.getJ() + 1);
+
+ point2d n5(k.getI() - 1, k.getJ() - 1);
+ point2d n6(k.getI() + 1, k.getJ() - 1);
+ point2d n7(k.getI() + 1, k.getJ() + 1);
+ point2d n8(k.getI() - 1, k.getJ() + 1);
+
+ point2d cupper(c.row() / 2, c.col() / 2);
+ point2d n1upper(n1.row() / 2, n1.col() / 2);
+ point2d n2upper(n2.row() / 2, n3.col() / 2);
+ point2d n3upper(n3.row() / 2, n3.col() / 2);
+ point2d n4upper(n4.row() / 2, n4.col() / 2);
+
+ point2d clower(c.row() * 2, c.col() * 2);
+ point2d n1lower(n1.row() * 2, n1.col() * 2);
+ point2d n2lower(n2.row() * 2, n2.col() * 2);
+ point2d n3lower(n3.row() * 2, n3.col() * 2);
+ point2d n4lower(n4.row() * 2, n4.col() * 2);
+
+ float partial_xx, partial_yy, partial_ss, partial_xy, partial_xs, partial_ys;
+
+ // Compute partial xx
+ partial_xx = main(n3) - 2 * main(c) + main(n2);
+
+ // Compute partial yy
+ partial_yy = main(n4) - 2 * main(c) + main(n1);
+
+ // Compute partial ss
+ partial_ss = lower(clower) - 2 * main(c)
+ + upper(cupper);
+
+ // Compute partial xy
+ partial_xy = (main(n8) - main(n6) - main(n7) + main(n5)) / 4.0;
+
+ // Compute partial xs
+ partial_xs = (upper(n3upper) - lower(n3lower)
+ - upper(n2upper) + lower(n2lower)) / 4.0;
+
+ // Compute partial ys
+ partial_ys = (upper(n4upper) - lower(n4lower)
+ - upper(n1upper) + lower(n1lower)) / 4.0;
+
+ matrix.set(0, 0, partial_xx);
+ matrix.set(0, 1, partial_xy);
+ matrix.set(0, 2, partial_xs);
+
+ matrix.set(1, 0, partial_xy);
+ matrix.set(1, 1, partial_yy);
+ matrix.set(1, 2, partial_ys);
+
+ matrix.set(2, 0, partial_xs);
+ matrix.set(2, 1, partial_ys);
+ matrix.set(2, 2, partial_ss);
}
// Discard low contrast keypoints thanks to taylor interpolation
// See Brown and Lowe paper (2002)
-// FIXME Move to object representation (size-templated matrix maybe ?)
-template<typename I>
+template<typename I, typename C>
void discardLowContrastKeypoints(const std::vector< std::vector<I> >&
dogSpace,
- std::vector<Keypoint>& keypoints)
+ std::vector<Keypoint>& keypoints,
+ C& extrema)
{
+ Keypoint k_old(0, 0, 0, 0, true);
+
for (unsigned i = 0; i < keypoints.size(); ++i)
{
Keypoint k = keypoints.at(i);
- Matrix *fom = computeFirstOrderMatrix(dogSpace, k);
- Matrix *som = computeSecondOrderMatrix(dogSpace, k);
- Matrix inversed(som->getHeight(), som->getWidth());
- bool inversible = som->inverse(inversed);
+ Matrix firstOrder(3, 1);
+ Matrix secondOrder(3, 3);
+ Matrix inversed(secondOrder.getHeight(), secondOrder.getWidth());
- if (inversible)
+ computeFirstOrderMatrix(dogSpace, k, firstOrder);
+ computeSecondOrderMatrix(dogSpace, k, secondOrder);
+ bool hasInversed = secondOrder.inverse(inversed);
+
+ if (hasInversed)
{
- Matrix offset = (*fom) * (*som);
-
- if (isBetter(offset))
+ Matrix x = inversed * firstOrder;
+ bool isMajorOffset = x.isMajorOffset();
+
+ if (isMajorOffset)
+ {
+ std::cout <<
"<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
<< std::endl;
+ std::cout << "First order matrix:" << std::endl;
+ firstOrder.print();
+
+ std::cout << "Second order matrix:" << std::endl;
+ secondOrder.print();
+
+ std::cout << "Offset: " << std::endl;
+ x.print();
+
+ std::cout << "k_old: " << k_old.getI() << "
" << k_old.getJ() << std::endl;
+ std::cout << "k: " << k.getI() << " "
<< k.getJ() << std::endl;
+ bool hasMoved = k.add(x, k_old);
+ std::cout << "k++: " << k.getI() << " "
<< k.getJ()
+ << "\thasMoved: " << hasMoved <<
std::endl;
+
+ point2d p(k.getI(), k.getJ());
+ std::cout << "Final point: " << extrema.domain() <<
"\t" << p << std::endl;
+
+ if (hasMoved && extrema.has(p)
+ && p.row() >= 0 && p.row() < geom::max_row(extrema)
+ && p.col() >= 0 && p.col() < geom::max_col(extrema))
+ {
+ std::cout << "VALID" << std::endl;
+ extrema(p) = literal::red;
+ k_old = keypoints.at(i);
+ keypoints.at(i--) = k;
+ }
+
+ std::cout << std::endl;
+ }
+ else
{
- changeKeypoint(k, offset);
+ point2d p(k.getI(), k.getJ());
+ extrema(p) = literal::red;
}
}
}
}
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-
// Main entry point
int main(int argc, char** argv)
{
@@ -624,18 +733,33 @@ int main(int argc, char** argv)
std::vector< std::vector<I> > dogSpace;
std::vector<Keypoint> keypoints;
I original;
- C extrema;
+ C extrema, improved;
+ bool black = true;
io::pgm::load(original, "images/lena.pgm");
+ if (black)
+ {
+ initialize(extrema, original);
+ initialize(improved, original);
+ }
+ else
+ {
+ extrema = data::convert(value::rgb8(), original);
+ improved = data::convert(value::rgb8(), original);
+ }
+
// Localization
buildScaleSpace(scaleSpace, original, octave_level, blur_level);
buildDifferenceOfGaussianSpace(scaleSpace, dogSpace);
buildExtrema(extrema, original, dogSpace, keypoints);
- //discardLowContrastKeypoints(dogSpace, keypoints);
+ discardLowContrastKeypoints(dogSpace, keypoints, improved);
// Processing
// TODO
+ 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/src/matrix.cc
index 1c5784d..ee00ffc 100644
--- a/milena/sandbox/anthony/src/matrix.cc
+++ b/milena/sandbox/anthony/src/matrix.cc
@@ -46,7 +46,6 @@ void Matrix::print()
std::cout << std::endl;
}
-
float Matrix::determinant()
{
float d1 = m.at(0).at(0) * m.at(1).at(1) * m.at(2).at(2);
@@ -99,7 +98,6 @@ bool Matrix::inverse(Matrix& inversed)
for (unsigned j = 0; j < comatrix.getHeight(); ++j)
comatrix.set(i, j, comatrix.get(i,j) / det);
- comatrix.print();
inversed = comatrix;
canInverse = true;
@@ -120,7 +118,33 @@ Matrix Matrix::operator*(Matrix& right)
result.add(i, k, m.at(i).at(j) * right.get(j, k));
return result;
-};
+}
+
+void Matrix::absolute()
+{
+ for (unsigned i = 0; i < height; ++i)
+ for (unsigned j = 0; j < width; ++j)
+ m.at(i).at(j) *= (m.at(i).at(j) >= 0) ? 1 : -1;
+}
+
+bool Matrix::isMajorOffset()
+{
+ unsigned i = 0;
+ unsigned j = 0;
+ bool isMajorOffset = false;
+
+ while (!isMajorOffset && i < height)
+ {
+ while (!isMajorOffset && j < width)
+ {
+ isMajorOffset = m.at(i).at(j) > 0.5 || - m.at(i).at(j) > 0.5;
+ ++j;
+ }
+ ++i;
+ }
+
+ return isMajorOffset;
+}
// Getters and Setters
unsigned Matrix::getHeight() { return height; }
diff --git a/milena/sandbox/anthony/src/matrix.hh b/milena/sandbox/anthony/src/matrix.hh
index b2ca124..de83912 100644
--- a/milena/sandbox/anthony/src/matrix.hh
+++ b/milena/sandbox/anthony/src/matrix.hh
@@ -13,8 +13,9 @@ class Matrix
void initialize();
void initialize(float *values);
void print();
- float determinant();
bool inverse(Matrix& inversed);
+ void absolute();
+ bool isMajorOffset();
// Operators
Matrix operator*(Matrix& right);
@@ -30,6 +31,8 @@ class Matrix
std::vector< std::vector<float> > m;
unsigned height;
unsigned width;
+
+ float determinant();
};
#endif /* ! MATRIX_HH */
--
1.7.2.5