forked from willard-yuan/cnn-cbir-benchmark
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrmac.py
156 lines (136 loc) · 5.77 KB
/
rmac.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import sys
import numpy as np
import caffe
import cv2
import os
class ImageHelper:
def __init__(self, S, L, means):
self.S = S
self.L = L
self.means = means
def prepare_image_and_grid_regions_for_network(self, fname, roi=None):
# Extract image, resize at desired size, and extract roi region if
# available. Then compute the rmac grid in the net format: ID X Y W H
I, im_resized = self.load_and_prepare_image(fname, roi)
if self.L == 0:
# Encode query in mac format instead of rmac, so only one region
# Regions are in ID X Y W H format
R = np.zeros((1, 5), dtype=np.float32)
R[0, 3] = im_resized.shape[1] - 1
R[0, 4] = im_resized.shape[0] - 1
else:
# Get the region coordinates and feed them to the network.
all_regions = []
all_regions.append(self.get_rmac_region_coordinates(im_resized.shape[0], im_resized.shape[1], self.L))
#print self.L
#print all_regions
R = self.pack_regions_for_network(all_regions)
#print R.shape
return I, R
def get_rmac_features(self, I, R, net):
net.blobs['data'].reshape(I.shape[0], 3, int(I.shape[2]), int(I.shape[3]))
net.blobs['data'].data[:] = I
net.forward()
return net.blobs['pool5'].data
def load_and_prepare_image(self, fname, roi=None):
# Read image, get aspect ratio, and resize such as the largest side equals S
im = cv2.imread(fname)
im_size_hw = np.array(im.shape[0:2])
ratio = float(self.S)/np.max(im_size_hw)
new_size = tuple(np.round(im_size_hw * ratio).astype(np.int32))
im_resized = cv2.resize(im, (new_size[1], new_size[0]))
# If there is a roi, adapt the roi to the new size and crop. Do not rescale
# the image once again
if roi is not None:
roi = np.round(roi * ratio).astype(np.int32)
im_resized = im_resized[roi[1]:roi[3], roi[0]:roi[2], :]
# Transpose for network and subtract mean
I = im_resized.transpose(2, 0, 1) - self.means
return I, im_resized
def pack_regions_for_network(self, all_regions):
n_regs = np.sum([len(e) for e in all_regions])
print all_regions[0]
R = np.zeros((n_regs, 5), dtype=np.float32)
cnt = 0
# There should be a check of overflow...
for i, r in enumerate(all_regions):
try:
R[cnt:cnt + r.shape[0], 0] = i
R[cnt:cnt + r.shape[0], 1:] = r
cnt += r.shape[0]
except:
continue
assert cnt == n_regs
R = R[:n_regs]
# regs where in xywh format. R is in xyxy format, where the last coordinate is included. Therefore...
R[:n_regs, 3] = R[:n_regs, 1] + R[:n_regs, 3] - 1
R[:n_regs, 4] = R[:n_regs, 2] + R[:n_regs, 4] - 1
print R[3]
return R
def get_rmac_region_coordinates(self, H, W, L):
# Almost verbatim from Tolias et al Matlab implementation.
# Could be heavily pythonized, but really not worth it...
# Desired overlap of neighboring regions
ovr = 0.4
# Possible regions for the long dimension
steps = np.array((2, 3, 4, 5, 6, 7), dtype=np.float32)
w = np.minimum(H, W)
b = (np.maximum(H, W) - w) / (steps - 1)
# steps(idx) regions for long dimension. The +1 comes from Matlab
# 1-indexing...
idx = np.argmin(np.abs(((w**2 - w * b) / w**2) - ovr)) + 1
# Region overplus per dimension
Wd = 0
Hd = 0
if H < W:
Wd = idx
elif H > W:
Hd = idx
regions_xywh = []
for l in range(1, L+1):
wl = np.floor(2 * w / (l + 1))
wl2 = np.floor(wl / 2 - 1)
# Center coordinates
if l + Wd - 1 > 0:
b = (W - wl) / (l + Wd - 1)
else:
b = 0
cenW = np.floor(wl2 + b * np.arange(l - 1 + Wd + 1)) - wl2
# Center coordinates
if l + Hd - 1 > 0:
b = (H - wl) / (l + Hd - 1)
else:
b = 0
cenH = np.floor(wl2 + b * np.arange(l - 1 + Hd + 1)) - wl2
for i_ in cenH:
for j_ in cenW:
regions_xywh.append([j_, i_, wl, wl])
print "regions number: %d" % len(regions_xywh)
# Round the regions. Careful with the borders!
for i in range(len(regions_xywh)):
for j in range(4):
regions_xywh[i][j] = int(round(regions_xywh[i][j]))
if regions_xywh[i][0] + regions_xywh[i][2] > W:
regions_xywh[i][0] -= ((regions_xywh[i][0] + regions_xywh[i][2]) - W)
if regions_xywh[i][1] + regions_xywh[i][3] > H:
regions_xywh[i][1] -= ((regions_xywh[i][1] + regions_xywh[i][3]) - H)
return np.array(regions_xywh).astype(np.float32)
if __name__ == '__main__':
img_path = 'all_souls_000000.jpg'
S = 800
multires = True
Ss = [S, ] if not multires else [S - 250, S, S + 250]
L = 3
means = np.array([103.93900299, 116.77899933, 123.68000031], dtype=np.float32)[None, :, None, None]
caffe.set_device(4)
caffe.set_mode_gpu()
proto = '/home/yuanyong/models/caffe.proto'
model = '/home/yuanyong/models/vgg.model'
net = caffe.Net(proto, model, caffe.TEST)
image_helper = ImageHelper(S, L, means)
for S in Ss:
# Load image, process image, get image regions, feed into the network, get descriptor, and store
image_helper.S = S
I, R = image_helper.prepare_image_and_grid_regions_for_network(img_path, roi=None)
test = image_helper.get_rmac_features(I, R, net)
#print test.shape