History

tests/dnn: Make DNN tests regular libavfilter tests

They test libavfilter internal API, so they should be libavfilter test programs (which implies: linked statically to libavfilter to access internal APIs and linked normally (statically or dynamically depending upon the build configuration) against all the other libs). Right now, they are always linked statically against all libs, which is a significant size waste compared to shared libs as all of libavcodec has been pulled in despite not being really used. This also leads to linking failures on systems for which av_export_avutil is intended: libavcodec does not expect to be linked statically against the library providing avpriv_(cga|vga16)_font in this case. This is fixed by this commit.

Andreas Rheinhardt committed 4 years ago

Commit c26730e1 parent 69a45b814 files · +31 −45Browse files

Showing the changes to libavfilter (10 of 14 files). Show all

Unified · Split

10 files
  1. libavfilter/Makefile +3 −0
  2. libavfilter/tests/.gitignore +8 −0
  3. libavfilter/tests/dnn-layer-avgpool.c +197 −0
  4. libavfilter/tests/dnn-layer-conv2d.c +248 −0
  5. libavfilter/tests/dnn-layer-dense.c +131 −0
  6. libavfilter/tests/dnn-layer-depth2space.c +102 −0
  7. libavfilter/tests/dnn-layer-mathbinary.c +214 −0
  8. libavfilter/tests/dnn-layer-mathunary.c +148 −0
  9. libavfilter/tests/dnn-layer-maximum.c +71 −0
  10. libavfilter/tests/dnn-layer-pad.c +239 −0
libavfilter/Makefile+3−0
@@ -590,6 +590,9 @@ SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_filter.h · 589 unmodified lines
590590
591591 TOOLS = graph2dot
592592 TESTPROGS = drawutils filtfmts formats integral
593+TESTPROGS-$(CONFIG_DNN) += dnn-layer-avgpool dnn-layer-conv2d dnn-layer-dense \
594+ dnn-layer-depth2space dnn-layer-mathbinary \
595+ dnn-layer-mathunary dnn-layer-maximum dnn-layer-pad \
593596
594597 TOOLS-$(CONFIG_LIBZMQ) += zmqsend
595598
libavfilter/tests/.gitignore+8−0
@@ -1,3 +1,11 @@
1+/dnn-layer-conv2d
2+/dnn-layer-depth2space
3+/dnn-layer-maximum
4+/dnn-layer-pad
5+/dnn-layer-mathbinary
6+/dnn-layer-mathunary
7+/dnn-layer-avgpool
8+/dnn-layer-dense
19 /drawutils
210 /filtfmts
311 /formats
libavfilter/tests/dnn-layer-avgpool.c+197−0
@@ -0,0 +1,197 @@
1+/*
2+ * Copyright (c) 2020
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 "libavfilter/dnn/dnn_backend_native_layer_avgpool.h"
23+
24+#define EPSON 0.00001
25+
26+static int test_with_same(void)
27+{
28+ // the input data and expected data are generated with below python code.
29+ /*
30+ import tensorflow as tf
31+ import numpy as np
32+
33+ x = tf.placeholder(tf.float32, shape=[1, None, None, 3])
34+ y = tf.layers.average_pooling2d(x, pool_size=[2,2], strides=[1,1], padding='VALID')
35+ data = np.random.rand(1, 5, 6, 3);
36+
37+ sess=tf.Session()
38+ sess.run(tf.global_variables_initializer())
39+
40+ output = sess.run(y, feed_dict={x: data})
41+
42+ print("input:")
43+ print(data.shape)
44+ print(list(data.flatten()))
45+
46+ print("output:")
47+ print(output.shape)
48+ print(list(output.flatten()))
49+ */
50+
51+ AvgPoolParams params;
52+ DnnOperand operands[2];
53+ int32_t input_indexes[1];
54+ float input[1*5*6*3] = {
55+ 0.7461309859908424, 0.7567538372797069, 0.07662743569678687, 0.8882112610336333, 0.9720443314026668, 0.3337200343220823, 0.4421032129780248,
56+ 0.14940809044964876, 0.6773177061961277, 0.9778844630669781, 0.6522650522626998, 0.0317651530878591, 0.31259897552911364, 0.6235936821891896,
57+ 0.40016094349542775, 0.4599222930032276, 0.7893807222960093, 0.8475986363538283, 0.5058802717647394, 0.7827005363222633, 0.3032188123727916,
58+ 0.8983728631302361, 0.20622408444965523, 0.22966072303869878, 0.09535751273161308, 0.8760709100995375, 0.9982324154558745, 0.7904595468621013,
59+ 0.13883671508879347, 0.9332751439533138, 0.0010861680752152214, 0.3607210449251048, 0.6600652759586171, 0.7629572058138805, 0.29441975810476106,
60+ 0.2683471432889405, 0.22574580829831536, 0.8893251976212904, 0.3907737043801005, 0.6421829842863968, 0.6670373870457297, 0.9383850793160277,
61+ 0.4120458907436003, 0.3589847212711481, 0.48047736550128983, 0.6428192648418949, 0.0313661686292348, 0.429357100401472, 0.5123413386514056,
62+ 0.8492446404097114, 0.9045286128486804, 0.8123708563814285, 0.3943245008451698, 0.9576713003177785, 0.5985610965938726, 0.9350833279543561,
63+ 0.8010079897491659, 0.45882114217642866, 0.35275037908941487, 0.4555844661432271, 0.12352455940255314, 0.37801756635035544, 0.2824056214573083,
64+ 0.6229462823245029, 0.7235305681391472, 0.5408259266122064, 0.12142224381781208, 0.34431198802873686, 0.7112823816321276, 0.6307144385115417,
65+ 0.8136734589018082, 0.842095618140585, 0.8602767724004784, 0.6649236853766185, 0.5184782829419623, 0.9119607270982825, 0.3084111974561645,
66+ 0.39460705638161364, 0.17710447526170836, 0.1715485945814199, 0.17277563576521882, 0.40188232428735704, 0.22847985411491878, 0.4135361701550696,
67+ 0.24621846601980057, 0.6576588108454774, 0.6063336087333997, 0.6452342242996931, 0.7071689702737508, 0.1973416063225648
68+ };
69+ float expected_output[] = {
70+ 0.75964886, 0.6794307, 0.23580676, 0.5810112, 0.5509369, 0.55973274, 0.5764512, 0.45414522, 0.6601476, 0.52050734, 0.44385415,
71+ 0.50631666, 0.38414115, 0.5170288, 0.544043, 0.61143976, 0.5419003, 0.5579729, 0.5680455, 0.6363218, 0.4655096, 0.51198983,
72+ 0.5270792, 0.66168886, 0.48517057, 0.3513146, 0.7103355, 0.48667657, 0.34504217, 0.7318065, 0.5221889, 0.4746775, 0.69765306,
73+ 0.78766406, 0.34437215, 0.6130092, 0.48132777, 0.7110491, 0.6464378, 0.40914366, 0.4391975, 0.5392131, 0.45033398, 0.37297475,
74+ 0.43326652, 0.4748823, 0.48711336, 0.64649844, 0.51921225, 0.60038865, 0.8538945, 0.7215426, 0.60399896, 0.89988345, 0.707405,
75+ 0.5652921, 0.54241943, 0.41785273, 0.30268195, 0.3263432, 0.3313644, 0.37539417, 0.35238582, 0.34811732, 0.48849532, 0.56799453,
76+ 0.41089734, 0.63070333, 0.5892633, 0.6379743, 0.7604212, 0.5197186, 0.88611877, 0.48666745, 0.45654267, 0.5445326, 0.2399799,
77+ 0.28369135, 0.28949338, 0.20001422, 0.2931559, 0.3240504, 0.44306934, 0.5099349, 0.44572634, 0.68241394, 0.40183762, 0.6452342,
78+ 0.707169, 0.1973416
79+ };
80+ float *output;
81+
82+ params.strides = 1;
83+ params.kernel_size = 2;
84+ params.padding_method = SAME;
85+
86+ operands[0].data = input;
87+ operands[0].dims[0] = 1;
88+ operands[0].dims[1] = 5;
89+ operands[0].dims[2] = 6;
90+ operands[0].dims[3] = 3;
91+ operands[1].data = NULL;
92+
93+ input_indexes[0] = 0;
94+ ff_dnn_execute_layer_avg_pool(operands, input_indexes, 1, &params, NULL);
95+
96+ output = operands[1].data;
97+ for (int i = 0; i < sizeof(expected_output) / sizeof(float); ++i) {
98+ if (fabs(output[i] - expected_output[i]) > EPSON) {
99+ printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
100+ av_freep(&output);
101+ return 1;
102+ }
103+ }
104+
105+ av_freep(&output);
106+ return 0;
107+}
108+
109+static int test_with_valid(void)
110+{
111+ // the input data and expected data are generated with below python code.
112+ /*
113+ import tensorflow as tf
114+ import numpy as np
115+
116+ x = tf.placeholder(tf.float32, shape=[1, None, None, 3])
117+ y = tf.layers.average_pooling2d(x, pool_size=[2,2], strides=[1,1], padding='VALID')
118+ data = np.random.rand(1, 5, 6, 3);
119+
120+ sess=tf.Session()
121+ sess.run(tf.global_variables_initializer())
122+
123+ output = sess.run(y, feed_dict={x: data})
124+
125+ print("input:")
126+ print(data.shape)
127+ print(list(data.flatten()))
128+
129+ print("output:")
130+ print(output.shape)
131+ print(list(output.flatten()))
132+ */
133+
134+ AvgPoolParams params;
135+ DnnOperand operands[2];
136+ int32_t input_indexes[1];
137+ float input[1*5*6*3] = {
138+ 0.5046741692941682, 0.9273653202485155, 0.8193878359859937, 0.1904059431360905, 0.8664919633253656, 0.7484625128286059, 0.984534184632278,
139+ 0.31900804890072254, 0.3259426099940872, 0.05388974903570376, 0.7356610151331133, 0.46710858713311965, 0.718553768817036, 0.062478421853278676,
140+ 0.7813224786584609, 0.4826837517658389, 0.9748095400220147, 0.8078547703898341, 0.11976750668368585, 0.8713586777195065, 0.41447321551284355,
141+ 0.9818788239089807, 0.4335715767584073, 0.4059793452147419, 0.3677205907204525, 0.47919995923571, 0.8341395256258882, 0.7059726374074609,
142+ 0.5478504551919791, 0.8622900484790175, 0.8343709722511167, 0.05089827275068537, 0.6465283980840416, 0.544539116066677, 0.39812057257884337,
143+ 0.9578115576866337, 0.25012888117580145, 0.579333516024662, 0.5556732133051457, 0.6119862111181243, 0.0018736758772316398, 0.9795490254040474,
144+ 0.4488085008883018, 0.28947489777011737, 0.4834108668633247, 0.9280490084385024, 0.9895821458049648, 0.31777618554697606, 0.42679693258977847,
145+ 0.74447844466923, 0.9752225305081498, 0.17564130841849335, 0.22382692067314292, 0.009602884447469373, 0.5144884415025782, 0.031622570708844555,
146+ 0.8277532752502512, 0.4111593210409763, 0.5272084646575664, 0.28856508082905297, 0.11317726946036655, 0.7203328275540273, 0.8310055019972384,
147+ 0.8535951508685228, 0.40230347305233227, 0.2819703265132867, 0.6243143957791139, 0.7512463693822311, 0.7523056340495644, 0.8838077258040928,
148+ 0.5472240664033092, 0.2550538284454935, 0.5560317774456567, 0.8966847087518931, 0.6728358284165321, 0.30361297147530875, 0.464343925441822,
149+ 0.34507695659461224, 0.6333175615390685, 0.26661369038523497, 0.9926748632253231, 0.9994267301382666, 0.8684917986974414, 0.3598754806113009,
150+ 0.49550268625464666, 0.03652458679973214, 0.13469081713137177, 0.4579424049273835, 0.48641107969110353, 0.9670250266945365
151+ };
152+ float expected_output[1*4*5*3] = {
153+ 0.44918162, 0.7746969, 0.5970757, 0.63113487, 0.5245679, 0.578631, 0.52802926, 0.52042985, 0.6223702, 0.57819676, 0.34922206,
154+ 0.6893124, 0.64503694, 0.37157673, 0.7983793, 0.49094033, 0.47153437, 0.5889187, 0.6025985, 0.30103004, 0.6757697, 0.6126377,
155+ 0.5765268, 0.62440413, 0.7237974, 0.5832023, 0.7004543, 0.49533707, 0.35433105, 0.6472913, 0.44694072, 0.28500956, 0.6628852,
156+ 0.39628282, 0.38472247, 0.6456326, 0.58590746, 0.60042334, 0.47854072, 0.7081889, 0.7219026, 0.5818187, 0.5276401, 0.56669396,
157+ 0.49804622, 0.4463231, 0.4799649, 0.5335578, 0.36531678, 0.4946247, 0.6143306, 0.6498792, 0.5644355, 0.6163815, 0.7432098,
158+ 0.5146416, 0.38221055, 0.6153918, 0.45535153, 0.5272688
159+ };
160+ float *output;
161+
162+ params.strides = 1;
163+ params.kernel_size = 2;
164+ params.padding_method = VALID;
165+
166+ operands[0].data = input;
167+ operands[0].dims[0] = 1;
168+ operands[0].dims[1] = 5;
169+ operands[0].dims[2] = 6;
170+ operands[0].dims[3] = 3;
171+ operands[1].data = NULL;
172+
173+ input_indexes[0] = 0;
174+ ff_dnn_execute_layer_avg_pool(operands, input_indexes, 1, &params, NULL);
175+
176+ output = operands[1].data;
177+ for (int i = 0; i < sizeof(expected_output) / sizeof(float); ++i) {
178+ if (fabs(output[i] - expected_output[i]) > EPSON) {
179+ printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
180+ av_freep(&output);
181+ return 1;
182+ }
183+ }
184+
185+ av_freep(&output);
186+ return 0;
187+}
188+
189+int main(int argc, char **argv)
190+{
191+ if (test_with_same())
192+ return 1;
193+ if (test_with_valid())
194+ return 1;
195+
196+ return 0;
197+}
libavfilter/tests/dnn-layer-conv2d.c+248−0
@@ -0,0 +1,248 @@
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_conv2d.h"
25+
26+#define EPSON 0.00001
27+
28+static int test_with_same_dilate(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.layers.conv2d(x, 2, 3, activation=tf.nn.tanh, padding='same', dilation_rate=(2, 2), bias_initializer=tf.keras.initializers.he_normal())
34+ data = np.random.rand(1, 5, 6, 3);
35+
36+ sess=tf.Session()
37+ sess.run(tf.global_variables_initializer())
38+
39+ weights = dict([(var.name, sess.run(var)) for var in tf.trainable_variables()])
40+ kernel = weights['conv2d/kernel:0']
41+ kernel = np.transpose(kernel, [3, 0, 1, 2])
42+ print("kernel:")
43+ print(kernel.shape)
44+ print(list(kernel.flatten()))
45+
46+ bias = weights['conv2d/bias:0']
47+ print("bias:")
48+ print(bias.shape)
49+ print(list(bias.flatten()))
50+
51+ output = sess.run(y, feed_dict={x: data})
52+
53+ print("input:")
54+ print(data.shape)
55+ print(list(data.flatten()))
56+
57+ print("output:")
58+ print(output.shape)
59+ print(list(output.flatten()))
60+ */
61+
62+ ConvolutionalParams params;
63+ DnnOperand operands[2];
64+ int32_t input_indexes[1];
65+ float input[1*5*6*3] = {
66+ 0.7012556460308194, 0.4233847954643357, 0.19515900664313612, 0.16343083004926495, 0.5758261611052848, 0.9510767434014871, 0.11014085055947687,
67+ 0.906327053637727, 0.8136794715542507, 0.45371764543639526, 0.5768443343523952, 0.19543668786046986, 0.15648326047898609, 0.2099500241141279,
68+ 0.17658777090552413, 0.059335724777169196, 0.1729991838469117, 0.8150514704819208, 0.4435535466703049, 0.3752188477566878, 0.749936650421431,
69+ 0.6823494635284907, 0.10776389679424747, 0.34247481674596836, 0.5147867256244629, 0.9063709728129032, 0.12423605800856818, 0.6064872945412728,
70+ 0.5891681538551459, 0.9865836236466314, 0.9002163879294677, 0.003968273184274618, 0.8628374809643967, 0.1327176268279583, 0.8449799925703798,
71+ 0.1937671869354366, 0.41524410152707425, 0.02038786604756837, 0.49792466069597496, 0.8881874553848784, 0.9683921035597336, 0.4122972568010813,
72+ 0.843553550993252, 0.9588482762501964, 0.5190350762645546, 0.4283584264145317, 0.09781496073714646, 0.9501058833776156, 0.8665541760152776,
73+ 0.31669272550095806, 0.07133074675453632, 0.606438007334886, 0.7007157020538224, 0.4827996264130444, 0.5167615606392761, 0.6385043039312651,
74+ 0.23069664707810555, 0.058233497329354456, 0.06323892961591071, 0.24816458893245974, 0.8646369065257812, 0.24742185893094837, 0.09991225948167437,
75+ 0.625700606979606, 0.7678541502111257, 0.6215834594679912, 0.5623003956582483, 0.07389123942681242, 0.7659100715711249, 0.486061471642225,
76+ 0.9947455699829012, 0.9094911797643259, 0.7644355876253265, 0.05384315321492239, 0.13565394382783613, 0.9810628204953316, 0.007386389078887889,
77+ 0.226182754156241, 0.2609021390764772, 0.24182802076928933, 0.13264782451941648, 0.2035816485767682, 0.005504188177612557, 0.7014619934040155,
78+ 0.956215988391991, 0.5670398541013633, 0.9809764721750784, 0.6886338100487461, 0.5758152317218274, 0.7137823176776179
79+ };
80+ float expected_output[1*5*6*2] = {
81+ -0.9480655, -0.7169147, -0.9404794, -0.5567385, -0.8991124, -0.8306558, -0.94487447, -0.8932543, -0.88238764, -0.7301602,
82+ -0.8974813, -0.7026703, -0.8858988, -0.53203243, -0.92881465, -0.5648504, -0.8871471, -0.7000097, -0.91754407, -0.79684794,
83+ -0.760465, -0.117928326, -0.88302773, -0.8975289, -0.70615053, 0.19231977, -0.8318776, -0.386184, -0.80698484, -0.8556624,
84+ -0.7336671, -0.6168619, -0.7658234, -0.63449603, -0.73314047, -0.87502456, -0.58158904, -0.4184259, -0.52618927, -0.13613208,
85+ -0.5093187, -0.21027721, -0.39455596, -0.44507834, -0.22269244, -0.73400885, -0.77655095, -0.74408925, -0.57313335, -0.15333457,
86+ -0.74620694, -0.34858236, -0.42586932, -0.5240488, 0.1634339, -0.2447881, -0.57927346, -0.62732303, -0.82287043, -0.8474058
87+ };
88+ float *output;
89+ float kernel[2*3*3*3] = {
90+ 0.26025516, 0.16536498, -0.24351254, 0.33892477, -0.34005195, 0.35202783, 0.34056443, 0.01422739, 0.13799345, 0.29489166,
91+ 0.2781723, 0.178585, 0.22122234, 0.044115514, 0.13134438, 0.31705368, 0.22527462, -0.021323413, 0.115134746, -0.18216397,
92+ -0.21197563, -0.027848959, -0.01704529, -0.12401503, -0.23415318, -0.12661739, -0.35338148, 0.20049328, -0.076153606,
93+ -0.23642601, -0.3125769, -0.025851756, -0.30006272, 0.050762743, 0.32003498, 0.3052225, -0.0017385483, 0.25337684, -0.25664508,
94+ 0.27846587, -0.3112659, 0.2066065, 0.31499845, 0.113178134, 0.09449363, -0.11828774, -0.12671001, -0.36259216, 0.2710235,
95+ -0.19676702, 0.023612618, -0.2596915, -0.34949252, -0.108270735
96+ };
97+ float bias[2] = { -1.6574852, -0.72915393 };
98+
99+ NativeContext ctx;
100+ ctx.class = NULL;
101+ ctx.options.conv2d_threads = 1;
102+
103+ params.activation = TANH;
104+ params.has_bias = 1;
105+ params.biases = bias;
106+ params.dilation = 2;
107+ params.input_num = 3;
108+ params.kernel = kernel;
109+ params.kernel_size = 3;
110+ params.output_num = 2;
111+ params.padding_method = SAME;
112+
113+ operands[0].data = input;
114+ operands[0].dims[0] = 1;
115+ operands[0].dims[1] = 5;
116+ operands[0].dims[2] = 6;
117+ operands[0].dims[3] = 3;
118+ operands[1].data = NULL;
119+
120+ input_indexes[0] = 0;
121+ ff_dnn_execute_layer_conv2d(operands, input_indexes, 1, &params, &ctx);
122+
123+ output = operands[1].data;
124+ for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
125+ if (fabs(output[i] - expected_output[i]) > EPSON) {
126+ printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
127+ av_freep(&output);
128+ return 1;
129+ }
130+ }
131+
132+ av_freep(&output);
133+ return 0;
134+}
135+
136+static int test_with_valid(void)
137+{
138+ // the input data and expected data are generated with below python code.
139+ /*
140+ x = tf.placeholder(tf.float32, shape=[1, None, None, 3])
141+ y = tf.layers.conv2d(x, 2, 3, activation=tf.nn.tanh, padding='valid', bias_initializer=tf.keras.initializers.he_normal())
142+ data = np.random.rand(1, 5, 6, 3);
143+
144+ sess=tf.Session()
145+ sess.run(tf.global_variables_initializer())
146+
147+ weights = dict([(var.name, sess.run(var)) for var in tf.trainable_variables()])
148+ kernel = weights['conv2d/kernel:0']
149+ kernel = np.transpose(kernel, [3, 0, 1, 2])
150+ print("kernel:")
151+ print(kernel.shape)
152+ print(list(kernel.flatten()))
153+
154+ bias = weights['conv2d/bias:0']
155+ print("bias:")
156+ print(bias.shape)
157+ print(list(bias.flatten()))
158+
159+ output = sess.run(y, feed_dict={x: data})
160+
161+ print("input:")
162+ print(data.shape)
163+ print(list(data.flatten()))
164+
165+ print("output:")
166+ print(output.shape)
167+ print(list(output.flatten()))
168+ */
169+
170+ ConvolutionalParams params;
171+ DnnOperand operands[2];
172+ int32_t input_indexes[1];
173+ float input[1*5*6*3] = {
174+ 0.26126657468269665, 0.42762216215337556, 0.7466274030131497, 0.802550266787863, 0.3709323443076644, 0.5919817068197668, 0.49274512279324967,
175+ 0.7170132295090351, 0.0911793215410649, 0.5134213878288361, 0.670132600785118, 0.49417034512633484, 0.03887389460089885, 0.436785102836845,
176+ 0.1490231658611978, 0.6413606121498127, 0.8595987991375995, 0.9132593077586231, 0.7075959004873255, 0.17754995944845464, 0.5212507214937141,
177+ 0.35379732738215475, 0.25205107358505296, 0.3928792840544273, 0.09485294189485782, 0.8685115437448666, 0.6489046799288605, 0.509253797582924,
178+ 0.8993255536791972, 0.18740056466602373, 0.34237617336313986, 0.3871438962989183, 0.1488532571774911, 0.5187002331293636, 0.8137098818752955,
179+ 0.521761863717401, 0.4622312310118274, 0.29038411334638825, 0.16194915718170566, 0.5175999923925211, 0.8852230040101133, 0.0218263385047206,
180+ 0.08482355352852367, 0.3463638568376264, 0.28627127120619733, 0.9553293378948409, 0.4803391055970835, 0.841635695030805, 0.3556828280031952,
181+ 0.06778527221541808, 0.28193560357091596, 0.8399957619031576, 0.03305536359456385, 0.6625039162109645, 0.9300552020023897, 0.8551529138204146,
182+ 0.6133216915522418, 0.222427800857393, 0.1315422686800336, 0.6189144989185527, 0.5346184916866876, 0.8348888624532548, 0.6544834567840291,
183+ 0.2844062293389934, 0.28780026600883324, 0.5372272015684924, 0.6250226011503823, 0.28119106062279453, 0.49655812908420094, 0.6451488959145951,
184+ 0.7362580606834843, 0.44815578616664087, 0.6454760235835586, 0.6794062414265861, 0.045378883014935756, 0.9008388543865096, 0.7949752851269782,
185+ 0.4179928876222264, 0.28733419007048644, 0.996902319501908, 0.5690851338677467, 0.9511814013279738, 0.025323788678181636, 0.5594359732604794,
186+ 0.1213732595086251, 0.7172624313368294, 0.6759328959074691, 0.07252138454885071, 0.17557735158403442, 0.5988895455048769
187+ };
188+ float expected_output[1*3*4*2] = {
189+ -0.556947, -0.42143887, -0.092070885, 0.27404794, -0.41886684, 0.0862887, -0.25001016, -0.342721, 0.020730592, 0.04016919, -0.69839877,
190+ -0.06136704, 0.14186388, -0.11655602, -0.23489095, -0.3845829, -0.19017771, 0.1595885, -0.18308741, -0.3071209, -0.5848686, -0.22509028,
191+ -0.6023201, -0.14448485
192+ };
193+ float *output;
194+ float kernel[2*3*3*3] = {
195+ -0.25291282, 0.22402048, 0.028642118, -0.14615723, -0.27362752, -0.34801802, -0.2759148, 0.19594926, -0.25029412, 0.34606284, 0.10376671,
196+ -0.1015394, 0.23616093, 0.2134214, 0.35285157, 0.05893758, 0.0024731457, -0.17143056, 0.35758412, 0.2186206, -0.28384736, -0.21206513,
197+ -0.20871592, 0.27070445, 0.25878823, 0.11136332, -0.33737376, 0.08353335, -0.34290665, 0.041805506, -0.09738535, 0.3284936, -0.16838405,
198+ -0.032494456, -0.29193437, 0.033259362, -0.09272635, -0.2802651, -0.28648436, 0.3542878, 0.2432127, -0.24551713, 0.27813476, 0.21024024,
199+ -0.013690501, -0.1350077, -0.07826337, -0.34563828, 0.3220685, -0.07571727, 0.19420576, 0.20783454, 0.18738335, 0.16672492
200+ };
201+ float bias[2] = { -0.4773722, -0.19620377 };
202+
203+ NativeContext ctx;
204+ ctx.class = NULL;
205+ ctx.options.conv2d_threads = 1;
206+
207+ params.activation = TANH;
208+ params.has_bias = 1;
209+ params.biases = bias;
210+ params.dilation = 1;
211+ params.input_num = 3;
212+ params.kernel = kernel;
213+ params.kernel_size = 3;
214+ params.output_num = 2;
215+ params.padding_method = VALID;
216+
217+ operands[0].data = input;
218+ operands[0].dims[0] = 1;
219+ operands[0].dims[1] = 5;
220+ operands[0].dims[2] = 6;
221+ operands[0].dims[3] = 3;
222+ operands[1].data = NULL;
223+
224+ input_indexes[0] = 0;
225+ ff_dnn_execute_layer_conv2d(operands, input_indexes, 1, &params, &ctx);
226+
227+ output = operands[1].data;
228+ for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
229+ if (fabs(output[i] - expected_output[i]) > EPSON) {
230+ printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
231+ av_freep(&output);
232+ return 1;
233+ }
234+ }
235+
236+ av_freep(&output);
237+ return 0;
238+}
239+
240+int main(int argc, char **argv)
241+{
242+ if (test_with_valid())
243+ return 1;
244+ if (test_with_same_dilate())
245+ return 1;
246+
247+ return 0;
248+}
libavfilter/tests/dnn-layer-dense.c+131−0
@@ -0,0 +1,131 @@
1+/*
2+ * Copyright (c) 2020
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_dense.h"
25+
26+#define EPSON 0.00001
27+
28+static int test(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.layers.dense(input_x, 3, activation=tf.nn.sigmoid, bias_initializer=tf.keras.initializers.he_normal())
34+ data = np.random.rand(1, 5, 6, 3);
35+
36+ sess=tf.Session()
37+ sess.run(tf.global_variables_initializer())
38+
39+ weights = dict([(var.name, sess.run(var)) for var in tf.trainable_variables()])
40+ kernel = weights['dense/kernel:0']
41+ kernel = np.transpose(kernel, [1, 0])
42+ print("kernel:")
43+ print(kernel.shape)
44+ print(list(kernel.flatten()))
45+
46+ bias = weights['dense/bias:0']
47+ print("bias:")
48+ print(bias.shape)
49+ print(list(bias.flatten()))
50+
51+ output = sess.run(y, feed_dict={x: data})
52+
53+ print("input:")
54+ print(data.shape)
55+ print(list(data.flatten()))
56+
57+ print("output:")
58+ print(output.shape)
59+ print(list(output.flatten()))
60+ */
61+
62+ DenseParams params;
63+ DnnOperand operands[2];
64+ int32_t input_indexes[1];
65+ float input[1*5*6*3] = {
66+ 0.5552418686576308, 0.20653189262022464, 0.31115120939398877, 0.5897014433221428, 0.37340078861060655, 0.6470921693941893, 0.8039950367872679, 0.8762700891949274,
67+ 0.6556655583829558, 0.5911096107039339, 0.18640250865290997, 0.2803248779238966, 0.31586613136402053, 0.9447300740056483, 0.9443980824873418, 0.8158851991115941,
68+ 0.5631010340387631, 0.9407402251929046, 0.6485434876551682, 0.5631376966470001, 0.17581924875609634, 0.7033802439103178, 0.04802402495561675, 0.9183681450194972,
69+ 0.46059317944364, 0.07964160481596883, 0.871787076270302, 0.973743142324361, 0.15923146943258415, 0.8212946080584571, 0.5415954459227064, 0.9552813822803975,
70+ 0.4908552668172057, 0.33723691635292274, 0.46588057864910026, 0.8994239961321776, 0.09845220457674186, 0.1713400292123486, 0.39570294912818826, 0.08018956486392803,
71+ 0.5290478278169032, 0.7141906125920976, 0.0320878067840098, 0.6412406575332606, 0.0075712007102423096, 0.7150828462386156, 0.1311989216968138, 0.4706847944253756,
72+ 0.5447610794883336, 0.3430923933318001, 0.536082357943209, 0.4371629342483694, 0.40227962985019927, 0.3553806249465469, 0.031806622424259245, 0.7053916426174,
73+ 0.3261570237309813, 0.419500213292063, 0.3155691223480851, 0.05664028113178088, 0.3636491555914486, 0.8502419746667123, 0.9836596530684955, 0.1628681802975801,
74+ 0.09410832912479894, 0.28407218939480294, 0.7983417928813697, 0.24132158596506748, 0.8154729498062224, 0.29173768373895637, 0.13407102008052096, 0.18705786678800385,
75+ 0.7167943621295573, 0.09222004247174376, 0.2319220738766018, 0.17708964382285064, 0.1391440370249517, 0.3254088083499256, 0.4013916894718289, 0.4819742663322323,
76+ 0.15080103744648077, 0.9302407847555013, 0.9397597961319524, 0.5719200825550793, 0.9538938024682824, 0.9583882089203861, 0.5168861091262276, 0.1926396841842669,
77+ 0.6781176744337578, 0.719366447288566
78+ };
79+ float expected_output[1*5*6*3] = {
80+ -0.3921688, -0.9243112, -0.29659146, -0.64000785, -0.9466343, -0.62125254, -0.71759033, -0.9171336, -0.735589, -0.34365994,
81+ -0.92100817, -0.23903961, -0.8962277, -0.9521279, -0.90962386, -0.7488303, -0.9563761, -0.7701762, -0.40800542, -0.87684774,
82+ -0.3339763, -0.6354543, -0.97068924, -0.6246325, -0.6992075, -0.9706726, -0.6818918, -0.51864433, -0.9592881, -0.51187396,
83+ -0.7423632, -0.89911884, -0.7457824, -0.82009757, -0.96402895, -0.8235518, -0.61980766, -0.94494647, -0.5410502, -0.8281218,
84+ -0.95508635, -0.8201453, -0.5937325, -0.8679507, -0.500767, -0.39430764, -0.93967676, -0.32183182, -0.58913624, -0.939717,
85+ -0.55179894, -0.55004454, -0.9214453, -0.4889004, -0.75294703, -0.9118363, -0.7200309, -0.3248641, -0.8878874, -0.18977344,
86+ -0.8873837, -0.9571257, -0.90145934, -0.50521654, -0.93739635, -0.39051685, -0.61143184, -0.9591179, -0.605999, -0.40008977,
87+ -0.92219675, -0.26732883, -0.19607787, -0.9172511, -0.07068595, -0.5409857, -0.9387041, -0.44181606, -0.4705004, -0.8899935,
88+ -0.37997037, -0.66105115, -0.89754754, -0.68141997, -0.6324047, -0.886776, -0.65066385, -0.8334821, -0.94801456, -0.83297
89+ };
90+ float *output;
91+ float kernel[3*3] = {
92+ 0.56611896, -0.5144603, -0.82600045, 0.19219112, 0.3835776, -0.7475352, 0.5209291, -0.6301091, -0.99442935};
93+ float bias[3] = {-0.3654299, -1.5711838, -0.15546428};
94+
95+ params.activation = TANH;
96+ params.has_bias = 1;
97+ params.biases = bias;
98+ params.input_num = 3;
99+ params.kernel = kernel;
100+ params.output_num = 3;
101+
102+ operands[0].data = input;
103+ operands[0].dims[0] = 1;
104+ operands[0].dims[1] = 5;
105+ operands[0].dims[2] = 6;
106+ operands[0].dims[3] = 3;
107+ operands[1].data = NULL;
108+
109+ input_indexes[0] = 0;
110+ ff_dnn_execute_layer_dense(operands, input_indexes, 1, &params, NULL);
111+
112+ output = operands[1].data;
113+ for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
114+ if (fabs(output[i] - expected_output[i]) > EPSON) {
115+ printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
116+ av_freep(&output);
117+ return 1;
118+ }
119+ }
120+
121+ av_freep(&output);
122+ return 0;
123+}
124+
125+int main(int argc, char **argv)
126+{
127+ if (test())
128+ return 1;
129+
130+ return 0;
131+}
libavfilter/tests/dnn-layer-depth2space.c+102−0
@@ -0,0 +1,102 @@
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.h"
25+#include "libavfilter/dnn/dnn_backend_native_layer_depth2space.h"
26+
27+#define EPSON 0.00001
28+
29+static int test(void)
30+{
31+ // the input data and expected data are generated with below python code.
32+ /*
33+ x = tf.placeholder(tf.float32, shape=[1, None, None, 4])
34+ y = tf.depth_to_space(x, 2)
35+ data = np.random.rand(1, 5, 3, 4);
36+
37+ sess=tf.Session()
38+ sess.run(tf.global_variables_initializer())
39+
40+ output = sess.run(y, feed_dict={x: data})
41+
42+ print("input:")
43+ print(data.shape)
44+ print(list(data.flatten()))
45+
46+ print("output:")
47+ print(output.shape)
48+ print(list(output.flatten()))
49+ */
50+
51+ DepthToSpaceParams params;
52+ DnnOperand operands[2];
53+ int32_t input_indexes[1];
54+ float input[1*5*3*4] = {
55+ 0.09771065121566602, 0.6336807372403175, 0.5142416549709786, 0.8027206567330333, 0.2154276025069397, 0.12112878462616772, 0.913936596765778,
56+ 0.38881443647542646, 0.5850447615898835, 0.9311499327398275, 0.3613660929428246, 0.5420722002125493, 0.6002131190230359, 0.44800665702299525,
57+ 0.7271322557896777, 0.3869293511885826, 0.5144404769364138, 0.6910844856987723, 0.6142102742269762, 0.6249991371621018, 0.45663376215836626,
58+ 0.19523477129943423, 0.2483895888532045, 0.64326768256278, 0.5485877602998981, 0.45442067849873546, 0.529374943304256, 0.30439850391811885,
59+ 0.11961343361340993, 0.2909643484561082, 0.9810970344127848, 0.8886928489786549, 0.6112237084436409, 0.8852482695156674, 0.9110868043114374,
60+ 0.21242780027585217, 0.7101536973207572, 0.9709717457443375, 0.2702666770969332, 0.7718295953780221, 0.3957005164588574, 0.24383544252475453,
61+ 0.040143453532367035, 0.26358051835323115, 0.013130251443791319, 0.3016550481482074, 0.03582340459943956, 0.718025513612361, 0.09844204177633753,
62+ 0.04433767496953056, 0.6221895044119757, 0.6190414032940228, 0.8963550834625371, 0.5642449700064629, 0.2482982014723497, 0.17824909294583013,
63+ 0.024401882408643272, 0.21742800875253465, 0.6794724473181843, 0.4814830479242237
64+ };
65+ float expected_output[1*10*6*1] = {
66+ 0.097710654, 0.63368076, 0.2154276, 0.12112878, 0.58504474, 0.93114996, 0.51424164, 0.80272067, 0.9139366, 0.38881445,
67+ 0.3613661, 0.5420722, 0.6002131, 0.44800666, 0.5144405, 0.6910845, 0.45663378, 0.19523478, 0.72713226, 0.38692936,
68+ 0.61421025, 0.62499917, 0.24838959, 0.6432677, 0.54858774, 0.4544207, 0.11961343, 0.29096434, 0.6112237, 0.88524824,
69+ 0.52937496, 0.3043985, 0.98109704, 0.88869286, 0.9110868, 0.2124278, 0.7101537, 0.97097176, 0.3957005, 0.24383545,
70+ 0.013130251, 0.30165505, 0.27026668, 0.7718296, 0.040143453, 0.26358053, 0.035823405, 0.7180255, 0.09844204,
71+ 0.044337675, 0.8963551, 0.564245, 0.024401883, 0.21742801, 0.6221895, 0.6190414, 0.2482982, 0.17824909, 0.67947245, 0.48148304
72+ };
73+ float *output;
74+
75+ operands[0].data = input;
76+ operands[0].dims[0] = 1;
77+ operands[0].dims[1] = 5;
78+ operands[0].dims[2] = 3;
79+ operands[0].dims[3] = 4;
80+ operands[1].data = NULL;
81+
82+ input_indexes[0] = 0;
83+ params.block_size = 2;
84+ ff_dnn_execute_layer_depth2space(operands, input_indexes, 1, &params, NULL);
85+
86+ output = operands[1].data;
87+ for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
88+ if (fabs(output[i] - expected_output[i]) > EPSON) {
89+ printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
90+ av_freep(&output);
91+ return 1;
92+ }
93+ }
94+
95+ av_freep(&output);
96+ return 0;
97+}
98+
99+int main(int argc, char **argv)
100+{
101+ return test();
102+}
libavfilter/tests/dnn-layer-mathbinary.c+214−0
@@ -0,0 +1,214 @@
1+/*
2+ * Copyright (c) 2020
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_mathbinary.h"
25+#include "libavutil/avassert.h"
26+
27+#define EPSON 0.00005
28+
29+static float get_expected(float f1, float f2, DNNMathBinaryOperation op)
30+{
31+ switch (op)
32+ {
33+ case DMBO_SUB:
34+ return f1 - f2;
35+ case DMBO_ADD:
36+ return f1 + f2;
37+ case DMBO_MUL:
38+ return f1 * f2;
39+ case DMBO_REALDIV:
40+ return f1 / f2;
41+ case DMBO_MINIMUM:
42+ return (f1 < f2) ? f1 : f2;
43+ case DMBO_FLOORMOD:
44+ return (float)((int)(f1) % (int)(f2));
45+ default:
46+ av_assert0(!"not supported yet");
47+ return 0.f;
48+ }
49+}
50+
51+static int test_broadcast_input0(DNNMathBinaryOperation op)
52+{
53+ DnnLayerMathBinaryParams params;
54+ DnnOperand operands[2];
55+ int32_t input_indexes[1];
56+ float input[1*1*2*3] = {
57+ -3, 2.5, 2, -2.1, 7.8, 100
58+ };
59+ float *output;
60+
61+ params.bin_op = op;
62+ params.input0_broadcast = 1;
63+ params.input1_broadcast = 0;
64+ params.v = 7.28;
65+
66+ operands[0].data = input;
67+ operands[0].dims[0] = 1;
68+ operands[0].dims[1] = 1;
69+ operands[0].dims[2] = 2;
70+ operands[0].dims[3] = 3;
71+ operands[1].data = NULL;
72+
73+ input_indexes[0] = 0;
74+ ff_dnn_execute_layer_math_binary(operands, input_indexes, 1, &params, NULL);
75+
76+ output = operands[1].data;
77+ for (int i = 0; i < sizeof(input) / sizeof(float); i++) {
78+ float expected_output = get_expected(params.v, input[i], op);
79+ if (fabs(output[i] - expected_output) > EPSON) {
80+ printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n",
81+ op, i, output[i], expected_output, __FILE__, __LINE__);
82+ av_freep(&output);
83+ return 1;
84+ }
85+ }
86+
87+ av_freep(&output);
88+ return 0;
89+}
90+
91+static int test_broadcast_input1(DNNMathBinaryOperation op)
92+{
93+ DnnLayerMathBinaryParams params;
94+ DnnOperand operands[2];
95+ int32_t input_indexes[1];
96+ float input[1*1*2*3] = {
97+ -3, 2.5, 2, -2.1, 7.8, 100
98+ };
99+ float *output;
100+
101+ params.bin_op = op;
102+ params.input0_broadcast = 0;
103+ params.input1_broadcast = 1;
104+ params.v = 7.28;
105+
106+ operands[0].data = input;
107+ operands[0].dims[0] = 1;
108+ operands[0].dims[1] = 1;
109+ operands[0].dims[2] = 2;
110+ operands[0].dims[3] = 3;
111+ operands[1].data = NULL;
112+
113+ input_indexes[0] = 0;
114+ ff_dnn_execute_layer_math_binary(operands, input_indexes, 1, &params, NULL);
115+
116+ output = operands[1].data;
117+ for (int i = 0; i < sizeof(input) / sizeof(float); i++) {
118+ float expected_output = get_expected(input[i], params.v, op);
119+ if (fabs(output[i] - expected_output) > EPSON) {
120+ printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n",
121+ op, i, output[i], expected_output, __FILE__, __LINE__);
122+ av_freep(&output);
123+ return 1;
124+ }
125+ }
126+
127+ av_freep(&output);
128+ return 0;
129+}
130+
131+static int test_no_broadcast(DNNMathBinaryOperation op)
132+{
133+ DnnLayerMathBinaryParams params;
134+ DnnOperand operands[3];
135+ int32_t input_indexes[2];
136+ float input0[1*1*2*3] = {
137+ -3, 2.5, 2, -2.1, 7.8, 100
138+ };
139+ float input1[1*1*2*3] = {
140+ -1, 2, 3, -21, 8, 10.0
141+ };
142+ float *output;
143+
144+ params.bin_op = op;
145+ params.input0_broadcast = 0;
146+ params.input1_broadcast = 0;
147+
148+ operands[0].data = input0;
149+ operands[0].dims[0] = 1;
150+ operands[0].dims[1] = 1;
151+ operands[0].dims[2] = 2;
152+ operands[0].dims[3] = 3;
153+ operands[1].data = input1;
154+ operands[1].dims[0] = 1;
155+ operands[1].dims[1] = 1;
156+ operands[1].dims[2] = 2;
157+ operands[1].dims[3] = 3;
158+ operands[2].data = NULL;
159+
160+ input_indexes[0] = 0;
161+ input_indexes[1] = 1;
162+ ff_dnn_execute_layer_math_binary(operands, input_indexes, 2, &params, NULL);
163+
164+ output = operands[2].data;
165+ for (int i = 0; i < sizeof(input0) / sizeof(float); i++) {
166+ float expected_output = get_expected(input0[i], input1[i], op);
167+ if (fabs(output[i] - expected_output) > EPSON) {
168+ printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n",
169+ op, i, output[i], expected_output, __FILE__, __LINE__);
170+ av_freep(&output);
171+ return 1;
172+ }
173+ }
174+
175+ av_freep(&output);
176+ return 0;
177+}
178+
179+static int test(DNNMathBinaryOperation op)
180+{
181+ if (test_broadcast_input0(op))
182+ return 1;
183+
184+ if (test_broadcast_input1(op))
185+ return 1;
186+
187+ if (test_no_broadcast(op))
188+ return 1;
189+
190+ return 0;
191+}
192+
193+int main(int argc, char **argv)
194+{
195+ if (test(DMBO_SUB))
196+ return 1;
197+
198+ if (test(DMBO_ADD))
199+ return 1;
200+
201+ if (test(DMBO_MUL))
202+ return 1;
203+
204+ if (test(DMBO_REALDIV))
205+ return 1;
206+
207+ if (test(DMBO_MINIMUM))
208+ return 1;
209+
210+ if (test(DMBO_FLOORMOD))
211+ return 1;
212+
213+ return 0;
214+}
libavfilter/tests/dnn-layer-mathunary.c+148−0
@@ -0,0 +1,148 @@
1+/*
2+ * Copyright (c) 2020
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_mathunary.h"
25+#include "libavutil/avassert.h"
26+
27+#define EPS 0.00001
28+
29+static float get_expected(float f, DNNMathUnaryOperation op)
30+{
31+ switch (op)
32+ {
33+ case DMUO_ABS:
34+ return (f >= 0) ? f : -f;
35+ case DMUO_SIN:
36+ return sin(f);
37+ case DMUO_COS:
38+ return cos(f);
39+ case DMUO_TAN:
40+ return tan(f);
41+ case DMUO_ASIN:
42+ return asin(f);
43+ case DMUO_ACOS:
44+ return acos(f);
45+ case DMUO_ATAN:
46+ return atan(f);
47+ case DMUO_SINH:
48+ return sinh(f);
49+ case DMUO_COSH:
50+ return cosh(f);
51+ case DMUO_TANH:
52+ return tanh(f);
53+ case DMUO_ASINH:
54+ return asinh(f);
55+ case DMUO_ACOSH:
56+ return acosh(f);
57+ case DMUO_ATANH:
58+ return atanh(f);
59+ case DMUO_CEIL:
60+ return ceil(f);
61+ case DMUO_FLOOR:
62+ return floor(f);
63+ case DMUO_ROUND:
64+ return round(f);
65+ case DMUO_EXP:
66+ return exp(f);
67+ default:
68+ av_assert0(!"not supported yet");
69+ return 0.f;
70+ }
71+}
72+
73+static int test(DNNMathUnaryOperation op)
74+{
75+ DnnLayerMathUnaryParams params;
76+ DnnOperand operands[2];
77+ int32_t input_indexes[1];
78+ float input[1*1*3*3] = {
79+ 0.1, 0.5, 0.75, -3, 2.5, 2, -2.1, 7.8, 100};
80+ float *output;
81+
82+ params.un_op = op;
83+
84+ operands[0].data = input;
85+ operands[0].dims[0] = 1;
86+ operands[0].dims[1] = 1;
87+ operands[0].dims[2] = 3;
88+ operands[0].dims[3] = 3;
89+ operands[1].data = NULL;
90+
91+ input_indexes[0] = 0;
92+ ff_dnn_execute_layer_math_unary(operands, input_indexes, 1, &params, NULL);
93+
94+ output = operands[1].data;
95+ for (int i = 0; i < sizeof(input) / sizeof(float); ++i) {
96+ float expected_output = get_expected(input[i], op);
97+ int output_nan = isnan(output[i]);
98+ int expected_nan = isnan(expected_output);
99+ if ((!output_nan && !expected_nan && fabs(output[i] - expected_output) > EPS) ||
100+ (output_nan && !expected_nan) || (!output_nan && expected_nan)) {
101+ printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output);
102+ av_freep(&output);
103+ return 1;
104+ }
105+ }
106+
107+ av_freep(&output);
108+ return 0;
109+}
110+
111+int main(int agrc, char **argv)
112+{
113+ if (test(DMUO_ABS))
114+ return 1;
115+ if (test(DMUO_SIN))
116+ return 1;
117+ if (test(DMUO_COS))
118+ return 1;
119+ if (test(DMUO_TAN))
120+ return 1;
121+ if (test(DMUO_ASIN))
122+ return 1;
123+ if (test(DMUO_ACOS))
124+ return 1;
125+ if (test(DMUO_ATAN))
126+ return 1;
127+ if (test(DMUO_SINH))
128+ return 1;
129+ if (test(DMUO_COSH))
130+ return 1;
131+ if (test(DMUO_TANH))
132+ return 1;
133+ if (test(DMUO_ASINH))
134+ return 1;
135+ if (test(DMUO_ACOSH))
136+ return 1;
137+ if (test(DMUO_ATANH))
138+ return 1;
139+ if (test(DMUO_CEIL))
140+ return 1;
141+ if (test(DMUO_FLOOR))
142+ return 1;
143+ if (test(DMUO_ROUND))
144+ return 1;
145+ if (test(DMUO_EXP))
146+ return 1;
147+ return 0;
148+}
libavfilter/tests/dnn-layer-maximum.c+71−0
@@ -0,0 +1,71 @@
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_maximum.h"
25+
26+#define EPSON 0.00001
27+
28+static int test(void)
29+{
30+ DnnLayerMaximumParams params;
31+ DnnOperand operands[2];
32+ int32_t input_indexes[1];
33+ float input[1*1*2*3] = {
34+ -3, 2.5, 2, -2.1, 7.8, 100
35+ };
36+ float *output;
37+
38+ params.val.y = 2.3;
39+
40+ operands[0].data = input;
41+ operands[0].dims[0] = 1;
42+ operands[0].dims[1] = 1;
43+ operands[0].dims[2] = 2;
44+ operands[0].dims[3] = 3;
45+ operands[1].data = NULL;
46+
47+ input_indexes[0] = 0;
48+ ff_dnn_execute_layer_maximum(operands, input_indexes, 1, &params, NULL);
49+
50+ output = operands[1].data;
51+ for (int i = 0; i < sizeof(input) / sizeof(float); i++) {
52+ float expected_output = input[i] > params.val.y ? input[i] : params.val.y;
53+ if (fabs(output[i] - expected_output) > EPSON) {
54+ printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output);
55+ av_freep(&output);
56+ return 1;
57+ }
58+ }
59+
60+ av_freep(&output);
61+ return 0;
62+
63+}
64+
65+int main(int argc, char **argv)
66+{
67+ if (test())
68+ return 1;
69+
70+ return 0;
71+}
libavfilter/tests/dnn-layer-pad.c+239−0
@@ -0,0 +1,239 @@
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+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t