-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathdescriptors.py
106 lines (80 loc) · 3.57 KB
/
descriptors.py
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
import numpy as np
import numpy.linalg as LA
from gaussian_filter import gaussian_filter
from orientation import quantize_orientation, cart_to_polar_grad
def get_patch_grads(p):
r1 = np.zeros_like(p)
r1[-1] = p[-1]
r1[:-1] = p[1:]
r2 = np.zeros_like(p)
r2[0] = p[0]
r2[1:] = p[:-1]
dy = r1-r2
r1[:,-1] = p[:,-1]
r1[:,:-1] = p[:,1:]
r2[:,0] = p[:,0]
r2[:,1:] = p[:,:-1]
dx = r1-r2
return dx, dy
def get_histogram_for_subregion(m, theta, num_bin, reference_angle, bin_width, subregion_w):
hist = np.zeros(num_bin, dtype=np.float32)
c = subregion_w/2 - .5
for i, (mag, angle) in enumerate(zip(m, theta)):
angle = (angle-reference_angle) % 360
binno = quantize_orientation(angle, num_bin)
vote = mag
# binno*bin_width is the start angle of the histogram bin
# binno*bin_width+bin_width/2 is the center of the histogram bin
# angle - " is the distance from the angle to the center of the bin
hist_interp_weight = 1 - abs(angle - (binno*bin_width + bin_width/2))/(bin_width/2)
vote *= max(hist_interp_weight, 1e-6)
gy, gx = np.unravel_index(i, (subregion_w, subregion_w))
x_interp_weight = max(1 - abs(gx - c)/c, 1e-6)
y_interp_weight = max(1 - abs(gy - c)/c, 1e-6)
vote *= x_interp_weight * y_interp_weight
hist[binno] += vote
return hist
def get_local_descriptors(kps, octave, w=16, num_subregion=4, num_bin=8):
descs = []
bin_width = 360//num_bin
for kp in kps:
cx, cy, s = int(kp[0]), int(kp[1]), int(kp[2])
s = np.clip(s, 0, octave.shape[2]-1)
kernel = gaussian_filter(w/6) # gaussian_filter multiplies sigma by 3
L = octave[...,s]
t, l = max(0, cy-w//2), max(0, cx-w//2)
b, r = min(L.shape[0], cy+w//2+1), min(L.shape[1], cx+w//2+1)
patch = L[t:b, l:r]
dx, dy = get_patch_grads(patch)
if dx.shape[0] < w+1:
if t == 0: kernel = kernel[kernel.shape[0]-dx.shape[0]:]
else: kernel = kernel[:dx.shape[0]]
if dx.shape[1] < w+1:
if l == 0: kernel = kernel[kernel.shape[1]-dx.shape[1]:]
else: kernel = kernel[:dx.shape[1]]
if dy.shape[0] < w+1:
if t == 0: kernel = kernel[kernel.shape[0]-dy.shape[0]:]
else: kernel = kernel[:dy.shape[0]]
if dy.shape[1] < w+1:
if l == 0: kernel = kernel[kernel.shape[1]-dy.shape[1]:]
else: kernel = kernel[:dy.shape[1]]
m, theta = cart_to_polar_grad(dx, dy)
dx, dy = dx*kernel, dy*kernel
subregion_w = w//num_subregion
featvec = np.zeros(num_bin * num_subregion**2, dtype=np.float32)
for i in range(0, subregion_w):
for j in range(0, subregion_w):
t, l = i*subregion_w, j*subregion_w
b, r = min(L.shape[0], (i+1)*subregion_w), min(L.shape[1], (j+1)*subregion_w)
hist = get_histogram_for_subregion(m[t:b, l:r].ravel(),
theta[t:b, l:r].ravel(),
num_bin,
kp[3],
bin_width,
subregion_w)
featvec[i*subregion_w*num_bin + j*num_bin:i*subregion_w*num_bin + (j+1)*num_bin] = hist.flatten()
featvec /= max(1e-6, LA.norm(featvec))
featvec[featvec>0.2] = 0.2
featvec /= max(1e-6, LA.norm(featvec))
descs.append(featvec)
return np.array(descs)