forked from edrosten/libcvd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tensor_voting.cc
111 lines (92 loc) · 2.24 KB
/
tensor_voting.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#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
{
Matrix<2> rot(double angle)
{
Matrix<2> v;
v[0] = makeVector(cos(angle), sin(angle));
v[1] = makeVector(-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(d.as_col() * d.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);
}
TV_coord make(int x, int y, int s)
{
TV_coord t;
t.x = x;
t.y = y;
t.o = (ptrdiff_t)s * y + x;
return t;
}
//Compute a kernel, with small values set to zero, with pointer offsets
//for the nonzero elements.
vector<pair<TV_coord, Matrix<2> > > compute_a_tensor_kernel(int radius, double cutoff, double angle, double sigma, double ratio, int row_stride)
{
vector<pair<TV_coord, 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(make(x,y,row_stride), scale * tensor));
}
return ret;
}
}
}