1 /*
2 * Copyright (c) 2019 Guo Yejun
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <math.h>
24 #include "libavfilter/dnn/dnn_backend_native_layer_pad.h"
25
26 #define EPSON 0.00001
27
test_with_mode_symmetric(void)28 static int test_with_mode_symmetric(void)
29 {
30 // the input data and expected data are generated with below python code.
31 /*
32 x = tf.placeholder(tf.float32, shape=[1, None, None, 3])
33 y = tf.pad(x, [[0, 0], [2, 3], [3, 2], [0, 0]], 'SYMMETRIC')
34 data = np.arange(48).reshape(1, 4, 4, 3);
35
36 sess=tf.Session()
37 sess.run(tf.global_variables_initializer())
38 output = sess.run(y, feed_dict={x: data})
39
40 print(list(data.flatten()))
41 print(list(output.flatten()))
42 print(data.shape)
43 print(output.shape)
44 */
45
46 LayerPadParams params;
47 DnnOperand operands[2];
48 int32_t input_indexes[1];
49 float input[1*4*4*3] = {
50 0, 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
51 };
52 float expected_output[1*9*9*3] = {
53 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0, 6.0, 7.0, 8.0, 3.0,
54 4.0, 5.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 10.0, 11.0, 6.0, 7.0, 8.0, 6.0, 7.0, 8.0, 3.0, 4.0, 5.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 3.0,
55 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 10.0, 11.0, 6.0, 7.0, 8.0, 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0,
56 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0, 30.0, 31.0, 32.0, 27.0, 28.0, 29.0, 24.0, 25.0, 26.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 33.0,
57 34.0, 35.0, 30.0, 31.0, 32.0, 42.0, 43.0, 44.0, 39.0, 40.0, 41.0, 36.0, 37.0, 38.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 45.0, 46.0, 47.0, 42.0, 43.0,
58 44.0, 42.0, 43.0, 44.0, 39.0, 40.0, 41.0, 36.0, 37.0, 38.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 45.0, 46.0, 47.0, 42.0, 43.0, 44.0, 30.0, 31.0, 32.0,
59 27.0, 28.0, 29.0, 24.0, 25.0, 26.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 33.0, 34.0, 35.0, 30.0, 31.0, 32.0, 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0,
60 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0
61 };
62 float *output;
63
64 params.mode = LPMP_SYMMETRIC;
65 params.paddings[0][0] = 0;
66 params.paddings[0][1] = 0;
67 params.paddings[1][0] = 2;
68 params.paddings[1][1] = 3;
69 params.paddings[2][0] = 3;
70 params.paddings[2][1] = 2;
71 params.paddings[3][0] = 0;
72 params.paddings[3][1] = 0;
73
74 operands[0].data = input;
75 operands[0].dims[0] = 1;
76 operands[0].dims[1] = 4;
77 operands[0].dims[2] = 4;
78 operands[0].dims[3] = 3;
79 operands[1].data = NULL;
80
81 input_indexes[0] = 0;
82 dnn_execute_layer_pad(operands, input_indexes, 1, ¶ms, NULL);
83
84 output = operands[1].data;
85 for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
86 if (fabs(output[i] - expected_output[i]) > EPSON) {
87 printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
88 av_freep(&output);
89 return 1;
90 }
91 }
92
93 av_freep(&output);
94 return 0;
95
96 }
97
test_with_mode_reflect(void)98 static int test_with_mode_reflect(void)
99 {
100 // the input data and expected data are generated with below python code.
101 /*
102 x = tf.placeholder(tf.float32, shape=[3, None, None, 3])
103 y = tf.pad(x, [[1, 2], [0, 0], [0, 0], [0, 0]], 'REFLECT')
104 data = np.arange(36).reshape(3, 2, 2, 3);
105
106 sess=tf.Session()
107 sess.run(tf.global_variables_initializer())
108 output = sess.run(y, feed_dict={x: data})
109
110 print(list(data.flatten()))
111 print(list(output.flatten()))
112 print(data.shape)
113 print(output.shape)
114 */
115
116 LayerPadParams params;
117 DnnOperand operands[2];
118 int32_t input_indexes[1];
119 float input[3*2*2*3] = {
120 0, 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
121 };
122 float expected_output[6*2*2*3] = {
123 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0,
124 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0,
125 35.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0
126 };
127 float *output;
128
129 params.mode = LPMP_REFLECT;
130 params.paddings[0][0] = 1;
131 params.paddings[0][1] = 2;
132 params.paddings[1][0] = 0;
133 params.paddings[1][1] = 0;
134 params.paddings[2][0] = 0;
135 params.paddings[2][1] = 0;
136 params.paddings[3][0] = 0;
137 params.paddings[3][1] = 0;
138
139 operands[0].data = input;
140 operands[0].dims[0] = 3;
141 operands[0].dims[1] = 2;
142 operands[0].dims[2] = 2;
143 operands[0].dims[3] = 3;
144 operands[1].data = NULL;
145
146 input_indexes[0] = 0;
147 dnn_execute_layer_pad(operands, input_indexes, 1, ¶ms, NULL);
148
149 output = operands[1].data;
150 for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
151 if (fabs(output[i] - expected_output[i]) > EPSON) {
152 printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
153 av_freep(&output);
154 return 1;
155 }
156 }
157
158 av_freep(&output);
159 return 0;
160
161 }
162
test_with_mode_constant(void)163 static int test_with_mode_constant(void)
164 {
165 // the input data and expected data are generated with below python code.
166 /*
167 x = tf.placeholder(tf.float32, shape=[1, None, None, 3])
168 y = tf.pad(x, [[0, 0], [1, 0], [0, 0], [1, 2]], 'CONSTANT', constant_values=728)
169 data = np.arange(12).reshape(1, 2, 2, 3);
170
171 sess=tf.Session()
172 sess.run(tf.global_variables_initializer())
173 output = sess.run(y, feed_dict={x: data})
174
175 print(list(data.flatten()))
176 print(list(output.flatten()))
177 print(data.shape)
178 print(output.shape)
179 */
180
181 LayerPadParams params;
182 DnnOperand operands[2];
183 int32_t input_indexes[1];
184 float input[1*2*2*3] = {
185 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
186 };
187 float expected_output[1*3*2*6] = {
188 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0,
189 728.0, 728.0, 0.0, 1.0, 2.0, 728.0, 728.0, 728.0, 3.0, 4.0, 5.0, 728.0, 728.0,
190 728.0, 6.0, 7.0, 8.0, 728.0, 728.0, 728.0, 9.0, 10.0, 11.0, 728.0, 728.0
191 };
192 float *output;
193
194 params.mode = LPMP_CONSTANT;
195 params.constant_values = 728;
196 params.paddings[0][0] = 0;
197 params.paddings[0][1] = 0;
198 params.paddings[1][0] = 1;
199 params.paddings[1][1] = 0;
200 params.paddings[2][0] = 0;
201 params.paddings[2][1] = 0;
202 params.paddings[3][0] = 1;
203 params.paddings[3][1] = 2;
204
205 operands[0].data = input;
206 operands[0].dims[0] = 1;
207 operands[0].dims[1] = 2;
208 operands[0].dims[2] = 2;
209 operands[0].dims[3] = 3;
210 operands[1].data = NULL;
211
212 input_indexes[0] = 0;
213 dnn_execute_layer_pad(operands, input_indexes, 1, ¶ms, NULL);
214
215 output = operands[1].data;
216 for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
217 if (fabs(output[i] - expected_output[i]) > EPSON) {
218 printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
219 av_freep(&output);
220 return 1;
221 }
222 }
223
224 av_freep(&output);
225 return 0;
226
227 }
228
main(int argc,char ** argv)229 int main(int argc, char **argv)
230 {
231 if (test_with_mode_symmetric())
232 return 1;
233
234 if (test_with_mode_reflect())
235 return 1;
236
237 if (test_with_mode_constant())
238 return 1;
239 }
240