[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libcvd-members] libcvd Makefile.in cvd/tensor_voting.h cvd_src/...
From: |
Edward Rosten |
Subject: |
[libcvd-members] libcvd Makefile.in cvd/tensor_voting.h cvd_src/... |
Date: |
Thu, 13 Dec 2007 22:36:57 +0000 |
CVSROOT: /cvsroot/libcvd
Module name: libcvd
Changes by: Edward Rosten <edrosten> 07/12/13 22:36:57
Modified files:
. : Makefile.in
Added files:
cvd : tensor_voting.h
cvd_src : tensor_voting.cc
Log message:
Dense tensor voting on gradients for detecting salient edges (for some
value of salient).
A good saliency function seems to be max eigenvalue - 2 * min
eigenvalue.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/tensor_voting.h?cvsroot=libcvd&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd_src/tensor_voting.cc?cvsroot=libcvd&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/libcvd/Makefile.in?cvsroot=libcvd&r1=1.63&r2=1.64
Patches:
Index: Makefile.in
===================================================================
RCS file: /cvsroot/libcvd/libcvd/Makefile.in,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -b -r1.63 -r1.64
--- Makefile.in 6 Dec 2007 00:00:48 -0000 1.63
+++ Makefile.in 13 Dec 2007 22:36:57 -0000 1.64
@@ -151,8 +151,7 @@
ifeq (@have_toon@,yes)
CVD_OBJS+=cvd_src/brezenham.o
\
- #cvd_src/se3.o
\
- #cvd_src/so3.o
+ cvd_src/tensor_voting.o
endif
ifeq (@have_lapack@,yes)
Index: cvd/tensor_voting.h
===================================================================
RCS file: cvd/tensor_voting.h
diff -N cvd/tensor_voting.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ cvd/tensor_voting.h 13 Dec 2007 22:36:56 -0000 1.1
@@ -0,0 +1,120 @@
+#ifndef CVD_INC_TENSOR_VOTE_H
+#define CVD_INC_TENSOR_VOTE_H
+
+#include <cvd/image.h>
+#include <TooN/TooN.h>
+#include <TooN/helpers.h>
+#include <vector>
+#include <utility>
+
+namespace CVD
+{
+
+ #ifndef DOXYGEN_IGNORE_INTERNAL
+ namespace TensorVoting
+ {
+ std::vector<std::pair<int, TooN::Matrix<2> > >
compute_a_tensor_kernel(int radius, double cutoff, double angle, double sigma,
double ratio, int row_stride);
+ unsigned int quantize_half_angle(double r, int num_divs);
+ }
+
+ #endif
+
+ /**
+ This function performs tensor voting on the gradients of an image. The
+ voting is performed densely at each pixel, and the contribution of each
+ pixel is scaled by its gradient magnitude. The kernel for voting is
+ computed as follows. Consider that there is a point at \f$(0,0)\f$,
with
+ gradient normal \f$(0,1)\f$. This will make a contribution to the point
+ \f$(x,y)\f$.
+
+ The arc-length, \f$l\f$, of the arc passing through \f$(0,0)\f$,
tangent to
+ the gradient at this point and also passing through \f$(x, y)\f$ is:
+ \f[
+ l = 2 r \theta
+ \f]
+ Where
+ \f[
+ \theta = \tan^{-1}\frac{y}{x}
+ \f]
+ and the radius of the arc, \f$r\f$ is:
+ \f[
+ r = \frac{x^2 + y^2}{2y}.
+ \f]
+
+ The scale of the contribution is:
+ \f[
+ s = e^{-\frac{l^2}{\sigma^2} - \kappa\frac{\sigma^2}{r^2}}.
+ \f]
+ Note that this is achieved by scaling \f$x\f$ and \f$y\f$ by
\f$\sigma\f$, so
+ \f$\kappa\f$ controls the kernel shape independent of the size.
+ The complete tensor contribution is therefore:
+ \f[
+ e^{-\frac{l^2}{\sigma^2} - \kappa\frac{\sigma^2}{r^2}}
+ \left[
+ \begin{array}{c}
+ \cos
2\theta\\
+ \sin
2\theta
+ \end{array}
+ \right]
+ [ \cos 2\theta\ \ \sin
2\theta]
+ \f]
+
+
+ @param image The image on which to perform tensor voting
+ @param sigma \f$ \sigma \f$
+ @param ratio \f$ \kappa \f$
+ @param cutoff When \f$s\f$ points drop below the cutoff, it is set to
zero.
+ @param num_divs The voting kernels are quantized by angle in to this
many dicisions in the half-circle.
+ @ingroup gVision
+ **/
+ template<class C> Image<TooN::Matrix<2> >
dense_tensor_vote_gradients(const SubImage<C>& image, double sigma, double
ratio, double cutoff=0.001, int num_divs = 4096)
+ {
+ using TooN::Matrix;
+ using std::pair;
+ using std::vector;
+
+ Matrix<2> zero;
+ TooN::Zero(zero);
+ Image<Matrix<2> > field(image.size(), zero);
+
+
+ //Kernel values go as exp(-x*x / sigma * sigma)
+ //So, for cutoff = exp(-x*x / sigma * sigma)
+ //ln cutoff = -x*x / sigma*sigma
+ //x = sigma * sqrt(-ln cutoff)
+ int kernel_radius = (int)ceil(sigma * sqrt(-log(cutoff)));
+
+
+ //First, build up the kernels
+ vector<vector<pair<int, Matrix<2> > > > kernels;
+ for(unsigned int i=0; i < num_divs; i++)
+ {
+ double angle = M_PI * i / num_divs;
+
kernels.push_back(TensorVoting::compute_a_tensor_kernel(kernel_radius, cutoff,
angle, sigma, ratio, field.row_stride()));
+ }
+
+
+ for(int y= kernel_radius; y < field.size().y - kernel_radius;
y++)
+ for(int x= kernel_radius; x < field.size().x -
kernel_radius; x++)
+ {
+ double gx = ((double)image[y][x+1] -
image[y][x-1])/2.;
+ double gy = ((double)image[y+1][x] -
image[y-1][x])/2.;
+
+ double scale = sqrt(gx*gx + gy*gy);
+ unsigned int direction =
TensorVoting::quantize_half_angle(M_PI/2 + atan(gy / gx), num_divs);
+
+ const vector<pair<int, Matrix<2> > >& kernel =
kernels[direction];
+
+ Matrix<2>* p = &field[y][x];
+
+ for(unsigned int i=0; i < kernel.size(); i++)
+ p[kernel[i].first] += kernel[i].second
* scale;
+ }
+
+
+ return field;
+ }
+}
+
+
+#endif
Index: cvd_src/tensor_voting.cc
===================================================================
RCS file: cvd_src/tensor_voting.cc
diff -N cvd_src/tensor_voting.cc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ cvd_src/tensor_voting.cc 13 Dec 2007 22:36:56 -0000 1.1
@@ -0,0 +1,105 @@
+#include <cvd/image.h>
+#include <TooN/TooN.h>
+#include <TooN/helpers.h>
+#include <cvd/tensor_voting.h>
+#include <utility>
+#include <vector>
+
+using namespace TooN;
+using namespace std;
+
+namespace CVD
+{
+ namespace TensorVoting
+ {
+
+ unsigned int quantize_half_angle(double r, int num_divs)
+ {
+ return ((int)floor((r/M_PI+100) * num_divs + 0.5)) %
num_divs;
+ }
+
+ Matrix<2> rot(double angle)
+ {
+ double v[]= {cos(angle), sin(angle), -sin(angle),
cos(angle)};
+ return v;
+ }
+
+ //See the tensor voting documentation for a description of the
maths
+ pair<Matrix<2>, double> tensor_kernel_element(Vector<2>& g, int
x1, int y1, double sigma, double ratio)
+ {
+ double x = x1 * g[0] + y1 * g[1];
+ double y = x1 * g[1] - y1 * g[0];
+ x /= sigma;
+ y /= sigma;
+
+ if(y == 0)
+ {
+ Matrix<2> t = g.as_col() * g.as_row();
+
+ if(x ==0)
+ return make_pair(t, 1);
+ else
+ return make_pair(t, exp(-(x * x)));
+ }
+ else
+ {
+ double k = 2 * y / (x*x + y*y);
+ double r = 1/k;
+ double theta = atan(y/x);
+ double arclen = 2 * theta * r;
+
+ double scale = exp(-(arclen * arclen + ratio *
k*k));
+ Vector<2> d = rot(2*theta) * g;
+
+ return make_pair(g.as_col() * g.as_row(),
scale);
+ }
+ }
+
+ //Borrowed from the tag library.
+ template<class A, class B> struct refpair
+ {
+ A& a;
+ B& b;
+ refpair(A& aa, B& bb)
+ :a(aa),b(bb)
+ {}
+
+ void operator=(const pair<A,B>& p)
+ {
+ a=p.first;
+ b=p.second;
+ }
+ };
+
+ template<class A, class B> refpair<A,B> rpair(A&aa, B&bb)
+ {
+ return refpair<A,B>(aa, bb);
+ }
+
+ //Compute a kernel, with small values set to zero, with pointer
offsets
+ //for the nonzero elements.
+ vector<pair<int, Matrix<2> > > compute_a_tensor_kernel(int
radius, double cutoff, double angle, double sigma, double ratio, int row_stride)
+ {
+
+ vector<pair<int, Matrix<2> > > ret;
+
+ Vector<2> g;
+ g[0] = cos(angle);
+ g[1] = sin(angle);
+
+ for(int y=-radius; y <= radius; y++)
+ for(int x=-radius; x <= radius; x++)
+ {
+ Matrix<2> tensor;
+ double scale;
+ rpair(tensor, scale) =
tensor_kernel_element(g, x, y, sigma, ratio);
+
+ if(scale >= cutoff)
+ ret.push_back(make_pair(x + y *
row_stride, scale * tensor));
+ }
+
+ return ret;
+ }
+ }
+}
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libcvd-members] libcvd Makefile.in cvd/tensor_voting.h cvd_src/...,
Edward Rosten <=