libcvd-members
[Top][All Lists]
Advanced

[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;
+               }
+       }
+}      
+




reply via email to

[Prev in Thread] Current Thread [Next in Thread]