]> git.sesse.net Git - ffmpeg/blob - tests/dnn/dnn-layer-pad-test.c
avfilter/avfilter: Remove deprecated avfilter_link_set_closed()
[ffmpeg] / tests / dnn / dnn-layer-pad-test.c
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
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     ff_dnn_execute_layer_pad(operands, input_indexes, 1, &params, 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
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     ff_dnn_execute_layer_pad(operands, input_indexes, 1, &params, 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
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     ff_dnn_execute_layer_pad(operands, input_indexes, 1, &params, 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
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 }