-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreaddatum.m
141 lines (116 loc) · 3.83 KB
/
readdatum.m
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
function [ datum ] = readdatum( in )
%READDATUM Read a Caffe's datum.
% Datum is a data structure which contains an image together with its
% meta-data and label.
% The sturcture is defined by caffe/src/caffe/proto/caffe.proto, based on
% Google's Protocol buffers.
% ------
% input: in Raw data array (uint8)
% output: datum The datum structure
% ------
% View the following pages for the details:
% https://developers.google.com/protocol-buffers/docs/encoding
% https://github.com/BVLC/caffe/blob/master/src/caffe/proto/caffe.proto
datum=[];
ptr=1;
ptr_float_data=0;
in = uint8(in);
while ptr<=numel(in)
% read key
key=in(ptr);
ptr = ptr+1;
% determine wire type, output a value
switch bitand(key,7)
%int32/bool
case 0
%read num
[value,ptr] = read128varint(in,ptr);
%bytes
case 2
%read length
[length,ptr] = read128varint(in,ptr);
%read bytes[length]
value=in(ptr:(ptr+length-1));
ptr=ptr+length;
%float
% Float and fixed32 have wire type 5, which tells it to expect 32 bits. In
% both cases the values are stored in little-endian byte order.
case 5
% TODO
% read bytes[4]
warning('Type float has not been tested yet @ %d !',ptr)
value=uint32(in(ptr:(ptr+3)));
ptr=ptr+4;
value = typecast( ...
bitor( ...
bitor( ...
value(1) , ...
bitshift(value(2),8) ...
), ...
bitor( ...
bitshift(value(3),16) , ...
bitshift(value(4),24) ...
) ...
) , ...
'single');
otherwise
error('Unknown type @ %d !',ptr)
end
% determine field
switch bitshift(key,-3)
case 1
datum.channels=value;
case 2
datum.height=value;
case 3
datum.width=value;
case 4
datum.data=value;
case 5
datum.label=value;
%repeated float_data
case 6
warning('Field float_data has not been tested yet @ %d !',ptr)
if ptr_float_data==0
datum.float_data=zeros(1,length,'single');
end
ptr_float_data=ptr_float_data+1;
datum.float_data(ptr_float_data)=value;
case 7
datum.encode=value;
otherwise
error('Unknown field!')
end
end
end
function [ value,ptr ] = read128varint( in,ptr )
%READ128VARINT Read the next base 128 varint.
% input: in Raw data array (uint8)
% ptr Previous pointer to the array in
% output: value Obtained int (uint32)
% ptr Pointer to the array in after reading
% -------------
% View the following page for the detail of encoding:
% https://developers.google.com/protocol-buffers/docs/encoding
BASE = 128;
BASEMASK = 127;
BASE_POWER=7;
shift = 0;
value = uint32(0);
while(ptr<=numel(in))
% read the next byte
ii=uint32(in(ptr));
ptr=ptr+1;
% if the most significant digit(msd)=0, return the number
if ii<BASE
value=bitor(bitshift(ii,shift),value);
return
% if msd=1, continue reading
else
value=bitor(bitshift(bitand(ii,BASEMASK),shift),value);
shift=shift+BASE_POWER;
end
end
% This function should be ended by 'return'
error('Unexpected end of array!')
end