1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
5 // Copyright (C) 2017, Intel Corporation, all rights reserved.
6 // Third party copyrights are property of their respective owners.
9 Test for Tensorflow models loading
12 #include "test_precomp.hpp"
13 #include "npy_blob.hpp"
15 #include <opencv2/dnn/layer.details.hpp> // CV_DNN_REGISTER_LAYER_CLASS
21 using namespace cv::dnn;
23 template<typename TString>
24 static std::string _tf(TString filename)
26 return (getOpenCVExtraDir() + "/dnn/") + filename;
29 TEST(Test_TensorFlow, read_inception)
33 const string model = findDataFile("dnn/tensorflow_inception_graph.pb", false);
34 net = readNetFromTensorflow(model);
35 ASSERT_FALSE(net.empty());
37 net.setPreferableBackend(DNN_BACKEND_OPENCV);
39 Mat sample = imread(_tf("grace_hopper_227.png"));
40 ASSERT_TRUE(!sample.empty());
42 resize(sample, input, Size(224, 224));
43 input -= 128; // mean sub
45 Mat inputBlob = blobFromImage(input);
47 net.setInput(inputBlob, "input");
48 Mat out = net.forward("softmax2");
50 std::cout << out.dims << std::endl;
53 TEST(Test_TensorFlow, inception_accuracy)
57 const string model = findDataFile("dnn/tensorflow_inception_graph.pb", false);
58 net = readNetFromTensorflow(model);
59 ASSERT_FALSE(net.empty());
61 net.setPreferableBackend(DNN_BACKEND_OPENCV);
63 Mat sample = imread(_tf("grace_hopper_227.png"));
64 ASSERT_TRUE(!sample.empty());
65 resize(sample, sample, Size(224, 224));
66 Mat inputBlob = blobFromImage(sample);
68 net.setInput(inputBlob, "input");
69 Mat out = net.forward("softmax2");
71 Mat ref = blobFromNPY(_tf("tf_inception_prob.npy"));
76 static std::string path(const std::string& file)
78 return findDataFile("dnn/tensorflow/" + file, false);
81 static void runTensorFlowNet(const std::string& prefix, int targetId = DNN_TARGET_CPU, bool hasText = false,
82 double l1 = 1e-5, double lInf = 1e-4,
83 bool memoryLoad = false)
85 std::string netPath = path(prefix + "_net.pb");
86 std::string netConfig = (hasText ? path(prefix + "_net.pbtxt") : "");
87 std::string inpPath = path(prefix + "_in.npy");
88 std::string outPath = path(prefix + "_out.npy");
93 // Load files into a memory buffers
95 ASSERT_TRUE(readFileInMemory(netPath, dataModel));
99 ASSERT_TRUE(readFileInMemory(netConfig, dataConfig));
101 net = readNetFromTensorflow(dataModel.c_str(), dataModel.size(),
102 dataConfig.c_str(), dataConfig.size());
105 net = readNetFromTensorflow(netPath, netConfig);
107 ASSERT_FALSE(net.empty());
109 net.setPreferableBackend(DNN_BACKEND_OPENCV);
110 net.setPreferableTarget(targetId);
112 cv::Mat input = blobFromNPY(inpPath);
113 cv::Mat target = blobFromNPY(outPath);
116 cv::Mat output = net.forward();
117 normAssert(target, output, "", l1, lInf);
120 typedef testing::TestWithParam<DNNTarget> Test_TensorFlow_layers;
122 TEST_P(Test_TensorFlow_layers, conv)
124 int targetId = GetParam();
125 runTensorFlowNet("single_conv", targetId);
126 runTensorFlowNet("atrous_conv2d_valid", targetId);
127 runTensorFlowNet("atrous_conv2d_same", targetId);
128 runTensorFlowNet("depthwise_conv2d", targetId);
129 runTensorFlowNet("keras_atrous_conv2d_same", targetId);
132 TEST_P(Test_TensorFlow_layers, padding)
134 int targetId = GetParam();
135 runTensorFlowNet("padding_same", targetId);
136 runTensorFlowNet("padding_valid", targetId);
137 runTensorFlowNet("spatial_padding", targetId);
140 TEST_P(Test_TensorFlow_layers, eltwise_add_mul)
142 runTensorFlowNet("eltwise_add_mul", GetParam());
145 TEST_P(Test_TensorFlow_layers, concat)
147 runTensorFlowNet("pad_and_concat", GetParam());
148 runTensorFlowNet("concat_axis_1", GetParam());
151 TEST_P(Test_TensorFlow_layers, batch_norm)
153 int targetId = GetParam();
154 runTensorFlowNet("batch_norm", targetId);
155 runTensorFlowNet("fused_batch_norm", targetId);
156 runTensorFlowNet("batch_norm_text", targetId, true);
157 runTensorFlowNet("mvn_batch_norm", targetId);
158 runTensorFlowNet("mvn_batch_norm_1x1", targetId);
159 runTensorFlowNet("unfused_batch_norm", targetId);
160 runTensorFlowNet("fused_batch_norm_no_gamma", targetId);
161 runTensorFlowNet("unfused_batch_norm_no_gamma", targetId);
164 TEST_P(Test_TensorFlow_layers, pooling)
166 int targetId = GetParam();
167 cv::ocl::Device d = cv::ocl::Device::getDefault();
168 bool loosenFlag = targetId == DNN_TARGET_OPENCL && d.isIntel() && d.type() == cv::ocl::Device::TYPE_CPU;
169 runTensorFlowNet("max_pool_even", targetId);
170 runTensorFlowNet("max_pool_odd_valid", targetId);
171 runTensorFlowNet("ave_pool_same", targetId);
172 runTensorFlowNet("max_pool_odd_same", targetId, false, loosenFlag ? 3e-5 : 1e-5, loosenFlag ? 3e-4 : 1e-4);
173 runTensorFlowNet("reduce_mean", targetId); // an average pooling over all spatial dimensions.
176 TEST_P(Test_TensorFlow_layers, deconvolution)
178 int targetId = GetParam();
179 runTensorFlowNet("deconvolution", targetId);
180 runTensorFlowNet("deconvolution_same", targetId);
181 runTensorFlowNet("deconvolution_stride_2_same", targetId);
182 runTensorFlowNet("deconvolution_adj_pad_valid", targetId);
183 runTensorFlowNet("deconvolution_adj_pad_same", targetId);
184 runTensorFlowNet("keras_deconv_valid", targetId);
185 runTensorFlowNet("keras_deconv_same", targetId);
188 TEST_P(Test_TensorFlow_layers, matmul)
190 int targetId = GetParam();
191 runTensorFlowNet("matmul", targetId);
192 runTensorFlowNet("nhwc_reshape_matmul", targetId);
193 runTensorFlowNet("nhwc_transpose_reshape_matmul", targetId);
196 TEST_P(Test_TensorFlow_layers, reshape)
198 int targetId = GetParam();
199 runTensorFlowNet("shift_reshape_no_reorder", targetId);
200 runTensorFlowNet("reshape_reduce", targetId);
201 runTensorFlowNet("flatten", targetId, true);
202 runTensorFlowNet("unfused_flatten", targetId);
203 runTensorFlowNet("unfused_flatten_unknown_batch", targetId);
206 TEST_P(Test_TensorFlow_layers, l2_normalize)
208 int targetId = GetParam();
209 runTensorFlowNet("l2_normalize", targetId);
210 runTensorFlowNet("l2_normalize_3d", targetId);
213 INSTANTIATE_TEST_CASE_P(/**/, Test_TensorFlow_layers, availableDnnTargets());
215 typedef testing::TestWithParam<DNNTarget> Test_TensorFlow_nets;
217 TEST_P(Test_TensorFlow_nets, MobileNet_SSD)
219 std::string netPath = findDataFile("dnn/ssd_mobilenet_v1_coco.pb", false);
220 std::string netConfig = findDataFile("dnn/ssd_mobilenet_v1_coco.pbtxt", false);
221 std::string imgPath = findDataFile("dnn/street.png", false);
224 resize(imread(imgPath), inp, Size(300, 300));
225 inp = blobFromImage(inp, 1.0f / 127.5, Size(), Scalar(127.5, 127.5, 127.5), true);
227 std::vector<String> outNames(3);
228 outNames[0] = "concat";
229 outNames[1] = "concat_1";
230 outNames[2] = "detection_out";
232 std::vector<Mat> target(outNames.size());
233 for (int i = 0; i < outNames.size(); ++i)
235 std::string path = findDataFile("dnn/tensorflow/ssd_mobilenet_v1_coco." + outNames[i] + ".npy", false);
236 target[i] = blobFromNPY(path);
239 Net net = readNetFromTensorflow(netPath, netConfig);
240 net.setPreferableBackend(DNN_BACKEND_OPENCV);
241 net.setPreferableTarget(GetParam());
245 std::vector<Mat> output;
246 net.forward(output, outNames);
248 normAssert(target[0].reshape(1, 1), output[0].reshape(1, 1), "", 1e-5, 1.5e-4);
249 normAssert(target[1].reshape(1, 1), output[1].reshape(1, 1), "", 1e-5, 3e-4);
250 normAssertDetections(target[2], output[2], "", 0.2);
253 TEST_P(Test_TensorFlow_nets, Inception_v2_SSD)
255 std::string proto = findDataFile("dnn/ssd_inception_v2_coco_2017_11_17.pbtxt", false);
256 std::string model = findDataFile("dnn/ssd_inception_v2_coco_2017_11_17.pb", false);
258 Net net = readNetFromTensorflow(model, proto);
259 Mat img = imread(findDataFile("dnn/street.png", false));
260 Mat blob = blobFromImage(img, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), true, false);
262 net.setPreferableBackend(DNN_BACKEND_OPENCV);
263 net.setPreferableTarget(GetParam());
266 // Output has shape 1x1xNx7 where N - number of detections.
267 // An every detection is a vector of values [id, classId, confidence, left, top, right, bottom]
268 Mat out = net.forward();
269 Mat ref = (Mat_<float>(5, 7) << 0, 1, 0.90176028, 0.19872092, 0.36311883, 0.26461923, 0.63498729,
270 0, 3, 0.93569964, 0.64865261, 0.45906419, 0.80675775, 0.65708131,
271 0, 3, 0.75838411, 0.44668293, 0.45907149, 0.49459291, 0.52197015,
272 0, 10, 0.95932811, 0.38349164, 0.32528657, 0.40387636, 0.39165527,
273 0, 10, 0.93973452, 0.66561931, 0.37841269, 0.68074018, 0.42907384);
274 normAssertDetections(ref, out, "", 0.5);
277 TEST_P(Test_TensorFlow_nets, Inception_v2_Faster_RCNN)
279 std::string proto = findDataFile("dnn/faster_rcnn_inception_v2_coco_2018_01_28.pbtxt", false);
280 std::string model = findDataFile("dnn/faster_rcnn_inception_v2_coco_2018_01_28.pb", false);
282 Net net = readNetFromTensorflow(model, proto);
283 net.setPreferableBackend(DNN_BACKEND_OPENCV);
284 Mat img = imread(findDataFile("dnn/dog416.png", false));
285 Mat blob = blobFromImage(img, 1.0f / 127.5, Size(800, 600), Scalar(127.5, 127.5, 127.5), true, false);
288 Mat out = net.forward();
290 Mat ref = blobFromNPY(findDataFile("dnn/tensorflow/faster_rcnn_inception_v2_coco_2018_01_28.detection_out.npy"));
291 normAssertDetections(ref, out, "", 0.3);
294 TEST_P(Test_TensorFlow_nets, opencv_face_detector_uint8)
296 std::string proto = findDataFile("dnn/opencv_face_detector.pbtxt", false);
297 std::string model = findDataFile("dnn/opencv_face_detector_uint8.pb", false);
299 Net net = readNetFromTensorflow(model, proto);
300 Mat img = imread(findDataFile("gpu/lbpcascade/er.png", false));
301 Mat blob = blobFromImage(img, 1.0, Size(), Scalar(104.0, 177.0, 123.0), false, false);
303 net.setPreferableBackend(DNN_BACKEND_OPENCV);
304 net.setPreferableTarget(GetParam());
307 // Output has shape 1x1xNx7 where N - number of detections.
308 // An every detection is a vector of values [id, classId, confidence, left, top, right, bottom]
309 Mat out = net.forward();
311 // References are from test for Caffe model.
312 Mat ref = (Mat_<float>(6, 7) << 0, 1, 0.99520785, 0.80997437, 0.16379407, 0.87996572, 0.26685631,
313 0, 1, 0.9934696, 0.2831718, 0.50738752, 0.345781, 0.5985168,
314 0, 1, 0.99096733, 0.13629119, 0.24892329, 0.19756334, 0.3310290,
315 0, 1, 0.98977017, 0.23901358, 0.09084064, 0.29902688, 0.1769477,
316 0, 1, 0.97203469, 0.67965847, 0.06876482, 0.73999709, 0.1513494,
317 0, 1, 0.95097077, 0.51901293, 0.45863652, 0.5777427, 0.5347801);
318 normAssertDetections(ref, out, "", 0.9, 3.4e-3, 1e-2);
321 // inp = cv.imread('opencv_extra/testdata/cv/ximgproc/sources/08.png')
322 // inp = inp[:,:,[2, 1, 0]].astype(np.float32).reshape(1, 512, 512, 3)
323 // outs = sess.run([sess.graph.get_tensor_by_name('feature_fusion/Conv_7/Sigmoid:0'),
324 // sess.graph.get_tensor_by_name('feature_fusion/concat_3:0')],
325 // feed_dict={'input_images:0': inp})
326 // scores = np.ascontiguousarray(outs[0].transpose(0, 3, 1, 2))
327 // geometry = np.ascontiguousarray(outs[1].transpose(0, 3, 1, 2))
328 // np.save('east_text_detection.scores.npy', scores)
329 // np.save('east_text_detection.geometry.npy', geometry)
330 TEST_P(Test_TensorFlow_nets, EAST_text_detection)
332 std::string netPath = findDataFile("dnn/frozen_east_text_detection.pb", false);
333 std::string imgPath = findDataFile("cv/ximgproc/sources/08.png", false);
334 std::string refScoresPath = findDataFile("dnn/east_text_detection.scores.npy", false);
335 std::string refGeometryPath = findDataFile("dnn/east_text_detection.geometry.npy", false);
337 Net net = readNet(findDataFile("dnn/frozen_east_text_detection.pb", false));
339 net.setPreferableTarget(GetParam());
341 Mat img = imread(imgPath);
342 Mat inp = blobFromImage(img, 1.0, Size(), Scalar(123.68, 116.78, 103.94), true, false);
345 std::vector<Mat> outs;
346 std::vector<String> outNames(2);
347 outNames[0] = "feature_fusion/Conv_7/Sigmoid";
348 outNames[1] = "feature_fusion/concat_3";
349 net.forward(outs, outNames);
351 Mat scores = outs[0];
352 Mat geometry = outs[1];
354 normAssert(scores, blobFromNPY(refScoresPath), "scores");
355 normAssert(geometry, blobFromNPY(refGeometryPath), "geometry", 1e-4, 3e-3);
358 INSTANTIATE_TEST_CASE_P(/**/, Test_TensorFlow_nets, availableDnnTargets());
360 typedef testing::TestWithParam<DNNTarget> Test_TensorFlow_fp16;
362 TEST_P(Test_TensorFlow_fp16, tests)
364 int targetId = GetParam();
365 const float l1 = 7e-4;
366 const float lInf = 1e-2;
367 runTensorFlowNet("fp16_single_conv", targetId, false, l1, lInf);
368 runTensorFlowNet("fp16_deconvolution", targetId, false, l1, lInf);
369 runTensorFlowNet("fp16_max_pool_odd_same", targetId, false, l1, lInf);
370 runTensorFlowNet("fp16_padding_valid", targetId, false, l1, lInf);
371 runTensorFlowNet("fp16_eltwise_add_mul", targetId, false, l1, lInf);
372 runTensorFlowNet("fp16_max_pool_odd_valid", targetId, false, l1, lInf);
373 runTensorFlowNet("fp16_pad_and_concat", targetId, false, l1, lInf);
374 runTensorFlowNet("fp16_max_pool_even", targetId, false, l1, lInf);
375 runTensorFlowNet("fp16_padding_same", targetId, false, l1, lInf);
378 INSTANTIATE_TEST_CASE_P(/**/, Test_TensorFlow_fp16,
379 Values(DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16));
381 TEST(Test_TensorFlow, defun)
383 runTensorFlowNet("defun_dropout");
386 TEST(Test_TensorFlow, quantized)
388 runTensorFlowNet("uint8_single_conv");
391 TEST(Test_TensorFlow, lstm)
393 runTensorFlowNet("lstm", DNN_TARGET_CPU, true);
396 TEST(Test_TensorFlow, split)
398 runTensorFlowNet("split_equals");
401 TEST(Test_TensorFlow, resize_nearest_neighbor)
403 runTensorFlowNet("resize_nearest_neighbor");
406 TEST(Test_TensorFlow, slice)
408 runTensorFlowNet("slice_4d");
411 TEST(Test_TensorFlow, softmax)
413 runTensorFlowNet("keras_softmax");
416 TEST(Test_TensorFlow, relu6)
418 runTensorFlowNet("keras_relu6");
419 runTensorFlowNet("keras_relu6", DNN_TARGET_CPU, /*hasText*/ true);
422 TEST(Test_TensorFlow, keras_mobilenet_head)
424 runTensorFlowNet("keras_mobilenet_head");
427 TEST(Test_TensorFlow, memory_read)
431 runTensorFlowNet("lstm", DNN_TARGET_CPU, true, l1, lInf, true);
433 runTensorFlowNet("batch_norm", DNN_TARGET_CPU, false, l1, lInf, true);
434 runTensorFlowNet("fused_batch_norm", DNN_TARGET_CPU, false, l1, lInf, true);
435 runTensorFlowNet("batch_norm_text", DNN_TARGET_CPU, true, l1, lInf, true);
438 TEST(Test_TensorFlow, resize_bilinear)
440 runTensorFlowNet("resize_bilinear");
441 runTensorFlowNet("resize_bilinear_factor");
444 TEST(Test_TensorFlow, two_inputs)
446 Net net = readNet(path("two_inputs_net.pbtxt"));
447 net.setPreferableBackend(DNN_BACKEND_OPENCV);
449 Mat firstInput(2, 3, CV_32FC1), secondInput(2, 3, CV_32FC1);
450 randu(firstInput, -1, 1);
451 randu(secondInput, -1, 1);
453 net.setInput(firstInput, "first_input");
454 net.setInput(secondInput, "second_input");
455 Mat out = net.forward();
457 normAssert(out, firstInput + secondInput);