mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
Merge pull request #28678 from omrope79:caffe-importer-cleanup
Caffe importer cleanup #28678 Merge with: https://github.com/opencv/opencv_extra/pull/1324 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -393,7 +393,7 @@ if(HAVE_PROTOBUF)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "HAVE_PROTOBUF=1")
|
||||
|
||||
if(PROTOBUF_UPDATE_FILES)
|
||||
file(GLOB proto_files "${CMAKE_CURRENT_LIST_DIR}/src/tensorflow/*.proto" "${CMAKE_CURRENT_LIST_DIR}/src/caffe/opencv-caffe.proto" "${CMAKE_CURRENT_LIST_DIR}/src/onnx/opencv-onnx.proto")
|
||||
file(GLOB proto_files "${CMAKE_CURRENT_LIST_DIR}/src/tensorflow/*.proto" "${CMAKE_CURRENT_LIST_DIR}/src/onnx/opencv-onnx.proto")
|
||||
if(CMAKE_VERSION VERSION_LESS "3.13.0")
|
||||
set(PROTOBUF_GENERATE_CPP_APPEND_PATH ON) # required for tensorflow
|
||||
protobuf_generate_cpp(fw_srcs fw_hdrs ${proto_files})
|
||||
@@ -587,28 +587,6 @@ ocv_add_perf_tests(${dnn_runtime_libs}
|
||||
FILES Include ${perf_hdrs}
|
||||
)
|
||||
|
||||
ocv_option(OPENCV_DNN_PERF_CAFFE "Add performance tests of Caffe framework" OFF)
|
||||
ocv_option(OPENCV_DNN_PERF_CLCAFFE "Add performance tests of clCaffe framework" OFF)
|
||||
if(BUILD_PERF_TESTS)
|
||||
if (OPENCV_DNN_PERF_CAFFE
|
||||
OR ${the_module}_PERF_CAFFE # compatibility for deprecated option
|
||||
)
|
||||
find_package(Caffe QUIET)
|
||||
if (Caffe_FOUND)
|
||||
ocv_target_compile_definitions(opencv_perf_dnn PRIVATE "HAVE_CAFFE=1")
|
||||
ocv_target_link_libraries(opencv_perf_dnn caffe)
|
||||
endif()
|
||||
elseif(OPENCV_DNN_PERF_CLCAFFE
|
||||
OR ${the_module}_PERF_CAFFE # compatibility for deprecated option
|
||||
)
|
||||
find_package(Caffe QUIET)
|
||||
if (Caffe_FOUND)
|
||||
ocv_target_compile_definitions(opencv_perf_dnn PRIVATE "HAVE_CLCAFFE=1")
|
||||
ocv_target_link_libraries(opencv_perf_dnn caffe)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DNN_ENABLE_PLUGINS)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE ENABLE_PLUGINS)
|
||||
if(TARGET opencv_test_dnn)
|
||||
|
||||
@@ -55,7 +55,7 @@ CV__DNN_INLINE_NS_BEGIN
|
||||
|
||||
Classes listed here, in fact, provides C++ API for creating instances of built-in layers.
|
||||
In addition to this way of layers instantiation, there is a more common factory API (see @ref dnnLayerFactory), it allows to create layers dynamically (by name) and register new ones.
|
||||
You can use both API, but factory API is less convenient for native C++ programming and basically designed for use inside importers (see @ref readNetFromCaffe(), @ref readNetFromTensorflow()).
|
||||
You can use both API, but factory API is less convenient for native C++ programming and basically designed for use inside importers (see @ref readNetFromTensorflow()).
|
||||
|
||||
Built-in layers partially reproduce functionality of corresponding ONNX, TensorFlow and Caffe layers.
|
||||
In particular, the following layers and Caffe importer were tested to reproduce <a href="http://caffe.berkeleyvision.org/tutorial/layers.html">Caffe</a> functionality:
|
||||
|
||||
@@ -1090,43 +1090,6 @@ CV__DNN_INLINE_NS_BEGIN
|
||||
ENGINE_ORT=4 //!< Try to use ONNX Runtime wrapper (ONNX only, requires build with WITH_ONNXRUNTIME=ON).
|
||||
};
|
||||
|
||||
/** @brief Reads a network model stored in <a href="http://caffe.berkeleyvision.org">Caffe</a> framework's format.
|
||||
* @param prototxt path to the .prototxt file with text description of the network architecture.
|
||||
* @param caffeModel path to the .caffemodel file with learned network.
|
||||
* @param engine select DNN engine to be used. With auto selection the new engine is used.
|
||||
* Please pay attention that the new DNN does not support non-CPU back-ends for now.
|
||||
* @returns Net object.
|
||||
*/
|
||||
CV_EXPORTS_W Net readNetFromCaffe(CV_WRAP_FILE_PATH const String &prototxt,
|
||||
CV_WRAP_FILE_PATH const String &caffeModel = String(),
|
||||
int engine = ENGINE_AUTO);
|
||||
|
||||
/** @brief Reads a network model stored in Caffe model in memory.
|
||||
* @param bufferProto buffer containing the content of the .prototxt file
|
||||
* @param bufferModel buffer containing the content of the .caffemodel file
|
||||
* @param engine select DNN engine to be used. With auto selection the new engine is used.
|
||||
* Please pay attention that the new DNN does not support non-CPU back-ends for now.
|
||||
* @returns Net object.
|
||||
*/
|
||||
CV_EXPORTS_W Net readNetFromCaffe(const std::vector<uchar>& bufferProto,
|
||||
const std::vector<uchar>& bufferModel = std::vector<uchar>(),
|
||||
int engine = ENGINE_AUTO);
|
||||
|
||||
/** @brief Reads a network model stored in Caffe model in memory.
|
||||
* @details This is an overloaded member function, provided for convenience.
|
||||
* It differs from the above function only in what argument(s) it accepts.
|
||||
* @param bufferProto buffer containing the content of the .prototxt file
|
||||
* @param lenProto length of bufferProto
|
||||
* @param bufferModel buffer containing the content of the .caffemodel file
|
||||
* @param lenModel length of bufferModel
|
||||
* @param engine select DNN engine to be used. With auto selection the new engine is used.
|
||||
* Please pay attention that the new DNN does not support non-CPU back-ends for now.
|
||||
* @returns Net object.
|
||||
*/
|
||||
CV_EXPORTS Net readNetFromCaffe(const char *bufferProto, size_t lenProto,
|
||||
const char *bufferModel = NULL, size_t lenModel = 0,
|
||||
int engine = ENGINE_AUTO);
|
||||
|
||||
/** @brief Reads a network model stored in <a href="https://www.tensorflow.org/">TensorFlow</a> framework's format.
|
||||
* @param model path to the .pb file with binary protobuf description of the network architecture
|
||||
* @param config path to the .pbtxt file that contains text graph definition in protobuf format.
|
||||
@@ -1201,13 +1164,11 @@ CV__DNN_INLINE_NS_BEGIN
|
||||
* @brief Read deep learning network represented in one of the supported formats.
|
||||
* @param[in] model Binary file contains trained weights. The following file
|
||||
* extensions are expected for models from different frameworks:
|
||||
* * `*.caffemodel` (Caffe, http://caffe.berkeleyvision.org/)
|
||||
* * `*.pb` (TensorFlow, https://www.tensorflow.org/)
|
||||
* * `*.bin` | `*.onnx` (OpenVINO, https://software.intel.com/openvino-toolkit)
|
||||
* * `*.onnx` (ONNX, https://onnx.ai/)
|
||||
* @param[in] config Text file contains network configuration. It could be a
|
||||
* file with the following extensions:
|
||||
* * `*.prototxt` (Caffe, http://caffe.berkeleyvision.org/)
|
||||
* * `*.pbtxt` (TensorFlow, https://www.tensorflow.org/)
|
||||
* * `*.xml` (OpenVINO, https://software.intel.com/openvino-toolkit)
|
||||
* @param[in] framework Explicit framework name tag to determine a format.
|
||||
@@ -1217,7 +1178,7 @@ CV__DNN_INLINE_NS_BEGIN
|
||||
* @returns Net object.
|
||||
*
|
||||
* This function automatically detects an origin framework of trained model
|
||||
* and calls an appropriate function such @ref readNetFromCaffe, @ref readNetFromTensorflow.
|
||||
* and calls an appropriate function such @ref readNetFromTensorflow, @ref readNetFromONNX.
|
||||
* An order of @p model and @p config arguments does not matter.
|
||||
*/
|
||||
CV_EXPORTS_W Net readNet(CV_WRAP_FILE_PATH const String& model,
|
||||
@@ -1467,22 +1428,6 @@ CV__DNN_INLINE_NS_BEGIN
|
||||
*/
|
||||
CV_EXPORTS_W void imagesFromBlob(const cv::Mat& blob_, OutputArrayOfArrays images_);
|
||||
|
||||
/** @brief Convert all weights of Caffe network to half precision floating point.
|
||||
* @param src Path to origin model from Caffe framework contains single
|
||||
* precision floating point weights (usually has `.caffemodel` extension).
|
||||
* @param dst Path to destination model with updated weights.
|
||||
* @param layersTypes Set of layers types which parameters will be converted.
|
||||
* By default, converts only Convolutional and Fully-Connected layers'
|
||||
* weights.
|
||||
*
|
||||
* @note Shrinked model has no origin float32 weights so it can't be used
|
||||
* in origin Caffe framework anymore. However the structure of data
|
||||
* is taken from NVidia's Caffe fork: https://github.com/NVIDIA/caffe.
|
||||
* So the resulting model may be used there.
|
||||
*/
|
||||
CV_EXPORTS_W void shrinkCaffeModel(CV_WRAP_FILE_PATH const String& src, CV_WRAP_FILE_PATH const String& dst,
|
||||
const std::vector<String>& layersTypes = std::vector<String>());
|
||||
|
||||
/** @brief Create a text representation for a binary network stored in protocol buffer format.
|
||||
* @param[in] model A path to binary network.
|
||||
* @param[in] output A path to output text file to be created.
|
||||
|
||||
@@ -1,67 +1,71 @@
|
||||
package org.opencv.test.dnn;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfByte;
|
||||
import org.opencv.core.Range;
|
||||
import org.opencv.dnn.Dnn;
|
||||
import org.opencv.dnn.Net;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
|
||||
public class DnnForwardAndRetrieve extends OpenCVTestCase {
|
||||
|
||||
private final static String ENV_OPENCV_DNN_TEST_DATA_PATH = "OPENCV_DNN_TEST_DATA_PATH";
|
||||
private final static String ENV_OPENCV_TEST_DATA_PATH = "OPENCV_TEST_DATA_PATH";
|
||||
|
||||
private String modelFileName = "";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
String dnnTestDataPath = System.getenv(ENV_OPENCV_DNN_TEST_DATA_PATH);
|
||||
String generalTestDataPath = System.getenv(ENV_OPENCV_TEST_DATA_PATH);
|
||||
|
||||
File model = null;
|
||||
|
||||
if (generalTestDataPath != null) {
|
||||
model = new File(generalTestDataPath, "dnn/onnx/models/split_0.onnx");
|
||||
}
|
||||
|
||||
if ((model == null || !model.isFile()) && dnnTestDataPath != null) {
|
||||
model = new File(dnnTestDataPath, "dnn/onnx/models/split_0.onnx");
|
||||
}
|
||||
|
||||
if (model == null || !model.isFile()) {
|
||||
isTestCaseEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
modelFileName = model.getAbsolutePath();
|
||||
}
|
||||
|
||||
public void testForwardAndRetrieve()
|
||||
{
|
||||
// Create a simple Caffe prototxt with a Slice layer
|
||||
String prototxt =
|
||||
"input: \"data\"\n" +
|
||||
"layer {\n" +
|
||||
" name: \"testLayer\"\n" +
|
||||
" type: \"Slice\"\n" +
|
||||
" bottom: \"data\"\n" +
|
||||
" top: \"firstCopy\"\n" +
|
||||
" top: \"secondCopy\"\n" +
|
||||
" slice_param {\n" +
|
||||
" axis: 0\n" +
|
||||
" slice_point: 2\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
// Read network from prototxt
|
||||
MatOfByte bufferProto = new MatOfByte();
|
||||
bufferProto.fromArray(prototxt.getBytes());
|
||||
MatOfByte bufferModel = new MatOfByte();
|
||||
Net net = Dnn.readNetFromCaffe(bufferProto, bufferModel, Dnn.ENGINE_CLASSIC);
|
||||
// Verifies forwardAndRetrieve nested list marshalling using a small ONNX model instead of the removed Caffe importer.
|
||||
Net net = Dnn.readNetFromONNX(modelFileName, Dnn.ENGINE_CLASSIC);
|
||||
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
|
||||
|
||||
// Create input data
|
||||
Mat inp = new Mat(4, 5, CvType.CV_32F);
|
||||
// split_0.onnx declares a single 4D input named "image" of shape [1, 3, 2, 2].
|
||||
Mat inp = new Mat(new int[]{1, 3, 2, 2}, CvType.CV_32F);
|
||||
Core.randu(inp, -1, 1);
|
||||
net.setInput(inp);
|
||||
|
||||
// Define output names
|
||||
List<String> outNames = new ArrayList<>();
|
||||
outNames.add("testLayer");
|
||||
List<String> outNames = net.getUnconnectedOutLayersNames();
|
||||
assertFalse("Model has no output layers", outNames.isEmpty());
|
||||
|
||||
// Forward and retrieve multiple outputs
|
||||
// Forward and retrieve every output blob of the requested layers.
|
||||
List<List<Mat>> outBlobs = new ArrayList<>();
|
||||
net.forwardAndRetrieve(outBlobs, outNames);
|
||||
|
||||
// Verify results
|
||||
assertEquals(1, outBlobs.size());
|
||||
assertEquals(2, outBlobs.get(0).size());
|
||||
|
||||
// Compare results
|
||||
Mat expectedFirst = inp.rowRange(0, 2);
|
||||
Mat expectedSecond = inp.rowRange(2, 4);
|
||||
|
||||
Mat actualFirst = outBlobs.get(0).get(0);
|
||||
Mat actualSecond = outBlobs.get(0).get(1);
|
||||
|
||||
assertEquals(0, Core.norm(expectedFirst, actualFirst, Core.NORM_INF), EPS);
|
||||
assertEquals(0, Core.norm(expectedSecond, actualSecond, Core.NORM_INF), EPS);
|
||||
// One entry per requested layer name, each holding at least one valid blob.
|
||||
assertEquals(outNames.size(), outBlobs.size());
|
||||
for (List<Mat> blobs : outBlobs) {
|
||||
assertFalse(blobs.isEmpty());
|
||||
for (Mat blob : blobs)
|
||||
assertFalse(blob.empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"whitelist":
|
||||
{
|
||||
"dnn_Net": ["setInput", "forward", "setPreferableBackend","getUnconnectedOutLayersNames"],
|
||||
"": ["readNetFromCaffe", "readNetFromTensorflow", "readNetFromTorch",
|
||||
"": ["readNetFromTensorflow", "readNetFromTorch",
|
||||
"readNetFromONNX", "readNetFromTFLite", "readNet", "blobFromImage"]
|
||||
},
|
||||
"namespace_prefix_override":
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"func_arg_fix" : {
|
||||
"Dnn": {
|
||||
"(Net*)readNetFromCaffe:(NSString*)prototxt caffeModel:(NSString*)caffeModel engine:(int)engine" : { "readNetFromCaffe" : {"name" : "readNetFromCaffeFile"} },
|
||||
"(Net*)readNetFromCaffe:(ByteVector*)bufferProto bufferModel:(ByteVector*)bufferModel engine:(int)engine" : { "readNetFromCaffe" : {"name" : "readNetFromCaffeBuffer"} },
|
||||
"(Net*)readNetFromONNX:(NSString*)onnxFile engine:(int)engine" : { "readNetFromONNX" : {"name" : "readNetFromONNXFile"} },
|
||||
"(Net*)readNetFromONNX:(ByteVector*)buffer engine:(int)engine" : { "readNetFromONNX" : {"name" : "readNetFromONNXBuffer"} },
|
||||
"(Net*)readNetFromTensorflow:(NSString*)model config:(NSString*)config engine:(int)engine extraOutputs:(NSArray<NSString*>*)extraOutputs" : { "readNetFromTensorflow" : {"name" : "readNetFromTensorflowFile"} },
|
||||
|
||||
@@ -82,6 +82,13 @@ class dnn_test(NewOpenCVTests):
|
||||
g_dnnBackendsAndTargets = self.initBackendsAndTargets()
|
||||
self.dnnBackendsAndTargets = g_dnnBackendsAndTargets
|
||||
|
||||
def checkIETarget(self, backend, target):
|
||||
# OpenVINO is optional; a target is usable only if its backend lists it.
|
||||
try:
|
||||
return target in cv.dnn.getAvailableTargets(backend)
|
||||
except BaseException:
|
||||
return False
|
||||
|
||||
def initBackendsAndTargets(self):
|
||||
self.dnnBackendsAndTargets = [
|
||||
[cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_CPU],
|
||||
@@ -109,20 +116,6 @@ class dnn_test(NewOpenCVTests):
|
||||
os.environ['OPENCV_TEST_DATA_PATH']],
|
||||
required=required)
|
||||
|
||||
def checkIETarget(self, backend, target):
|
||||
proto = self.find_dnn_file('dnn/layers/layer_convolution.prototxt')
|
||||
model = self.find_dnn_file('dnn/layers/layer_convolution.caffemodel')
|
||||
net = cv.dnn.readNet(proto, model, engine=cv.dnn.ENGINE_CLASSIC)
|
||||
try:
|
||||
net.setPreferableBackend(backend)
|
||||
net.setPreferableTarget(target)
|
||||
inp = np.random.standard_normal([1, 2, 10, 11]).astype(np.float32)
|
||||
net.setInput(inp)
|
||||
net.forward()
|
||||
except BaseException:
|
||||
return False
|
||||
return True
|
||||
|
||||
def test_getAvailableTargets(self):
|
||||
targets = cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_OPENCV)
|
||||
self.assertTrue(cv.dnn.DNN_TARGET_CPU in targets)
|
||||
@@ -219,25 +212,24 @@ class dnn_test(NewOpenCVTests):
|
||||
|
||||
def test_model(self):
|
||||
img_path = self.find_dnn_file("dnn/street.png")
|
||||
weights = self.find_dnn_file("dnn/MobileNetSSD_deploy_19e3ec3.caffemodel", required=False)
|
||||
config = self.find_dnn_file("dnn/MobileNetSSD_deploy_19e3ec3.prototxt", required=False)
|
||||
if weights is None or config is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/MobileNetSSD_deploy_19e3ec3.{prototxt/caffemodel}). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
weights = self.find_dnn_file("dnn/onnx/models/ssd_vgg16.onnx", required=False)
|
||||
if weights is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/onnx/models/ssd_vgg16.onnx). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
|
||||
frame = cv.imread(img_path)
|
||||
model = cv.dnn_DetectionModel(weights, config)
|
||||
model.setInputParams(size=(300, 300), mean=(127.5, 127.5, 127.5), scale=1.0/127.5)
|
||||
model = cv.dnn_DetectionModel(weights)
|
||||
model.setInputParams(size=(300, 300), mean=(0, 0, 0), scale=1.0, swapRB=False)
|
||||
|
||||
iouDiff = 0.05
|
||||
confThreshold = 0.0001
|
||||
confThreshold = 0.3
|
||||
nmsThreshold = 0
|
||||
scoreDiff = 1.1e-3
|
||||
scoreDiff = 5e-3
|
||||
|
||||
classIds, confidences, boxes = model.detect(frame, confThreshold, nmsThreshold)
|
||||
|
||||
refClassIds = (7, 15)
|
||||
refConfidences = (0.9998, 0.8793)
|
||||
refBoxes = ((328, 238, 85, 102), (101, 188, 34, 138))
|
||||
refClassIds = (37,)
|
||||
refConfidences = (0.8196,)
|
||||
refBoxes = ((331, 233, 85, 107),)
|
||||
|
||||
normAssertDetections(self, refClassIds, refConfidences, refBoxes,
|
||||
classIds, confidences, boxes,confThreshold, scoreDiff, iouDiff)
|
||||
@@ -251,14 +243,13 @@ class dnn_test(NewOpenCVTests):
|
||||
|
||||
def test_classification_model(self):
|
||||
img_path = self.find_dnn_file("dnn/googlenet_0.png")
|
||||
weights = self.find_dnn_file("dnn/squeezenet_v1.1.caffemodel", required=False)
|
||||
config = self.find_dnn_file("dnn/squeezenet_v1.1.prototxt")
|
||||
weights = self.find_dnn_file("dnn/squeezenet_v1.1.onnx", required=False)
|
||||
ref = np.load(self.find_dnn_file("dnn/squeezenet_v1.1_prob.npy"))
|
||||
if weights is None or config is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/squeezenet_v1.1.{prototxt/caffemodel}). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
if weights is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/squeezenet_v1.1.onnx). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
|
||||
frame = cv.imread(img_path)
|
||||
model = cv.dnn_ClassificationModel(config, weights)
|
||||
model = cv.dnn_ClassificationModel(weights)
|
||||
model.setInputSize(227, 227)
|
||||
model.setInputCrop(True)
|
||||
|
||||
@@ -323,54 +314,6 @@ class dnn_test(NewOpenCVTests):
|
||||
normAssertDetections(self, refClassIds, refScores, refBoxes, testClassIds,
|
||||
testScores, testBoxes, 0.5)
|
||||
|
||||
def test_async(self):
|
||||
# bug: https://github.com/opencv/opencv/issues/26376
|
||||
raise unittest.SkipTest("The new dnn engine does not support async inference")
|
||||
|
||||
timeout = 10*1000*10**6 # in nanoseconds (10 sec)
|
||||
proto = self.find_dnn_file('dnn/layers/layer_convolution.prototxt')
|
||||
model = self.find_dnn_file('dnn/layers/layer_convolution.caffemodel')
|
||||
if proto is None or model is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/layers/layer_convolution.{prototxt/caffemodel}). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
|
||||
print('\n')
|
||||
for backend, target in self.dnnBackendsAndTargets:
|
||||
if backend != cv.dnn.DNN_BACKEND_INFERENCE_ENGINE:
|
||||
continue
|
||||
|
||||
printParams(backend, target)
|
||||
|
||||
netSync = cv.dnn.readNet(proto, model, engine=cv.dnn.ENGINE_CLASSIC)
|
||||
netSync.setPreferableBackend(backend)
|
||||
netSync.setPreferableTarget(target)
|
||||
|
||||
netAsync = cv.dnn.readNet(proto, model)
|
||||
netAsync.setPreferableBackend(backend)
|
||||
netAsync.setPreferableTarget(target)
|
||||
|
||||
# Generate inputs
|
||||
numInputs = 10
|
||||
inputs = []
|
||||
for _ in range(numInputs):
|
||||
inputs.append(np.random.standard_normal([2, 6, 75, 113]).astype(np.float32))
|
||||
|
||||
# Run synchronously
|
||||
refs = []
|
||||
for i in range(numInputs):
|
||||
netSync.setInput(inputs[i])
|
||||
refs.append(netSync.forward())
|
||||
|
||||
# Run asynchronously. To make test more robust, process inputs in the reversed order.
|
||||
outs = []
|
||||
for i in reversed(range(numInputs)):
|
||||
netAsync.setInput(inputs[i])
|
||||
outs.insert(0, netAsync.forwardAsync())
|
||||
|
||||
for i in reversed(range(numInputs)):
|
||||
ret, result = outs[i].get(timeoutNs=float(timeout))
|
||||
self.assertTrue(ret)
|
||||
normAssert(self, refs[i], result, 'Index: %d' % i, 1e-10)
|
||||
|
||||
def test_nms(self):
|
||||
confs = (1, 1)
|
||||
rects = ((0, 0, 0.4, 0.4), (0, 0, 0.2, 0.4)) # 0.5 overlap
|
||||
@@ -401,51 +344,8 @@ class dnn_test(NewOpenCVTests):
|
||||
return [inputs[0][:,:,self.ystart:self.yend,self.xstart:self.xend]]
|
||||
|
||||
cv.dnn_registerLayer('CropCaffe', CropLayer)
|
||||
proto = '''
|
||||
name: "TestCrop"
|
||||
input: "input"
|
||||
input_shape
|
||||
{
|
||||
dim: 1
|
||||
dim: 2
|
||||
dim: 5
|
||||
dim: 5
|
||||
}
|
||||
input: "roi"
|
||||
input_shape
|
||||
{
|
||||
dim: 1
|
||||
dim: 2
|
||||
dim: 3
|
||||
dim: 3
|
||||
}
|
||||
layer {
|
||||
name: "Crop"
|
||||
type: "CropCaffe"
|
||||
bottom: "input"
|
||||
bottom: "roi"
|
||||
top: "Crop"
|
||||
}'''
|
||||
|
||||
net = cv.dnn.readNetFromCaffe(bytearray(proto.encode()))
|
||||
for backend, target in self.dnnBackendsAndTargets:
|
||||
if backend != cv.dnn.DNN_BACKEND_OPENCV:
|
||||
continue
|
||||
|
||||
printParams(backend, target)
|
||||
|
||||
net.setPreferableBackend(backend)
|
||||
net.setPreferableTarget(target)
|
||||
src_shape = [1, 2, 5, 5]
|
||||
dst_shape = [1, 2, 3, 3]
|
||||
inp = np.arange(0, np.prod(src_shape), dtype=np.float32).reshape(src_shape)
|
||||
roi = np.empty(dst_shape, dtype=np.float32)
|
||||
net.setInput(inp, "input")
|
||||
net.setInput(roi, "roi")
|
||||
out = net.forward()
|
||||
ref = inp[:, :, 1:4, 1:4]
|
||||
normAssert(self, out, ref)
|
||||
|
||||
# Skipped: Requires ONNX custom layer multi-input support and Python binding fixes for Net.connect (see #26200).
|
||||
cv.dnn_unregisterLayer('CropCaffe')
|
||||
|
||||
# check that dnn module can work with 3D tensor as input for network
|
||||
|
||||
@@ -33,7 +33,7 @@ assert(not args.quantize or not args.fp16)
|
||||
dtype = tf.float16 if args.fp16 else tf.float32
|
||||
|
||||
################################################################################
|
||||
cvNet = cv.dnn.readNetFromCaffe(args.proto, args.model)
|
||||
cvNet = cv.dnn.readNet(args.proto, args.model)
|
||||
|
||||
def dnnLayer(name):
|
||||
return cvNet.getLayer(long(cvNet.getLayerId(name)))
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
// Recommends run this performance test via
|
||||
// ./bin/opencv_perf_dnn 2> /dev/null | grep "PERFSTAT" -A 3
|
||||
// because whole output includes Caffe's logs.
|
||||
//
|
||||
// Note: Be sure that interesting version of Caffe was linked.
|
||||
//
|
||||
// How to build Intel-Caffe with MKLDNN backend
|
||||
// ============================================
|
||||
// mkdir build && cd build
|
||||
// cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
// -DUSE_MKLDNN_AS_DEFAULT_ENGINE=ON \
|
||||
// -DUSE_MKL2017_AS_DEFAULT_ENGINE=OFF \
|
||||
// -DCPU_ONLY=ON \
|
||||
// -DCMAKE_INSTALL_PREFIX=/usr/local .. && make -j8
|
||||
// sudo make install
|
||||
//
|
||||
// In case of problems with cublas_v2.h at include/caffe/util/device_alternate.hpp: add line
|
||||
// #define CPU_ONLY
|
||||
// before the first line
|
||||
// #ifdef CPU_ONLY // CPU-only Caffe.
|
||||
|
||||
#if defined(HAVE_CAFFE) || defined(HAVE_CLCAFFE)
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
#include <iostream>
|
||||
#include <caffe/caffe.hpp>
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
static caffe::Net<float>* initNet(std::string proto, std::string weights)
|
||||
{
|
||||
proto = findDataFile(proto);
|
||||
weights = findDataFile(weights, false);
|
||||
|
||||
#ifdef HAVE_CLCAFFE
|
||||
caffe::Caffe::set_mode(caffe::Caffe::GPU);
|
||||
caffe::Caffe::SetDevice(0);
|
||||
|
||||
caffe::Net<float>* net =
|
||||
new caffe::Net<float>(proto, caffe::TEST, caffe::Caffe::GetDefaultDevice());
|
||||
#else
|
||||
caffe::Caffe::set_mode(caffe::Caffe::CPU);
|
||||
|
||||
caffe::Net<float>* net = new caffe::Net<float>(proto, caffe::TEST);
|
||||
#endif
|
||||
|
||||
net->CopyTrainedLayersFrom(weights);
|
||||
|
||||
caffe::Blob<float>* input = net->input_blobs()[0];
|
||||
|
||||
CV_Assert(input->num() == 1);
|
||||
CV_Assert(input->channels() == 3);
|
||||
|
||||
Mat inputMat(input->height(), input->width(), CV_32FC3, (char*)input->cpu_data());
|
||||
randu(inputMat, 0.0f, 1.0f);
|
||||
|
||||
net->Forward();
|
||||
return net;
|
||||
}
|
||||
|
||||
PERF_TEST(AlexNet_caffe, CaffePerfTest)
|
||||
{
|
||||
caffe::Net<float>* net = initNet("dnn/bvlc_alexnet.prototxt",
|
||||
"dnn/bvlc_alexnet.caffemodel");
|
||||
TEST_CYCLE() net->Forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(GoogLeNet_caffe, CaffePerfTest)
|
||||
{
|
||||
caffe::Net<float>* net = initNet("dnn/bvlc_googlenet.prototxt",
|
||||
"dnn/bvlc_googlenet.caffemodel");
|
||||
TEST_CYCLE() net->Forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(ResNet50_caffe, CaffePerfTest)
|
||||
{
|
||||
caffe::Net<float>* net = initNet("dnn/ResNet-50-deploy.prototxt",
|
||||
"dnn/ResNet-50-model.caffemodel");
|
||||
TEST_CYCLE() net->Forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(SqueezeNet_v1_1_caffe, CaffePerfTest)
|
||||
{
|
||||
caffe::Net<float>* net = initNet("dnn/squeezenet_v1.1.prototxt",
|
||||
"dnn/squeezenet_v1.1.caffemodel");
|
||||
TEST_CYCLE() net->Forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(MobileNet_SSD, CaffePerfTest)
|
||||
{
|
||||
caffe::Net<float>* net = initNet("dnn/MobileNetSSD_deploy_19e3ec3.prototxt",
|
||||
"dnn/MobileNetSSD_deploy_19e3ec3.caffemodel");
|
||||
TEST_CYCLE() net->Forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif // HAVE_CAFFE
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "opencv2/core/ocl.hpp"
|
||||
|
||||
#include "opencv2/dnn/shape_utils.hpp"
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
|
||||
#include "../test/test_common.hpp"
|
||||
|
||||
@@ -96,17 +97,17 @@ public:
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, AlexNet)
|
||||
{
|
||||
processNet("dnn/bvlc_alexnet.caffemodel", "dnn/bvlc_alexnet.prototxt", cv::Size(227, 227));
|
||||
processNet("dnn/onnx/models/alexnet.onnx", "", cv::Size(227, 227));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, GoogLeNet)
|
||||
{
|
||||
processNet("dnn/bvlc_googlenet.caffemodel", "dnn/bvlc_googlenet.prototxt", cv::Size(224, 224));
|
||||
processNet("dnn/onnx/models/googlenet.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, ResNet_50)
|
||||
{
|
||||
processNet("dnn/ResNet-50-model.caffemodel", "dnn/ResNet-50-deploy.prototxt", cv::Size(224, 224));
|
||||
processNet("dnn/onnx/models/resnet50v1.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, ResNet_18_v1_ONNX)
|
||||
@@ -131,7 +132,7 @@ PERF_TEST_P_(DNNTestNetwork, ResNet50_QDQ_ONNX)
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, SqueezeNet_v1_1)
|
||||
{
|
||||
processNet("dnn/squeezenet_v1.1.caffemodel", "dnn/squeezenet_v1.1.prototxt", cv::Size(227, 227));
|
||||
processNet("dnn/onnx/models/squeezenet.onnx", "", cv::Size(227, 227));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, Inception_5h)
|
||||
@@ -144,12 +145,28 @@ PERF_TEST_P_(DNNTestNetwork, SSD)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DEBUG_VERYLONG);
|
||||
|
||||
processNet("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel", "dnn/ssd_vgg16.prototxt", cv::Size(300, 300));
|
||||
// The Caffe-SSD specific handling lives in the new engine importer only;
|
||||
// the classic importer can no longer load this model.
|
||||
auto engine_forced = static_cast<dnn::EngineType>(
|
||||
utils::getConfigurationParameterSizeT("OPENCV_FORCE_DNN_ENGINE", dnn::ENGINE_AUTO));
|
||||
if (engine_forced == dnn::ENGINE_CLASSIC)
|
||||
throw SkipTestException("SSD_VGG16 is supported on the new DNN engine only");
|
||||
|
||||
processNet("dnn/onnx/models/ssd_vgg16.onnx", "", cv::Size(300, 300));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_Caffe)
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_v1_ONNX)
|
||||
{
|
||||
processNet("dnn/MobileNetSSD_deploy_19e3ec3.caffemodel", "dnn/MobileNetSSD_deploy_19e3ec3.prototxt", cv::Size(300, 300));
|
||||
// Dynamic-shape preprocessing in this model needs the new engine; OpenVINO uses the classic one.
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
// This model expects a uint8 NHWC image as input.
|
||||
Mat image(cv::Size(300, 300), CV_8UC3);
|
||||
randu(image, 0, 255);
|
||||
int imsize[] = {1, image.rows, image.cols, 3};
|
||||
Mat input(4, imsize, CV_8U, image.data);
|
||||
processNet("dnn/onnx/models/ssd_mobilenet_v1_12.onnx", "", input);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_v1_TensorFlow)
|
||||
@@ -162,18 +179,9 @@ PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_v2_TensorFlow)
|
||||
processNet("dnn/ssd_mobilenet_v2_coco_2018_03_29.pb", "ssd_mobilenet_v2_coco_2018_03_29.pbtxt", cv::Size(300, 300));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_v1_ONNX)
|
||||
{
|
||||
Mat image(cv::Size(300, 300), CV_8UC3);
|
||||
randu(image, 0, 255);
|
||||
int imsize[] = {1, image.rows, image.cols, 3};
|
||||
Mat input(4, imsize, CV_8U, image.data);
|
||||
processNet("dnn/onnx/models/ssd_mobilenet_v1_12.onnx", "", input);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, DenseNet_121)
|
||||
{
|
||||
processNet("dnn/DenseNet_121.caffemodel", "dnn/DenseNet_121.prototxt", cv::Size(224, 224));
|
||||
processNet("dnn/onnx/models/densenet121.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
|
||||
@@ -184,7 +192,8 @@ PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
|
||||
throw SkipTestException("");
|
||||
// The same .caffemodel but modified .prototxt
|
||||
// See https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/src/openpose/pose/poseParameters.cpp
|
||||
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi_faster_4_stages.prototxt", cv::Size(368, 368));
|
||||
// processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi_faster_4_stages.prototxt", cv::Size(368, 368));
|
||||
processNet("dnn/onnx/models/openpose_pose_mpi.onnx", "", cv::Size(368, 368));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, Inception_v2_SSD_TensorFlow)
|
||||
|
||||
@@ -1,828 +0,0 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "../net_impl.hpp"
|
||||
|
||||
#ifdef HAVE_PROTOBUF
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/reflection.h>
|
||||
#include "caffe_io.hpp"
|
||||
#endif
|
||||
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
#include <opencv2/core/utils/fp_control_utils.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
|
||||
#ifdef HAVE_PROTOBUF
|
||||
using ::google::protobuf::RepeatedFieldRef;
|
||||
using ::google::protobuf::Message;
|
||||
using ::google::protobuf::Descriptor;
|
||||
using ::google::protobuf::FieldDescriptor;
|
||||
using ::google::protobuf::Reflection;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
static cv::String toString(const T &v)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static inline
|
||||
MatShape parseBlobShape(const caffe::BlobShape& _input_shape)
|
||||
{
|
||||
MatShape shape;
|
||||
for (int i = 0; i < _input_shape.dim_size(); i++)
|
||||
{
|
||||
shape.push_back((int)_input_shape.dim(i));
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
class CaffeImporter
|
||||
{
|
||||
FPDenormalsIgnoreHintScope fp_denormals_ignore_scope;
|
||||
|
||||
caffe::NetParameter net;
|
||||
caffe::NetParameter netBinary;
|
||||
|
||||
public:
|
||||
|
||||
CaffeImporter(const char *prototxt, const char *caffeModel)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
ReadNetParamsFromTextFileOrDie(prototxt, &net);
|
||||
|
||||
if (caffeModel && caffeModel[0])
|
||||
ReadNetParamsFromBinaryFileOrDie(caffeModel, &netBinary);
|
||||
}
|
||||
|
||||
CaffeImporter(const char *dataProto, size_t lenProto,
|
||||
const char *dataModel, size_t lenModel)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
ReadNetParamsFromTextBufferOrDie(dataProto, lenProto, &net);
|
||||
|
||||
if (dataModel != NULL && lenModel > 0)
|
||||
ReadNetParamsFromBinaryBufferOrDie(dataModel, lenModel, &netBinary);
|
||||
}
|
||||
|
||||
void extractCustomParams(const google::protobuf::UnknownFieldSet& unknownFields, cv::dnn::LayerParams ¶ms)
|
||||
{
|
||||
const int numFields = unknownFields.field_count();
|
||||
for (int i = 0; i < numFields; ++i)
|
||||
{
|
||||
const google::protobuf::UnknownField& field = unknownFields.field(i);
|
||||
CV_Assert(field.type() == google::protobuf::UnknownField::TYPE_GROUP);
|
||||
CV_CheckGE(field.group().field_count(), 2, "UnknownField should have at least 2 items: name and value");
|
||||
std::string fieldName(field.group().field(0).length_delimited());
|
||||
std::string fieldValue(field.group().field(1).length_delimited());
|
||||
params.set(fieldName, fieldValue);
|
||||
}
|
||||
}
|
||||
|
||||
void addParam(const Message &msg, const FieldDescriptor *field, cv::dnn::LayerParams ¶ms)
|
||||
{
|
||||
const Reflection *refl = msg.GetReflection();
|
||||
int type = field->cpp_type();
|
||||
bool isRepeated = field->is_repeated();
|
||||
const std::string name(field->name());
|
||||
|
||||
#define SET_UP_FILED(getter, arrayConstr, gtype) \
|
||||
if (isRepeated) { \
|
||||
const RepeatedFieldRef<gtype> v = refl->GetRepeatedFieldRef<gtype>(msg, field); \
|
||||
params.set(name, DictValue::arrayConstr(v.begin(), (int)v.size())); \
|
||||
} \
|
||||
else { \
|
||||
params.set(name, refl->getter(msg, field)); \
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
SET_UP_FILED(GetInt32, arrayInt, ::google::protobuf::int32);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
SET_UP_FILED(GetUInt32, arrayInt, ::google::protobuf::uint32);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
SET_UP_FILED(GetInt32, arrayInt, ::google::protobuf::int64);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
SET_UP_FILED(GetUInt32, arrayInt, ::google::protobuf::uint64);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
SET_UP_FILED(GetBool, arrayInt, bool);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
SET_UP_FILED(GetDouble, arrayReal, double);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
SET_UP_FILED(GetFloat, arrayReal, float);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
if (isRepeated) {
|
||||
const RepeatedFieldRef<std::string> v = refl->GetRepeatedFieldRef<std::string>(msg, field);
|
||||
params.set(name, DictValue::arrayString(v.begin(), (int)v.size()));
|
||||
}
|
||||
else {
|
||||
params.set(name, refl->GetString(msg, field));
|
||||
}
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
if (isRepeated) {
|
||||
int size = refl->FieldSize(msg, field);
|
||||
std::vector<cv::String> buf(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
buf[i] = refl->GetRepeatedEnum(msg, field, i)->name();
|
||||
params.set(name, DictValue::arrayString(buf.begin(), size));
|
||||
}
|
||||
else {
|
||||
params.set(name, std::string(refl->GetEnum(msg, field)->name()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsError, "Unknown type \"" + String(field->type_name()) + "\" in prototxt");
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool ends_with_param(const std::string &str)
|
||||
{
|
||||
static const std::string _param("_param");
|
||||
return (str.size() >= _param.size()) && str.compare(str.size() - _param.size(), _param.size(), _param) == 0;
|
||||
}
|
||||
|
||||
template<class MSG>
|
||||
typename std::enable_if<std::is_base_of<Message, MSG>::value, void>::type
|
||||
extractLayerParams(const MSG &msg, cv::dnn::LayerParams ¶ms, bool isInternal = false)
|
||||
{
|
||||
const Descriptor *msgDesc = msg.GetDescriptor();
|
||||
const Reflection *msgRefl = msg.GetReflection();
|
||||
|
||||
for (int fieldId = 0; fieldId < msgDesc->field_count(); fieldId++)
|
||||
{
|
||||
const FieldDescriptor *fd = msgDesc->field(fieldId);
|
||||
|
||||
if (!isInternal && !ends_with_param(std::string(fd->name())))
|
||||
continue;
|
||||
|
||||
const google::protobuf::UnknownFieldSet& unknownFields = msgRefl->GetUnknownFields(msg);
|
||||
bool hasData = fd->is_required() ||
|
||||
(!fd->is_repeated() && !fd->is_required() && msgRefl->HasField(msg, fd)) ||
|
||||
(fd->is_repeated() && msgRefl->FieldSize(msg, fd) > 0) ||
|
||||
!unknownFields.empty();
|
||||
if (!hasData)
|
||||
continue;
|
||||
|
||||
extractCustomParams(unknownFields, params);
|
||||
if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE)
|
||||
{
|
||||
if (fd->is_repeated()) //Extract only first item!
|
||||
extractLayerParams(msgRefl->GetRepeatedMessage(msg, fd, 0), params, true);
|
||||
else
|
||||
extractLayerParams(msgRefl->GetMessage(msg, fd), params, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
addParam(msg, fd, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class MSG>
|
||||
typename std::enable_if<!std::is_base_of<Message, MSG>::value, void>::type
|
||||
extractLayerParams(const MSG &msg, cv::dnn::LayerParams ¶ms, bool isInternal = false)
|
||||
{
|
||||
CV_Error(Error::StsError, "DNN/CAFFE: do not have your message be a MessageLite");
|
||||
}
|
||||
|
||||
void blobShapeFromProto(const caffe::BlobProto &pbBlob, MatShape& shape)
|
||||
{
|
||||
shape.clear();
|
||||
if (pbBlob.has_num() || pbBlob.has_channels() || pbBlob.has_height() || pbBlob.has_width())
|
||||
{
|
||||
shape.push_back(pbBlob.num());
|
||||
shape.push_back(pbBlob.channels());
|
||||
shape.push_back(pbBlob.height());
|
||||
shape.push_back(pbBlob.width());
|
||||
}
|
||||
else if (pbBlob.has_shape())
|
||||
{
|
||||
shape = parseBlobShape(pbBlob.shape());
|
||||
}
|
||||
else
|
||||
shape.resize(1, 1); // Is a scalar.
|
||||
}
|
||||
|
||||
template<class BLOB_PROTO>
|
||||
typename std::enable_if<std::is_base_of<Message, BLOB_PROTO>::value, void>::type
|
||||
AssertBlobProtoIsFloat(const BLOB_PROTO &pbBlob) {
|
||||
CV_DbgAssert(pbBlob.GetDescriptor()->FindFieldByLowercaseName("data")->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT);
|
||||
}
|
||||
|
||||
template<class BLOB_PROTO>
|
||||
typename std::enable_if<!std::is_base_of<Message, BLOB_PROTO>::value, void>::type
|
||||
AssertBlobProtoIsFloat(const BLOB_PROTO &pbBlob) {
|
||||
CV_Error(Error::StsError, "DNN/CAFFE: do not have your message be a MessageLite");
|
||||
}
|
||||
|
||||
void blobFromProto(const caffe::BlobProto &pbBlob, cv::Mat &dstBlob)
|
||||
{
|
||||
MatShape shape;
|
||||
blobShapeFromProto(pbBlob, shape);
|
||||
|
||||
dstBlob.create((int)shape.size(), &shape[0], CV_32F);
|
||||
if (pbBlob.data_size())
|
||||
{
|
||||
// Single precision floats.
|
||||
CV_Assert(pbBlob.data_size() == (int)dstBlob.total());
|
||||
|
||||
AssertBlobProtoIsFloat(pbBlob);
|
||||
Mat(dstBlob.size, CV_32F, (void*)pbBlob.data().data()).copyTo(dstBlob);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(pbBlob.has_raw_data());
|
||||
const std::string& raw_data = pbBlob.raw_data();
|
||||
if (pbBlob.raw_data_type() == caffe::FLOAT16)
|
||||
{
|
||||
// Half precision floats.
|
||||
CV_Assert(raw_data.size() / 2 == (int)dstBlob.total());
|
||||
|
||||
Mat halfs((int)shape.size(), &shape[0], CV_16FC1, (void*)raw_data.c_str());
|
||||
halfs.convertTo(dstBlob, CV_32F);
|
||||
}
|
||||
else if (pbBlob.raw_data_type() == caffe::FLOAT)
|
||||
{
|
||||
CV_Assert(raw_data.size() / 4 == (int)dstBlob.total());
|
||||
Mat((int)shape.size(), &shape[0], CV_32FC1, (void*)raw_data.c_str()).copyTo(dstBlob);
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsNotImplemented, "Unexpected blob data type");
|
||||
}
|
||||
}
|
||||
|
||||
void extractBinaryLayerParams(const caffe::LayerParameter& layer, LayerParams& layerParams)
|
||||
{
|
||||
const std::string &name = layer.name();
|
||||
|
||||
int li;
|
||||
for (li = 0; li != netBinary.layer_size(); li++)
|
||||
{
|
||||
const caffe::LayerParameter& binLayer = netBinary.layer(li);
|
||||
// Break if the layer name is the same and the blobs are not cleared
|
||||
if (binLayer.name() == name && binLayer.blobs_size() != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (li == netBinary.layer_size())
|
||||
return;
|
||||
|
||||
caffe::LayerParameter* binLayer = netBinary.mutable_layer(li);
|
||||
const int numBlobs = binLayer->blobs_size();
|
||||
std::vector<caffe::BlobProto*> blobs(numBlobs);
|
||||
binLayer->mutable_blobs()->ExtractSubrange(0, numBlobs, blobs.data());
|
||||
layerParams.blobs.resize(numBlobs);
|
||||
for (int bi = 0; bi < numBlobs; bi++)
|
||||
{
|
||||
blobFromProto(*blobs[bi], layerParams.blobs[bi]);
|
||||
delete blobs[bi];
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<Layer> addLayer(Net& dstNet,
|
||||
const String& type,
|
||||
const String& name,
|
||||
LayerParams& layerParams,
|
||||
const std::vector<String>& inputs,
|
||||
const std::vector<String>& outputs)
|
||||
{
|
||||
layerParams.type = type;
|
||||
layerParams.name = name;
|
||||
Ptr<Layer> layer = LayerFactory::createLayerInstance(type, layerParams);
|
||||
if (!layer) {
|
||||
CV_Error(Error::StsError, "Can't create layer " + name + " with type " + type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const String& inputName : inputs)
|
||||
layer->inputs.push_back(dstNet.getArg(inputName));
|
||||
for (const String& outputName : outputs)
|
||||
layer->outputs.push_back(dstNet.getArg(outputName));
|
||||
layer->netimpl = dstNet.getImpl();
|
||||
CV_Assert(dstNet.getImpl()->dump_indent == 3);
|
||||
return layer;
|
||||
}
|
||||
|
||||
struct BlobNote
|
||||
{
|
||||
BlobNote(const std::string &_name, int _layerId, int _outNum) :
|
||||
name(_name), layerId(_layerId), outNum(_outNum) {}
|
||||
|
||||
std::string name;
|
||||
int layerId, outNum;
|
||||
};
|
||||
|
||||
std::vector<BlobNote> addedBlobs;
|
||||
std::map<String, int> layerCounter;
|
||||
|
||||
void populateNet(Net dstNet, bool newEngine)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
int layersSize = net.layer_size();
|
||||
layerCounter.clear();
|
||||
|
||||
// OLD ENGINE
|
||||
if(!newEngine)
|
||||
{
|
||||
addedBlobs.clear();
|
||||
addedBlobs.reserve(layersSize + 1);
|
||||
}
|
||||
std::vector<String> netInputs(net.input_size());
|
||||
std::vector<MatShape> inp_shapes;
|
||||
|
||||
// NEW ENGINE
|
||||
Net::Impl* netImpl = dstNet.getImpl();
|
||||
std::vector<Ptr<Layer>> curr_prog;
|
||||
std::vector<Arg> modelInputs, modelOutputs;
|
||||
|
||||
{
|
||||
int net_input_size = net.input_size();
|
||||
for (int inNum = 0; inNum < net_input_size; inNum++)
|
||||
{
|
||||
if (newEngine)
|
||||
{
|
||||
modelInputs.push_back(netImpl->newArg(net.input(inNum), DNN_ARG_INPUT));
|
||||
netImpl->args.at(modelInputs.back().idx).type = CV_32F;
|
||||
}
|
||||
else
|
||||
{
|
||||
addedBlobs.push_back(BlobNote(net.input(inNum), 0, inNum));
|
||||
netInputs[inNum] = net.input(inNum);
|
||||
}
|
||||
}
|
||||
|
||||
if (net.input_dim_size() > 0) // deprecated in Caffe proto
|
||||
{
|
||||
int net_input_dim_size = net.input_dim_size();
|
||||
CV_Check(net_input_dim_size, net_input_dim_size % 4 == 0, "");
|
||||
CV_CheckEQ(net_input_dim_size, net_input_size * 4, "");
|
||||
for (int inp_id = 0; inp_id < net_input_size; inp_id++)
|
||||
{
|
||||
int dim = inp_id * 4;
|
||||
MatShape shape(4);
|
||||
shape[0] = net.input_dim(dim);
|
||||
shape[1] = net.input_dim(dim+1);
|
||||
shape[2] = net.input_dim(dim+2);
|
||||
shape[3] = net.input_dim(dim+3);
|
||||
if (newEngine)
|
||||
netImpl->args.at(modelInputs[inp_id].idx).shape = shape;
|
||||
else
|
||||
inp_shapes.push_back(shape);
|
||||
}
|
||||
}
|
||||
else if (net.input_shape_size() > 0) // deprecated in Caffe proto
|
||||
{
|
||||
int net_input_shape_size = net.input_shape_size();
|
||||
CV_CheckEQ(net_input_shape_size, net_input_size, "");
|
||||
for (int inp_id = 0; inp_id < net_input_shape_size; inp_id++)
|
||||
{
|
||||
MatShape shape = parseBlobShape(net.input_shape(inp_id));
|
||||
if (newEngine)
|
||||
netImpl->args.at(modelInputs[inp_id].idx).shape = shape;
|
||||
else
|
||||
inp_shapes.push_back(shape);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int inp_id = 0; inp_id < net_input_size; inp_id++)
|
||||
{
|
||||
MatShape shape; // empty
|
||||
if (newEngine)
|
||||
netImpl->args.at(modelInputs[inp_id].idx).shape = shape;
|
||||
else
|
||||
inp_shapes.push_back(shape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newEngine && net.layer(layersSize - 1).type() == "Silence")
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Caffe parser: Silence layer was ignored");
|
||||
layersSize--;
|
||||
}
|
||||
|
||||
for (int li = 0; li < layersSize; li++)
|
||||
{
|
||||
const caffe::LayerParameter &layer = net.layer(li);
|
||||
String name = layer.name();
|
||||
String type = layer.type();
|
||||
LayerParams layerParams;
|
||||
|
||||
extractLayerParams(layer, layerParams);
|
||||
extractBinaryLayerParams(layer, layerParams);
|
||||
|
||||
if (newEngine && li == layersSize - 1)
|
||||
{
|
||||
for (int outNum = 0; outNum < layer.top_size(); outNum++)
|
||||
modelOutputs.push_back(netImpl->newArg(layer.top(outNum), DNN_ARG_OUTPUT));
|
||||
}
|
||||
|
||||
int repetitions = layerCounter[name]++;
|
||||
if (repetitions)
|
||||
name += String("_") + toString(repetitions);
|
||||
|
||||
if (type == "Input")
|
||||
{
|
||||
for (int outNum = 0; outNum < layer.top_size(); outNum++)
|
||||
{
|
||||
if (newEngine)
|
||||
{
|
||||
modelInputs.push_back(netImpl->newArg(layer.top(outNum), DNN_ARG_INPUT));
|
||||
netImpl->args.at(modelInputs.back().idx).type = CV_32F;
|
||||
}
|
||||
else
|
||||
{
|
||||
addOutput(layer, 0, outNum);
|
||||
addedBlobs.back().outNum = netInputs.size();
|
||||
netInputs.push_back(addedBlobs.back().name);
|
||||
}
|
||||
}
|
||||
if (layer.has_input_param())
|
||||
{
|
||||
const caffe::InputParameter &inputParameter = layer.input_param();
|
||||
int input_shape_size = inputParameter.shape_size();
|
||||
CV_CheckEQ(input_shape_size, layer.top_size(), "");
|
||||
for (int inp_id = 0; inp_id < input_shape_size; inp_id++)
|
||||
{
|
||||
MatShape shape = parseBlobShape(inputParameter.shape(inp_id));
|
||||
if (newEngine)
|
||||
{
|
||||
int inputIdx = modelInputs.size() - input_shape_size + inp_id;
|
||||
netImpl->args.at(modelInputs[inputIdx].idx).shape = shape;
|
||||
}
|
||||
else
|
||||
{
|
||||
inp_shapes.push_back(shape);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (type == "BatchNorm")
|
||||
{
|
||||
if (!layerParams.get<bool>("use_global_stats", true))
|
||||
{
|
||||
CV_Assert_N(layer.bottom_size() == 1, layer.top_size() == 1);
|
||||
|
||||
LayerParams mvnParams;
|
||||
mvnParams.set("eps", layerParams.get<float>("eps", 1e-5));
|
||||
std::string mvnName = name + "/mvn";
|
||||
|
||||
int repetitions = layerCounter[mvnName]++;
|
||||
if (repetitions)
|
||||
mvnName += String("_") + toString(repetitions);
|
||||
|
||||
if (newEngine)
|
||||
{
|
||||
Ptr<Layer> netLayer = addLayer(
|
||||
dstNet, "MVN", mvnName, mvnParams,
|
||||
{layer.bottom(0)},
|
||||
{layer.top(0)});
|
||||
curr_prog.push_back(netLayer);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
int mvnId = dstNet.addLayer(mvnName, "MVN", mvnParams);
|
||||
addInput(layer.bottom(0), mvnId, 0, dstNet);
|
||||
addOutput(layer, mvnId, 0);
|
||||
net.mutable_layer(li)->set_bottom(0, layer.top(0));
|
||||
layerParams.blobs[0].setTo(0); // mean
|
||||
layerParams.blobs[1].setTo(1); // std
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == "Axpy")
|
||||
{
|
||||
CV_Assert_N(layer.bottom_size() == 3, layer.top_size() == 1);
|
||||
|
||||
std::string scaleName = name + "/scale";
|
||||
int repetitions = layerCounter[scaleName]++;
|
||||
if (repetitions) {
|
||||
scaleName += String("_") + toString(repetitions);
|
||||
}
|
||||
|
||||
LayerParams scaleParams;
|
||||
scaleParams.set("axis", 1);
|
||||
scaleParams.set("has_bias", false);
|
||||
|
||||
if (newEngine)
|
||||
{
|
||||
std::string intermediateTensor = scaleName + "_intermediate_output";
|
||||
Ptr<Layer> netLayerScale= addLayer(
|
||||
dstNet, "Scale", scaleName, scaleParams,
|
||||
{layer.bottom(2), layer.bottom(0)},
|
||||
{intermediateTensor});
|
||||
curr_prog.push_back(netLayerScale);
|
||||
|
||||
LayerParams eltwiseParams;
|
||||
Ptr<Layer> netLayerEltwise = addLayer(
|
||||
dstNet, "Eltwise", name, eltwiseParams,
|
||||
{intermediateTensor, layer.bottom(1)},
|
||||
{layer.top(0)});
|
||||
curr_prog.push_back(netLayerEltwise);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
int scaleId = dstNet.addLayer(scaleName, "Scale", scaleParams);
|
||||
addInput(layer.bottom(2), scaleId, 0, dstNet);
|
||||
addInput(layer.bottom(0), scaleId, 1, dstNet);
|
||||
addOutput(layer, scaleId, 0);
|
||||
net.mutable_layer(li)->set_bottom(0, layer.top(0));
|
||||
net.mutable_layer(li)->mutable_bottom()->RemoveLast();
|
||||
type = "Eltwise";
|
||||
}
|
||||
}
|
||||
else if (type == "Resample")
|
||||
{
|
||||
CV_Assert(layer.bottom_size() == 1 || layer.bottom_size() == 2);
|
||||
type = "Resize";
|
||||
String interp = toLowerCase(layerParams.get<String>("type"));
|
||||
layerParams.set("interpolation", interp == "linear" ? "bilinear" : interp);
|
||||
|
||||
if (layerParams.has("factor"))
|
||||
{
|
||||
float factor = layerParams.get<float>("factor");
|
||||
CV_Assert(layer.bottom_size() != 2 || factor == 1.0);
|
||||
layerParams.set("zoom_factor", factor);
|
||||
|
||||
if ((interp == "linear" && factor != 1.0) ||
|
||||
(interp == "nearest" && factor < 1.0))
|
||||
CV_Error(Error::StsNotImplemented, "Unsupported Resample mode");
|
||||
}
|
||||
}
|
||||
else if ("Convolution" == type)
|
||||
{
|
||||
CV_Assert(layer.bottom_size() == layer.top_size());
|
||||
for (int i = 0; i < layer.bottom_size(); i++)
|
||||
{
|
||||
if (newEngine)
|
||||
{
|
||||
Ptr<Layer> netLayer = addLayer(
|
||||
dstNet, type, layer.top(i), layerParams,
|
||||
{layer.bottom(i)}, {layer.top(i)});
|
||||
curr_prog.push_back(netLayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
int conv_id = dstNet.addLayer(layer.top(i), type, layerParams);
|
||||
addInput(layer.bottom(i), conv_id, 0, dstNet);
|
||||
addedBlobs.push_back(BlobNote(layer.top(i), conv_id, 0));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if ("ConvolutionDepthwise" == type)
|
||||
{
|
||||
type = "Convolution";
|
||||
}
|
||||
else if (type == "Softmax"){
|
||||
// set default axis to 1
|
||||
if(!layerParams.has("axis"))
|
||||
layerParams.set("axis", 1);
|
||||
}
|
||||
else if ("Proposal" == type)
|
||||
{
|
||||
if (newEngine && layer.top_size() == 1)
|
||||
{
|
||||
// Add unused optional second output and create the Proposal layer
|
||||
std::vector<string> layerInputs;
|
||||
for (int inNum = 0; inNum < layer.bottom_size(); inNum++)
|
||||
layerInputs.push_back(layer.bottom(inNum));
|
||||
Ptr<Layer> netLayer = addLayer(
|
||||
dstNet, type, name, layerParams,
|
||||
layerInputs, {layer.top(0), name + "___output_scores"});
|
||||
curr_prog.push_back(netLayer);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ("Silence" == type)
|
||||
{
|
||||
if (newEngine)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Caffe parser: Silence layer was ignored");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (newEngine)
|
||||
{
|
||||
std::vector<string> layerInputs, layerOutputs;
|
||||
for (int inNum = 0; inNum < layer.bottom_size(); inNum++)
|
||||
layerInputs.push_back(layer.bottom(inNum));
|
||||
for (int outNum = 0; outNum < layer.top_size(); outNum++)
|
||||
layerOutputs.push_back(layer.top(outNum));
|
||||
|
||||
Ptr<Layer> netLayer = addLayer(
|
||||
dstNet, type, name, layerParams,
|
||||
layerInputs, layerOutputs);
|
||||
curr_prog.push_back(netLayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
int id = dstNet.addLayer(name, type, layerParams);
|
||||
for (int inNum = 0; inNum < layer.bottom_size(); inNum++)
|
||||
addInput(layer.bottom(inNum), id, inNum, dstNet);
|
||||
for (int outNum = 0; outNum < layer.top_size(); outNum++)
|
||||
addOutput(layer, id, outNum);
|
||||
}
|
||||
}
|
||||
|
||||
if (newEngine)
|
||||
{
|
||||
Ptr<Graph> curr_graph = netImpl->newGraph(net.name(), modelInputs, true);
|
||||
curr_graph->setOutputs(modelOutputs);
|
||||
curr_graph->setProg(curr_prog);
|
||||
|
||||
netImpl->mainGraph = curr_graph;
|
||||
netImpl->modelFormat = DNN_MODEL_CAFFE;
|
||||
netImpl->originalLayout = DATA_LAYOUT_NCHW;
|
||||
netImpl->prepareForInference();
|
||||
}
|
||||
else
|
||||
{
|
||||
dstNet.setInputsNames(netInputs);
|
||||
|
||||
if (inp_shapes.size() > 0)
|
||||
{
|
||||
CV_CheckEQ(inp_shapes.size(), netInputs.size(), "");
|
||||
for (int inp_id = 0; inp_id < inp_shapes.size(); inp_id++)
|
||||
dstNet.setInputShape(netInputs[inp_id], inp_shapes[inp_id]);
|
||||
}
|
||||
|
||||
addedBlobs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void addOutput(const caffe::LayerParameter &layer, int layerId, int outNum)
|
||||
{
|
||||
const std::string &name = layer.top(outNum);
|
||||
|
||||
bool haveDups = false;
|
||||
for (int idx = (int)addedBlobs.size() - 1; idx >= 0; idx--)
|
||||
{
|
||||
if (addedBlobs[idx].name == name)
|
||||
{
|
||||
haveDups = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (haveDups)
|
||||
{
|
||||
bool isInplace = layer.bottom_size() > outNum && layer.bottom(outNum) == name;
|
||||
if (!isInplace)
|
||||
CV_Error(Error::StsBadArg, "Duplicate blobs produced by multiple sources");
|
||||
}
|
||||
|
||||
addedBlobs.push_back(BlobNote(name, layerId, outNum));
|
||||
}
|
||||
|
||||
void addInput(const std::string &name, int layerId, int inNum, Net &dstNet)
|
||||
{
|
||||
int idx;
|
||||
for (idx = (int)addedBlobs.size() - 1; idx >= 0; idx--)
|
||||
{
|
||||
if (addedBlobs[idx].name == name)
|
||||
break;
|
||||
}
|
||||
|
||||
if (idx < 0)
|
||||
{
|
||||
CV_Error(Error::StsObjectNotFound, "Can't find output blob \"" + name + "\"");
|
||||
}
|
||||
|
||||
dstNet.connect(addedBlobs[idx].layerId, addedBlobs[idx].outNum, layerId, inNum);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Net readNetFromCaffe(const String &prototxt,
|
||||
const String &caffeModel, /*= String()*/
|
||||
int engine)
|
||||
{
|
||||
static const int engine_forced = (int)utils::getConfigurationParameterSizeT("OPENCV_FORCE_DNN_ENGINE", ENGINE_AUTO);
|
||||
if(engine_forced != ENGINE_AUTO)
|
||||
engine = engine_forced;
|
||||
|
||||
CaffeImporter caffeImporter(prototxt.c_str(), caffeModel.c_str());
|
||||
Net net;
|
||||
caffeImporter.populateNet(net, engine == ENGINE_NEW || engine == ENGINE_AUTO);
|
||||
return net;
|
||||
}
|
||||
|
||||
Net readNetFromCaffe(const char *bufferProto, size_t lenProto,
|
||||
const char *bufferModel, size_t lenModel,
|
||||
int engine)
|
||||
{
|
||||
static const int engine_forced = (int)utils::getConfigurationParameterSizeT("OPENCV_FORCE_DNN_ENGINE", ENGINE_AUTO);
|
||||
if(engine_forced != ENGINE_AUTO)
|
||||
engine = engine_forced;
|
||||
|
||||
CaffeImporter caffeImporter(bufferProto, lenProto, bufferModel, lenModel);
|
||||
Net net;
|
||||
caffeImporter.populateNet(net, engine == ENGINE_NEW || engine == ENGINE_AUTO);
|
||||
return net;
|
||||
}
|
||||
|
||||
Net readNetFromCaffe(const std::vector<uchar>& bufferProto,
|
||||
const std::vector<uchar>& bufferModel,
|
||||
int engine)
|
||||
{
|
||||
const char* bufferProtoPtr = reinterpret_cast<const char*>(&bufferProto[0]);
|
||||
const char* bufferModelPtr = bufferModel.empty() ? NULL :
|
||||
reinterpret_cast<const char*>(&bufferModel[0]);
|
||||
return readNetFromCaffe(bufferProtoPtr, bufferProto.size(),
|
||||
bufferModelPtr, bufferModel.size(),
|
||||
engine);
|
||||
}
|
||||
|
||||
#else // HAVE_PROTOBUF
|
||||
|
||||
#define DNN_PROTOBUF_UNSUPPORTED() CV_Error(Error::StsError, "DNN/Caffe: Build OpenCV with Protobuf to import Caffe models")
|
||||
|
||||
Net readNetFromCaffe(const String &, const String &, int) {
|
||||
DNN_PROTOBUF_UNSUPPORTED();
|
||||
}
|
||||
|
||||
Net readNetFromCaffe(const char *, size_t, const char *, size_t, int) {
|
||||
DNN_PROTOBUF_UNSUPPORTED();
|
||||
}
|
||||
|
||||
Net readNetFromCaffe(const std::vector<uchar>&, const std::vector<uchar>&, int) {
|
||||
DNN_PROTOBUF_UNSUPPORTED();
|
||||
}
|
||||
|
||||
#endif // HAVE_PROTOBUF
|
||||
|
||||
CV__DNN_INLINE_NS_END
|
||||
}} // namespace
|
||||
@@ -1,80 +0,0 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "../precomp.hpp"
|
||||
|
||||
#ifdef HAVE_PROTOBUF
|
||||
#include <fstream>
|
||||
#include "caffe_io.hpp"
|
||||
#endif
|
||||
|
||||
namespace cv { namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
|
||||
#ifdef HAVE_PROTOBUF
|
||||
|
||||
void shrinkCaffeModel(const String& src, const String& dst, const std::vector<String>& layersTypes)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
std::vector<String> types(layersTypes);
|
||||
if (types.empty())
|
||||
{
|
||||
types.push_back("Convolution");
|
||||
types.push_back("InnerProduct");
|
||||
}
|
||||
|
||||
caffe::NetParameter net;
|
||||
ReadNetParamsFromBinaryFileOrDie(src.c_str(), &net);
|
||||
|
||||
for (int i = 0; i < net.layer_size(); ++i)
|
||||
{
|
||||
caffe::LayerParameter* lp = net.mutable_layer(i);
|
||||
if (std::find(types.begin(), types.end(), lp->type()) == types.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < lp->blobs_size(); ++j)
|
||||
{
|
||||
caffe::BlobProto* blob = lp->mutable_blobs(j);
|
||||
CV_Assert(blob->data_size() != 0); // float32 array.
|
||||
|
||||
Mat floats(1, blob->data_size(), CV_32FC1, (void*)blob->data().data());
|
||||
Mat halfs(1, blob->data_size(), CV_16FC1);
|
||||
floats.convertTo(halfs, CV_16F); // Convert to float16.
|
||||
|
||||
blob->clear_data(); // Clear float32 data.
|
||||
|
||||
// Set float16 data.
|
||||
blob->set_raw_data(halfs.data, halfs.total() * halfs.elemSize());
|
||||
blob->set_raw_data_type(caffe::FLOAT16);
|
||||
}
|
||||
}
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3005000
|
||||
size_t msgSize = saturate_cast<size_t>(net.ByteSize());
|
||||
#else
|
||||
size_t msgSize = net.ByteSizeLong();
|
||||
#endif
|
||||
std::vector<uint8_t> output(msgSize);
|
||||
net.SerializeWithCachedSizesToArray(&output[0]);
|
||||
|
||||
std::ofstream ofs(dst.c_str(), std::ios::binary);
|
||||
ofs.write((const char*)&output[0], msgSize);
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void shrinkCaffeModel(const String& src, const String& dst, const std::vector<String>& types)
|
||||
{
|
||||
CV_Error(cv::Error::StsNotImplemented, "libprotobuf required to import data from Caffe models");
|
||||
}
|
||||
|
||||
#endif // HAVE_PROTOBUF
|
||||
|
||||
CV__DNN_INLINE_NS_END
|
||||
}} // namespace
|
||||
File diff suppressed because it is too large
Load Diff
@@ -95,7 +95,9 @@ namespace cv { namespace dnn { namespace cuda4dnn {
|
||||
const std::vector<cv::Ptr<BackendWrapper>>& outputs,
|
||||
csl::Workspace& workspace) override
|
||||
{
|
||||
CV_Assert(inputs.size() == 2); /* we don't need the inputs but we are given */
|
||||
// PriorBox uses layer parameters and inputs[0]/inputs[1] shapes; tensor data is never read.
|
||||
// Extra inputs (e.g., in ssd_vgg16.onnx) are ignored, so require >= 2 inputs instead of exactly 2.
|
||||
CV_Assert(inputs.size() >= 2);
|
||||
CV_Assert(outputs.size() == 1);
|
||||
|
||||
auto output_wrapper = outputs[0].dynamicCast<wrapper_type>();
|
||||
|
||||
@@ -17,11 +17,10 @@ Net readNet(const String& _model, const String& _config, const String& _framewor
|
||||
String config = _config;
|
||||
const std::string modelExt = model.substr(model.rfind('.') + 1);
|
||||
const std::string configExt = config.substr(config.rfind('.') + 1);
|
||||
if (framework == "caffe" || modelExt == "caffemodel" || configExt == "caffemodel" || modelExt == "prototxt" || configExt == "prototxt")
|
||||
if (framework == "caffe" || modelExt == "caffemodel" || configExt == "caffemodel" ||
|
||||
modelExt == "prototxt" || configExt == "prototxt")
|
||||
{
|
||||
if (modelExt == "prototxt" || configExt == "caffemodel")
|
||||
std::swap(model, config);
|
||||
return readNetFromCaffe(config, model, engine);
|
||||
CV_Error(Error::StsError, "Caffe importer has been removed. Please use ONNX-converted models or use an older OpenCV version.");
|
||||
}
|
||||
if (framework == "tensorflow" || modelExt == "pb" || configExt == "pb" || modelExt == "pbtxt" || configExt == "pbtxt")
|
||||
{
|
||||
@@ -58,10 +57,10 @@ Net readNet(const String& _framework, const std::vector<uchar>& bufferModel,
|
||||
const std::vector<uchar>& bufferConfig, int engine)
|
||||
{
|
||||
String framework = toLowerCase(_framework);
|
||||
if (framework == "caffe")
|
||||
CV_Error(Error::StsError, "Caffe importer has been removed. Please use ONNX-converted models or use an older OpenCV version.");
|
||||
if (framework == "onnx")
|
||||
return readNetFromONNX(bufferModel, engine);
|
||||
else if (framework == "caffe")
|
||||
return readNetFromCaffe(bufferConfig, bufferModel, engine);
|
||||
else if (framework == "tensorflow")
|
||||
return readNetFromTensorflow(bufferModel, bufferConfig, engine);
|
||||
else if (framework == "darknet")
|
||||
|
||||
@@ -459,7 +459,9 @@ public:
|
||||
inputs_arr.getMatVector(inputs);
|
||||
outputs_arr.getMatVector(outputs);
|
||||
|
||||
CV_Assert(inputs.size() == 2);
|
||||
// PriorBox uses layer parameters and inputs[0]/inputs[1] shapes; tensor data is never read.
|
||||
// Extra inputs (e.g., in ssd_vgg16.onnx) are ignored, so require >= 2 inputs instead of exactly 2.
|
||||
CV_Assert(inputs.size() >= 2);
|
||||
|
||||
int _layerWidth = inputs[0].size[3];
|
||||
int _layerHeight = inputs[0].size[2];
|
||||
@@ -528,7 +530,9 @@ public:
|
||||
#ifdef HAVE_DNN_NGRAPH
|
||||
virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inputs, const std::vector<Ptr<BackendNode> >& nodes) CV_OVERRIDE
|
||||
{
|
||||
CV_Assert(nodes.size() == 2);
|
||||
// PriorBox uses layer parameters and inputs[0]/inputs[1] shapes; tensor data is never read.
|
||||
// Extra inputs (e.g., in ssd_vgg16.onnx) are ignored, so require >= 2 inputs instead of exactly 2.
|
||||
CV_Assert(nodes.size() >= 2);
|
||||
auto layer = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
|
||||
auto image = nodes[1].dynamicCast<InfEngineNgraphNode>()->node;
|
||||
auto layer_shape = std::make_shared<ov::op::v3::ShapeOf>(layer);
|
||||
|
||||
@@ -1,262 +0,0 @@
|
||||
from __future__ import print_function
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import numpy as np
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import time
|
||||
|
||||
try:
|
||||
import caffe
|
||||
except ImportError:
|
||||
raise ImportError('Can\'t find Caffe Python module. If you\'ve built it from sources without installation, '
|
||||
'configure environment variable PYTHONPATH to "git/caffe/python" directory')
|
||||
try:
|
||||
import cv2 as cv
|
||||
except ImportError:
|
||||
raise ImportError('Can\'t find OpenCV Python module. If you\'ve built it from sources without installation, '
|
||||
'configure environment variable PYTHONPATH to "opencv_build_dir/lib" directory (with "python3" subdirectory if required)')
|
||||
|
||||
try:
|
||||
xrange # Python 2
|
||||
except NameError:
|
||||
xrange = range # Python 3
|
||||
|
||||
|
||||
class DataFetch(object):
|
||||
imgs_dir = ''
|
||||
frame_size = 0
|
||||
bgr_to_rgb = False
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
@abstractmethod
|
||||
def preprocess(self, img):
|
||||
pass
|
||||
|
||||
def get_batch(self, imgs_names):
|
||||
assert type(imgs_names) is list
|
||||
batch = np.zeros((len(imgs_names), 3, self.frame_size, self.frame_size)).astype(np.float32)
|
||||
for i in range(len(imgs_names)):
|
||||
img_name = imgs_names[i]
|
||||
img_file = self.imgs_dir + img_name
|
||||
assert os.path.exists(img_file)
|
||||
img = cv.imread(img_file, cv.IMREAD_COLOR)
|
||||
min_dim = min(img.shape[-3], img.shape[-2])
|
||||
resize_ratio = self.frame_size / float(min_dim)
|
||||
img = cv.resize(img, (0, 0), fx=resize_ratio, fy=resize_ratio)
|
||||
cols = img.shape[1]
|
||||
rows = img.shape[0]
|
||||
y1 = (rows - self.frame_size) / 2
|
||||
y2 = y1 + self.frame_size
|
||||
x1 = (cols - self.frame_size) / 2
|
||||
x2 = x1 + self.frame_size
|
||||
img = img[y1:y2, x1:x2]
|
||||
if self.bgr_to_rgb:
|
||||
img = img[..., ::-1]
|
||||
image_data = img[:, :, 0:3].transpose(2, 0, 1)
|
||||
batch[i] = self.preprocess(image_data)
|
||||
return batch
|
||||
|
||||
|
||||
class MeanBlobFetch(DataFetch):
|
||||
mean_blob = np.ndarray(())
|
||||
|
||||
def __init__(self, frame_size, mean_blob_path, imgs_dir):
|
||||
self.imgs_dir = imgs_dir
|
||||
self.frame_size = frame_size
|
||||
blob = caffe.proto.caffe_pb2.BlobProto()
|
||||
data = open(mean_blob_path, 'rb').read()
|
||||
blob.ParseFromString(data)
|
||||
self.mean_blob = np.array(caffe.io.blobproto_to_array(blob))
|
||||
start = (self.mean_blob.shape[2] - self.frame_size) / 2
|
||||
stop = start + self.frame_size
|
||||
self.mean_blob = self.mean_blob[:, :, start:stop, start:stop][0]
|
||||
|
||||
def preprocess(self, img):
|
||||
return img - self.mean_blob
|
||||
|
||||
|
||||
class MeanChannelsFetch(MeanBlobFetch):
|
||||
def __init__(self, frame_size, imgs_dir):
|
||||
self.imgs_dir = imgs_dir
|
||||
self.frame_size = frame_size
|
||||
self.mean_blob = np.ones((3, self.frame_size, self.frame_size)).astype(np.float32)
|
||||
self.mean_blob[0] *= 104
|
||||
self.mean_blob[1] *= 117
|
||||
self.mean_blob[2] *= 123
|
||||
|
||||
|
||||
class MeanValueFetch(MeanBlobFetch):
|
||||
def __init__(self, frame_size, imgs_dir, bgr_to_rgb):
|
||||
self.imgs_dir = imgs_dir
|
||||
self.frame_size = frame_size
|
||||
self.mean_blob = np.ones((3, self.frame_size, self.frame_size)).astype(np.float32)
|
||||
self.mean_blob *= 117
|
||||
self.bgr_to_rgb = bgr_to_rgb
|
||||
|
||||
|
||||
def get_correct_answers(img_list, img_classes, net_output_blob):
|
||||
correct_answers = 0
|
||||
for i in range(len(img_list)):
|
||||
indexes = np.argsort(net_output_blob[i])[-5:]
|
||||
correct_index = img_classes[img_list[i]]
|
||||
if correct_index in indexes:
|
||||
correct_answers += 1
|
||||
return correct_answers
|
||||
|
||||
|
||||
class Framework(object):
|
||||
in_blob_name = ''
|
||||
out_blob_name = ''
|
||||
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
@abstractmethod
|
||||
def get_name(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_output(self, input_blob):
|
||||
pass
|
||||
|
||||
|
||||
class CaffeModel(Framework):
|
||||
net = caffe.Net
|
||||
need_reshape = False
|
||||
|
||||
def __init__(self, prototxt, caffemodel, in_blob_name, out_blob_name, need_reshape=False):
|
||||
caffe.set_mode_cpu()
|
||||
self.net = caffe.Net(prototxt, caffemodel, caffe.TEST)
|
||||
self.in_blob_name = in_blob_name
|
||||
self.out_blob_name = out_blob_name
|
||||
self.need_reshape = need_reshape
|
||||
|
||||
def get_name(self):
|
||||
return 'Caffe'
|
||||
|
||||
def get_output(self, input_blob):
|
||||
if self.need_reshape:
|
||||
self.net.blobs[self.in_blob_name].reshape(*input_blob.shape)
|
||||
return self.net.forward_all(**{self.in_blob_name: input_blob})[self.out_blob_name]
|
||||
|
||||
|
||||
class DnnCaffeModel(Framework):
|
||||
net = object
|
||||
|
||||
def __init__(self, prototxt, caffemodel, in_blob_name, out_blob_name):
|
||||
self.net = cv.dnn.readNetFromCaffe(prototxt, caffemodel)
|
||||
self.in_blob_name = in_blob_name
|
||||
self.out_blob_name = out_blob_name
|
||||
|
||||
def get_name(self):
|
||||
return 'DNN'
|
||||
|
||||
def get_output(self, input_blob):
|
||||
self.net.setInput(input_blob, self.in_blob_name)
|
||||
return self.net.forward(self.out_blob_name)
|
||||
|
||||
class DNNOnnxModel(Framework):
|
||||
net = object
|
||||
|
||||
def __init__(self, onnx_file, in_blob_name, out_blob_name):
|
||||
self.net = cv.dnn.readNetFromONNX(onnx_file)
|
||||
self.in_blob_name = in_blob_name
|
||||
self.out_blob_name = out_blob_name
|
||||
|
||||
def get_name(self):
|
||||
return 'DNN (ONNX)'
|
||||
|
||||
def get_output(self, input_blob):
|
||||
self.net.setInput(input_blob, self.in_blob_name)
|
||||
return self.net.forward(self.out_blob_name)
|
||||
|
||||
|
||||
class ClsAccEvaluation:
|
||||
log = sys.stdout
|
||||
img_classes = {}
|
||||
batch_size = 0
|
||||
|
||||
def __init__(self, log_path, img_classes_file, batch_size):
|
||||
self.log = open(log_path, 'w')
|
||||
self.img_classes = self.read_classes(img_classes_file)
|
||||
self.batch_size = batch_size
|
||||
|
||||
@staticmethod
|
||||
def read_classes(img_classes_file):
|
||||
result = {}
|
||||
with open(img_classes_file) as file:
|
||||
for l in file.readlines():
|
||||
result[l.split()[0]] = int(l.split()[1])
|
||||
return result
|
||||
|
||||
def process(self, frameworks, data_fetcher):
|
||||
sorted_imgs_names = sorted(self.img_classes.keys())
|
||||
correct_answers = [0] * len(frameworks)
|
||||
samples_handled = 0
|
||||
blobs_l1_diff = [0] * len(frameworks)
|
||||
blobs_l1_diff_count = [0] * len(frameworks)
|
||||
blobs_l_inf_diff = [sys.float_info.min] * len(frameworks)
|
||||
inference_time = [0.0] * len(frameworks)
|
||||
|
||||
for x in xrange(0, len(sorted_imgs_names), self.batch_size):
|
||||
sublist = sorted_imgs_names[x:x + self.batch_size]
|
||||
batch = data_fetcher.get_batch(sublist)
|
||||
|
||||
samples_handled += len(sublist)
|
||||
|
||||
frameworks_out = []
|
||||
fw_accuracy = []
|
||||
for i in range(len(frameworks)):
|
||||
start = time.time()
|
||||
out = frameworks[i].get_output(batch)
|
||||
end = time.time()
|
||||
correct_answers[i] += get_correct_answers(sublist, self.img_classes, out)
|
||||
fw_accuracy.append(100 * correct_answers[i] / float(samples_handled))
|
||||
frameworks_out.append(out)
|
||||
inference_time[i] += end - start
|
||||
print(samples_handled, 'Accuracy for', frameworks[i].get_name() + ':', fw_accuracy[i], file=self.log)
|
||||
print("Inference time, ms ", \
|
||||
frameworks[i].get_name(), inference_time[i] / samples_handled * 1000, file=self.log)
|
||||
|
||||
for i in range(1, len(frameworks)):
|
||||
log_str = frameworks[0].get_name() + " vs " + frameworks[i].get_name() + ':'
|
||||
diff = np.abs(frameworks_out[0] - frameworks_out[i])
|
||||
l1_diff = np.sum(diff) / diff.size
|
||||
print(samples_handled, "L1 difference", log_str, l1_diff, file=self.log)
|
||||
blobs_l1_diff[i] += l1_diff
|
||||
blobs_l1_diff_count[i] += 1
|
||||
if np.max(diff) > blobs_l_inf_diff[i]:
|
||||
blobs_l_inf_diff[i] = np.max(diff)
|
||||
print(samples_handled, "L_INF difference", log_str, blobs_l_inf_diff[i], file=self.log)
|
||||
|
||||
self.log.flush()
|
||||
|
||||
for i in range(1, len(blobs_l1_diff)):
|
||||
log_str = frameworks[0].get_name() + " vs " + frameworks[i].get_name() + ':'
|
||||
print('Final l1 diff', log_str, blobs_l1_diff[i] / blobs_l1_diff_count[i], file=self.log)
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--imgs_dir", help="path to ImageNet validation subset images dir, ILSVRC2012_img_val dir")
|
||||
parser.add_argument("--img_cls_file", help="path to file with classes ids for images, val.txt file from this "
|
||||
"archive: http://dl.caffe.berkeleyvision.org/caffe_ilsvrc12.tar.gz")
|
||||
parser.add_argument("--prototxt", help="path to caffe prototxt, download it here: "
|
||||
"https://github.com/BVLC/caffe/blob/master/models/bvlc_alexnet/deploy.prototxt")
|
||||
parser.add_argument("--caffemodel", help="path to caffemodel file, download it here: "
|
||||
"http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel")
|
||||
parser.add_argument("--log", help="path to logging file")
|
||||
parser.add_argument("--mean", help="path to ImageNet mean blob caffe file, imagenet_mean.binaryproto file from"
|
||||
"this archive: http://dl.caffe.berkeleyvision.org/caffe_ilsvrc12.tar.gz")
|
||||
parser.add_argument("--batch_size", help="size of images in batch", default=1000)
|
||||
parser.add_argument("--frame_size", help="size of input image", default=227)
|
||||
parser.add_argument("--in_blob", help="name for input blob", default='data')
|
||||
parser.add_argument("--out_blob", help="name for output blob", default='prob')
|
||||
args = parser.parse_args()
|
||||
|
||||
data_fetcher = MeanBlobFetch(args.frame_size, args.mean, args.imgs_dir)
|
||||
|
||||
frameworks = [CaffeModel(args.prototxt, args.caffemodel, args.in_blob, args.out_blob),
|
||||
DnnCaffeModel(args.prototxt, args.caffemodel, '', args.out_blob)]
|
||||
|
||||
acc_eval = ClsAccEvaluation(args.log, args.img_cls_file, args.batch_size)
|
||||
acc_eval.process(frameworks, data_fetcher)
|
||||
@@ -1,39 +0,0 @@
|
||||
import numpy as np
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
from imagenet_cls_test_alexnet import MeanChannelsFetch, CaffeModel, DnnCaffeModel, ClsAccEvaluation
|
||||
try:
|
||||
import caffe
|
||||
except ImportError:
|
||||
raise ImportError('Can\'t find Caffe Python module. If you\'ve built it from sources without installation, '
|
||||
'configure environment variable PYTHONPATH to "git/caffe/python" directory')
|
||||
try:
|
||||
import cv2 as cv
|
||||
except ImportError:
|
||||
raise ImportError('Can\'t find OpenCV Python module. If you\'ve built it from sources without installation, '
|
||||
'configure environment variable PYTHONPATH to "opencv_build_dir/lib" directory (with "python3" subdirectory if required)')
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--imgs_dir", help="path to ImageNet validation subset images dir, ILSVRC2012_img_val dir")
|
||||
parser.add_argument("--img_cls_file", help="path to file with classes ids for images, val.txt file from this "
|
||||
"archive: http://dl.caffe.berkeleyvision.org/caffe_ilsvrc12.tar.gz")
|
||||
parser.add_argument("--prototxt", help="path to caffe prototxt, download it here: "
|
||||
"https://github.com/BVLC/caffe/blob/master/models/bvlc_alexnet/deploy.prototxt")
|
||||
parser.add_argument("--caffemodel", help="path to caffemodel file, download it here: "
|
||||
"http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel")
|
||||
parser.add_argument("--log", help="path to logging file")
|
||||
parser.add_argument("--batch_size", help="size of images in batch", default=500, type=int)
|
||||
parser.add_argument("--frame_size", help="size of input image", default=224, type=int)
|
||||
parser.add_argument("--in_blob", help="name for input blob", default='data')
|
||||
parser.add_argument("--out_blob", help="name for output blob", default='prob')
|
||||
args = parser.parse_args()
|
||||
|
||||
data_fetcher = MeanChannelsFetch(args.frame_size, args.imgs_dir)
|
||||
|
||||
frameworks = [CaffeModel(args.prototxt, args.caffemodel, args.in_blob, args.out_blob),
|
||||
DnnCaffeModel(args.prototxt, args.caffemodel, '', args.out_blob)]
|
||||
|
||||
acc_eval = ClsAccEvaluation(args.log, args.img_cls_file, args.batch_size)
|
||||
acc_eval.process(frameworks, data_fetcher)
|
||||
@@ -1,77 +0,0 @@
|
||||
import numpy as np
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import tensorflow as tf
|
||||
from tensorflow.python.platform import gfile
|
||||
from imagenet_cls_test_alexnet import MeanValueFetch, DnnCaffeModel, Framework, ClsAccEvaluation
|
||||
try:
|
||||
import cv2 as cv
|
||||
except ImportError:
|
||||
raise ImportError('Can\'t find OpenCV Python module. If you\'ve built it from sources without installation, '
|
||||
'configure environment variable PYTHONPATH to "opencv_build_dir/lib" directory (with "python3" subdirectory if required)')
|
||||
|
||||
# If you've got an exception "Cannot load libmkl_avx.so or libmkl_def.so" or similar, try to export next variable
|
||||
# before running the script:
|
||||
# LD_PRELOAD=/opt/intel/mkl/lib/intel64/libmkl_core.so:/opt/intel/mkl/lib/intel64/libmkl_sequential.so
|
||||
|
||||
|
||||
class TensorflowModel(Framework):
|
||||
sess = tf.Session
|
||||
output = tf.Graph
|
||||
|
||||
def __init__(self, model_file, in_blob_name, out_blob_name):
|
||||
self.in_blob_name = in_blob_name
|
||||
self.sess = tf.Session()
|
||||
with gfile.FastGFile(model_file, 'rb') as f:
|
||||
graph_def = tf.GraphDef()
|
||||
graph_def.ParseFromString(f.read())
|
||||
self.sess.graph.as_default()
|
||||
tf.import_graph_def(graph_def, name='')
|
||||
self.output = self.sess.graph.get_tensor_by_name(out_blob_name + ":0")
|
||||
|
||||
def get_name(self):
|
||||
return 'Tensorflow'
|
||||
|
||||
def get_output(self, input_blob):
|
||||
assert len(input_blob.shape) == 4
|
||||
batch_tf = input_blob.transpose(0, 2, 3, 1)
|
||||
out = self.sess.run(self.output,
|
||||
{self.in_blob_name+':0': batch_tf})
|
||||
out = out[..., 1:1001]
|
||||
return out
|
||||
|
||||
|
||||
class DnnTfInceptionModel(DnnCaffeModel):
|
||||
net = cv.dnn.Net()
|
||||
|
||||
def __init__(self, model_file, in_blob_name, out_blob_name):
|
||||
self.net = cv.dnn.readNetFromTensorflow(model_file)
|
||||
self.in_blob_name = in_blob_name
|
||||
self.out_blob_name = out_blob_name
|
||||
|
||||
def get_output(self, input_blob):
|
||||
return super(DnnTfInceptionModel, self).get_output(input_blob)[..., 1:1001]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--imgs_dir", help="path to ImageNet validation subset images dir, ILSVRC2012_img_val dir")
|
||||
parser.add_argument("--img_cls_file", help="path to file with classes ids for images, download it here:"
|
||||
"https://github.com/opencv/opencv_extra/tree/5.x/testdata/dnn/img_classes_inception.txt")
|
||||
parser.add_argument("--model", help="path to tensorflow model, download it here:"
|
||||
"https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip")
|
||||
parser.add_argument("--log", help="path to logging file")
|
||||
parser.add_argument("--batch_size", help="size of images in batch", default=1)
|
||||
parser.add_argument("--frame_size", help="size of input image", default=224)
|
||||
parser.add_argument("--in_blob", help="name for input blob", default='input')
|
||||
parser.add_argument("--out_blob", help="name for output blob", default='softmax2')
|
||||
args = parser.parse_args()
|
||||
|
||||
data_fetcher = MeanValueFetch(args.frame_size, args.imgs_dir, True)
|
||||
|
||||
frameworks = [TensorflowModel(args.model, args.in_blob, args.out_blob),
|
||||
DnnTfInceptionModel(args.model, '', args.out_blob)]
|
||||
|
||||
acc_eval = ClsAccEvaluation(args.log, args.img_cls_file, args.batch_size)
|
||||
acc_eval.process(frameworks, data_fetcher)
|
||||
@@ -1,255 +0,0 @@
|
||||
from __future__ import print_function
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import numpy as np
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
|
||||
from imagenet_cls_test_alexnet import CaffeModel, DNNOnnxModel
|
||||
try:
|
||||
import cv2 as cv
|
||||
except ImportError:
|
||||
raise ImportError('Can\'t find OpenCV Python module. If you\'ve built it from sources without installation, '
|
||||
'configure environment variable PYTHONPATH to "opencv_build_dir/lib" directory (with "python3" subdirectory if required)')
|
||||
|
||||
|
||||
def get_metrics(conf_mat):
|
||||
pix_accuracy = np.trace(conf_mat) / np.sum(conf_mat)
|
||||
t = np.sum(conf_mat, 1)
|
||||
num_cl = np.count_nonzero(t)
|
||||
assert num_cl
|
||||
mean_accuracy = np.sum(np.nan_to_num(np.divide(np.diagonal(conf_mat), t))) / num_cl
|
||||
col_sum = np.sum(conf_mat, 0)
|
||||
mean_iou = np.sum(
|
||||
np.nan_to_num(np.divide(np.diagonal(conf_mat), (t + col_sum - np.diagonal(conf_mat))))) / num_cl
|
||||
return pix_accuracy, mean_accuracy, mean_iou
|
||||
|
||||
|
||||
def eval_segm_result(net_out):
|
||||
assert type(net_out) is np.ndarray
|
||||
assert len(net_out.shape) == 4
|
||||
|
||||
channels_dim = 1
|
||||
y_dim = channels_dim + 1
|
||||
x_dim = y_dim + 1
|
||||
res = np.zeros(net_out.shape).astype(int)
|
||||
for i in range(net_out.shape[y_dim]):
|
||||
for j in range(net_out.shape[x_dim]):
|
||||
max_ch = np.argmax(net_out[..., i, j])
|
||||
res[0, max_ch, i, j] = 1
|
||||
return res
|
||||
|
||||
|
||||
def get_conf_mat(gt, prob):
|
||||
assert type(gt) is np.ndarray
|
||||
assert type(prob) is np.ndarray
|
||||
|
||||
conf_mat = np.zeros((gt.shape[0], gt.shape[0]))
|
||||
for ch_gt in range(conf_mat.shape[0]):
|
||||
gt_channel = gt[ch_gt, ...]
|
||||
for ch_pr in range(conf_mat.shape[1]):
|
||||
prob_channel = prob[ch_pr, ...]
|
||||
conf_mat[ch_gt][ch_pr] = np.count_nonzero(np.multiply(gt_channel, prob_channel))
|
||||
return conf_mat
|
||||
|
||||
|
||||
class MeanChannelsPreproc:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def process(img, framework):
|
||||
image_data = None
|
||||
if framework == "Caffe":
|
||||
image_data = cv.dnn.blobFromImage(img, scalefactor=1.0, mean=(123.0, 117.0, 104.0), swapRB=True)
|
||||
elif framework == "DNN (ONNX)":
|
||||
image_data = cv.dnn.blobFromImage(img, scalefactor=0.019, mean=(123.675, 116.28, 103.53), swapRB=True)
|
||||
else:
|
||||
raise ValueError("Unknown framework")
|
||||
return image_data
|
||||
|
||||
|
||||
class DatasetImageFetch(object):
|
||||
__metaclass__ = ABCMeta
|
||||
data_prepoc = object
|
||||
|
||||
@abstractmethod
|
||||
def __iter__(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def next(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def pix_to_c(pix):
|
||||
return pix[0] * 256 * 256 + pix[1] * 256 + pix[2]
|
||||
|
||||
@staticmethod
|
||||
def color_to_gt(color_img, colors):
|
||||
num_classes = len(colors)
|
||||
gt = np.zeros((num_classes, color_img.shape[0], color_img.shape[1])).astype(int)
|
||||
for img_y in range(color_img.shape[0]):
|
||||
for img_x in range(color_img.shape[1]):
|
||||
c = DatasetImageFetch.pix_to_c(color_img[img_y][img_x])
|
||||
if c in colors:
|
||||
cls = colors.index(c)
|
||||
gt[cls][img_y][img_x] = 1
|
||||
return gt
|
||||
|
||||
|
||||
class PASCALDataFetch(DatasetImageFetch):
|
||||
img_dir = ''
|
||||
segm_dir = ''
|
||||
names = []
|
||||
colors = []
|
||||
i = 0
|
||||
|
||||
def __init__(self, img_dir, segm_dir, names_file, segm_cls_colors, preproc):
|
||||
self.img_dir = img_dir
|
||||
self.segm_dir = segm_dir
|
||||
self.colors = self.read_colors(segm_cls_colors)
|
||||
self.data_prepoc = preproc
|
||||
self.i = 0
|
||||
|
||||
with open(names_file) as f:
|
||||
for l in f.readlines():
|
||||
self.names.append(l.rstrip())
|
||||
|
||||
@staticmethod
|
||||
def read_colors(colors):
|
||||
result = []
|
||||
for color in colors:
|
||||
result.append(DatasetImageFetch.pix_to_c(color))
|
||||
return result
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.i < len(self.names):
|
||||
name = self.names[self.i]
|
||||
self.i += 1
|
||||
segm_file = self.segm_dir + name + ".png"
|
||||
img_file = self.img_dir + name + ".jpg"
|
||||
gt = self.color_to_gt(cv.imread(segm_file, cv.IMREAD_COLOR)[:, :, ::-1], self.colors)
|
||||
img = cv.imread(img_file, cv.IMREAD_COLOR)
|
||||
img_caffe = self.data_prepoc.process(img[:, :, ::-1], "Caffe")
|
||||
img_dnn = self.data_prepoc.process(img[:, :, ::-1], "DNN (ONNX)")
|
||||
img_dict = {
|
||||
"Caffe": img_caffe,
|
||||
"DNN (ONNX)": img_dnn
|
||||
}
|
||||
return img_dict, gt
|
||||
else:
|
||||
self.i = 0
|
||||
raise StopIteration
|
||||
|
||||
def get_num_classes(self):
|
||||
return len(self.colors)
|
||||
|
||||
|
||||
class SemSegmEvaluation:
|
||||
log = sys.stdout
|
||||
|
||||
def __init__(self, log_path,):
|
||||
self.log = open(log_path, 'w')
|
||||
|
||||
def process(self, frameworks, data_fetcher):
|
||||
samples_handled = 0
|
||||
|
||||
conf_mats = [np.zeros((data_fetcher.get_num_classes(), data_fetcher.get_num_classes())) for i in range(len(frameworks))]
|
||||
blobs_l1_diff = [0] * len(frameworks)
|
||||
blobs_l1_diff_count = [0] * len(frameworks)
|
||||
blobs_l_inf_diff = [sys.float_info.min] * len(frameworks)
|
||||
inference_time = [0.0] * len(frameworks)
|
||||
|
||||
for in_blob_dict, gt in data_fetcher:
|
||||
frameworks_out = []
|
||||
samples_handled += 1
|
||||
for i in range(len(frameworks)):
|
||||
start = time.time()
|
||||
framework_name = frameworks[i].get_name()
|
||||
out = frameworks[i].get_output(in_blob_dict[framework_name])
|
||||
end = time.time()
|
||||
segm = eval_segm_result(out)
|
||||
conf_mats[i] += get_conf_mat(gt, segm[0])
|
||||
frameworks_out.append(out)
|
||||
inference_time[i] += end - start
|
||||
|
||||
pix_acc, mean_acc, miou = get_metrics(conf_mats[i])
|
||||
|
||||
name = frameworks[i].get_name()
|
||||
print(samples_handled, 'Pixel accuracy, %s:' % name, 100 * pix_acc, file=self.log)
|
||||
print(samples_handled, 'Mean accuracy, %s:' % name, 100 * mean_acc, file=self.log)
|
||||
print(samples_handled, 'Mean IOU, %s:' % name, 100 * miou, file=self.log)
|
||||
print("Inference time, ms ", \
|
||||
frameworks[i].get_name(), inference_time[i] / samples_handled * 1000, file=self.log)
|
||||
|
||||
for i in range(1, len(frameworks)):
|
||||
log_str = frameworks[0].get_name() + " vs " + frameworks[i].get_name() + ':'
|
||||
diff = np.abs(frameworks_out[0] - frameworks_out[i])
|
||||
l1_diff = np.sum(diff) / diff.size
|
||||
print(samples_handled, "L1 difference", log_str, l1_diff, file=self.log)
|
||||
blobs_l1_diff[i] += l1_diff
|
||||
blobs_l1_diff_count[i] += 1
|
||||
if np.max(diff) > blobs_l_inf_diff[i]:
|
||||
blobs_l_inf_diff[i] = np.max(diff)
|
||||
print(samples_handled, "L_INF difference", log_str, blobs_l_inf_diff[i], file=self.log)
|
||||
|
||||
self.log.flush()
|
||||
|
||||
for i in range(1, len(blobs_l1_diff)):
|
||||
log_str = frameworks[0].get_name() + " vs " + frameworks[i].get_name() + ':'
|
||||
print('Final l1 diff', log_str, blobs_l1_diff[i] / blobs_l1_diff_count[i], file=self.log)
|
||||
|
||||
# PASCAL VOC 2012 classes colors
|
||||
colors_pascal_voc_2012 = [
|
||||
[0, 0, 0],
|
||||
[128, 0, 0],
|
||||
[0, 128, 0],
|
||||
[128, 128, 0],
|
||||
[0, 0, 128],
|
||||
[128, 0, 128],
|
||||
[0, 128, 128],
|
||||
[128, 128, 128],
|
||||
[64, 0, 0],
|
||||
[192, 0, 0],
|
||||
[64, 128, 0],
|
||||
[192, 128, 0],
|
||||
[64, 0, 128],
|
||||
[192, 0, 128],
|
||||
[64, 128, 128],
|
||||
[192, 128, 128],
|
||||
[0, 64, 0],
|
||||
[128, 64, 0],
|
||||
[0, 192, 0],
|
||||
[128, 192, 0],
|
||||
[0, 64, 128],
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--imgs_dir", help="path to PASCAL VOC 2012 images dir, data/VOC2012/JPEGImages")
|
||||
parser.add_argument("--segm_dir", help="path to PASCAL VOC 2012 segmentation dir, data/VOC2012/SegmentationClass/")
|
||||
parser.add_argument("--val_names", help="path to file with validation set image names, download it here: "
|
||||
"https://github.com/shelhamer/fcn.berkeleyvision.org/blob/master/data/pascal/seg11valid.txt")
|
||||
parser.add_argument("--prototxt", help="path to caffe prototxt, download it here: "
|
||||
"https://github.com/opencv/opencv/blob/5.x/samples/data/dnn/fcn8s-heavy-pascal.prototxt")
|
||||
parser.add_argument("--caffemodel", help="path to caffemodel file, download it here: "
|
||||
"http://dl.caffe.berkeleyvision.org/fcn8s-heavy-pascal.caffemodel")
|
||||
parser.add_argument("--onnxmodel", help="path to onnx model file, download it here: "
|
||||
"https://github.com/onnx/models/raw/491ce05590abb7551d7fae43c067c060eeb575a6/validated/vision/object_detection_segmentation/fcn/model/fcn-resnet50-12.onnx")
|
||||
parser.add_argument("--log", help="path to logging file", default='log.txt')
|
||||
parser.add_argument("--in_blob", help="name for input blob", default='data')
|
||||
parser.add_argument("--out_blob", help="name for output blob", default='score')
|
||||
args = parser.parse_args()
|
||||
|
||||
prep = MeanChannelsPreproc()
|
||||
df = PASCALDataFetch(args.imgs_dir, args.segm_dir, args.val_names, colors_pascal_voc_2012, prep)
|
||||
|
||||
fw = [CaffeModel(args.prototxt, args.caffemodel, args.in_blob, args.out_blob, True),
|
||||
DNNOnnxModel(args.onnxmodel, args.in_blob, args.out_blob)]
|
||||
|
||||
segm_eval = SemSegmEvaluation(args.log)
|
||||
segm_eval.process(fw, df)
|
||||
@@ -124,8 +124,11 @@ TEST_P(DNNTestNetwork, DISABLED_YOLOv8n) {
|
||||
TEST_P(DNNTestNetwork, AlexNet)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_1GB);
|
||||
processNet("dnn/bvlc_alexnet.caffemodel", "dnn/bvlc_alexnet.prototxt",
|
||||
Size(227, 227), "prob");
|
||||
// Skip memory-heavy OpenCL targets on 32-bit (x86) platforms to avoid OutOfMemoryError
|
||||
if (sizeof(void*) == 4 &&
|
||||
(target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
throw SkipTestException("Skip memory-heavy OpenCL target on 32-bit (x86) platform");
|
||||
processNet("dnn/onnx/models/alexnet.onnx", "", Size(227, 227));
|
||||
expectNoFallbacksFromIE(net);
|
||||
expectNoFallbacksFromCUDA(net);
|
||||
}
|
||||
@@ -137,16 +140,20 @@ TEST_P(DNNTestNetwork, ResNet_50)
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
processNet("dnn/ResNet-50-model.caffemodel", "dnn/ResNet-50-deploy.prototxt",
|
||||
Size(224, 224), "prob");
|
||||
double l1 = default_l1, lInf = default_lInf;
|
||||
if (target == DNN_TARGET_CUDA_FP16 || target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16)
|
||||
{
|
||||
l1 = 0.015;
|
||||
lInf = 0.05;
|
||||
}
|
||||
processNet("dnn/onnx/models/resnet50v1.onnx", "", Size(224, 224), "", l1, lInf);
|
||||
expectNoFallbacksFromIE(net);
|
||||
expectNoFallbacksFromCUDA(net);
|
||||
}
|
||||
|
||||
TEST_P(DNNTestNetwork, SqueezeNet_v1_1)
|
||||
{
|
||||
processNet("dnn/squeezenet_v1.1.caffemodel", "dnn/squeezenet_v1.1.prototxt",
|
||||
Size(227, 227), "prob");
|
||||
processNet("dnn/onnx/models/squeezenet.onnx", "", Size(227, 227));
|
||||
expectNoFallbacksFromIE(net);
|
||||
expectNoFallbacksFromCUDA(net);
|
||||
}
|
||||
@@ -155,8 +162,7 @@ TEST_P(DNNTestNetwork, GoogLeNet)
|
||||
{
|
||||
applyTestTag(target == DNN_TARGET_CPU ? "" : CV_TEST_TAG_MEMORY_512MB);
|
||||
|
||||
processNet("dnn/bvlc_googlenet.caffemodel", "dnn/bvlc_googlenet.prototxt",
|
||||
Size(224, 224), "prob");
|
||||
processNet("dnn/onnx/models/googlenet.onnx", "", Size(224, 224));
|
||||
expectNoFallbacksFromIE(net);
|
||||
expectNoFallbacksFromCUDA(net);
|
||||
}
|
||||
@@ -176,60 +182,6 @@ TEST_P(DNNTestNetwork, Inception_5h)
|
||||
expectNoFallbacksFromCUDA(net);
|
||||
}
|
||||
|
||||
TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
Mat sample = imread(findDataFile("dnn/street.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
|
||||
float scoreDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16) ? 1.5e-2 : 0.0;
|
||||
float iouDiff = (target == DNN_TARGET_MYRIAD) ? 0.063 : 0.0;
|
||||
float detectionConfThresh = (target == DNN_TARGET_MYRIAD) ? 0.262 : FLT_MIN;
|
||||
processNet("dnn/MobileNetSSD_deploy_19e3ec3.caffemodel", "dnn/MobileNetSSD_deploy_19e3ec3.prototxt",
|
||||
inp, "detection_out", scoreDiff, iouDiff, detectionConfThresh);
|
||||
expectNoFallbacksFromIE(net);
|
||||
}
|
||||
|
||||
TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe_Different_Width_Height)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2022010000)
|
||||
// May hang on some configurations
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION
|
||||
);
|
||||
#elif defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
|
||||
// IE exception: Ngraph operation Transpose with name conv15_2_mbox_conf_perm has dynamic output shape on 0 port, but CPU plug-in supports only static shape
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION
|
||||
);
|
||||
if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) &&
|
||||
target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#elif defined(INF_ENGINE_RELEASE)
|
||||
if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) &&
|
||||
target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/street.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 560), Scalar(127.5, 127.5, 127.5), false);
|
||||
float scoreDiff = 0.0, iouDiff = 0.0;
|
||||
if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16)
|
||||
{
|
||||
scoreDiff = 0.029;
|
||||
iouDiff = 0.09;
|
||||
}
|
||||
else if (target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
scoreDiff = 0.03;
|
||||
iouDiff = 0.08;
|
||||
}
|
||||
processNet("dnn/MobileNetSSD_deploy_19e3ec3.caffemodel", "dnn/MobileNetSSD_deploy_19e3ec3.prototxt",
|
||||
inp, "detection_out", scoreDiff, iouDiff);
|
||||
expectNoFallbacksFromIE(net);
|
||||
}
|
||||
|
||||
TEST_P(DNNTestNetwork, MobileNet_SSD_v1_TensorFlow)
|
||||
{
|
||||
applyTestTag((target == DNN_TARGET_CPU || target == DNN_TARGET_CPU_FP16) ? "" : CV_TEST_TAG_MEMORY_512MB);
|
||||
@@ -313,6 +265,18 @@ TEST_P(DNNTestNetwork, SSD_VGG16)
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
// This converted SSD model relies on layers the OpenVINO backend can't run.
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
auto engine_forced = static_cast<cv::dnn::EngineType>(
|
||||
cv::utils::getConfigurationParameterSizeT("OPENCV_FORCE_DNN_ENGINE", cv::dnn::ENGINE_AUTO));
|
||||
if (engine_forced == cv::dnn::ENGINE_CLASSIC)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_PARSER);
|
||||
return;
|
||||
}
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/street.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0f, Size(300, 300), Scalar(), false);
|
||||
|
||||
@@ -332,8 +296,8 @@ TEST_P(DNNTestNetwork, SSD_VGG16)
|
||||
iouDiff = 0.13;
|
||||
}
|
||||
|
||||
processNet("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel",
|
||||
"dnn/ssd_vgg16.prototxt", inp, "detection_out", scoreDiff,
|
||||
processNet("dnn/onnx/models/ssd_vgg16.onnx", "",
|
||||
inp, "detection_out", scoreDiff,
|
||||
iouDiff, 0.2, false);
|
||||
expectNoFallbacksFromIE(net);
|
||||
}
|
||||
@@ -350,7 +314,7 @@ TEST_P(DNNTestNetwork, OpenPose_pose_coco)
|
||||
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.009 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD) ? 0.09 : 0.0;
|
||||
processNet("dnn/openpose_pose_coco.caffemodel", "dnn/openpose_pose_coco.prototxt",
|
||||
processNet("dnn/onnx/models/openpose_pose_coco.onnx", "",
|
||||
Size(46, 46), "", l1, lInf);
|
||||
expectNoFallbacksFromIE(net);
|
||||
expectNoFallbacksFromCUDA(net);
|
||||
@@ -369,7 +333,7 @@ TEST_P(DNNTestNetwork, OpenPose_pose_mpi)
|
||||
// output range: [-0.001, 0.97]
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.02 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16) ? 0.2 : 0.0;
|
||||
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi.prototxt",
|
||||
processNet("dnn/onnx/models/openpose_pose_mpi.onnx", "",
|
||||
Size(46, 46), "", l1, lInf);
|
||||
expectNoFallbacksFromIE(net);
|
||||
expectNoFallbacksFromCUDA(net);
|
||||
@@ -384,9 +348,8 @@ TEST_P(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
// The same .caffemodel but modified .prototxt
|
||||
// See https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/src/openpose/pose/poseParameters.cpp
|
||||
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi_faster_4_stages.prototxt",
|
||||
processNet("dnn/onnx/models/openpose_pose_mpi_faster_4_stages.onnx", "",
|
||||
Size(46, 46));
|
||||
expectNoFallbacksFromIE(net);
|
||||
expectNoFallbacksFromCUDA(net);
|
||||
@@ -456,10 +419,10 @@ TEST_P(DNNTestNetwork, DenseNet_121)
|
||||
}
|
||||
else if (target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
l1 = 0.008;
|
||||
lInf = 0.06;
|
||||
l1 = 2e-2;
|
||||
lInf = 9e-2;
|
||||
}
|
||||
processNet("dnn/DenseNet_121.caffemodel", "dnn/DenseNet_121.prototxt", Size(224, 224), "", l1, lInf);
|
||||
processNet("dnn/onnx/models/densenet121.onnx", "", Size(224, 224), "", l1, lInf);
|
||||
if (target != DNN_TARGET_MYRIAD || getInferenceEngineVPUType() != CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
|
||||
expectNoFallbacksFromIE(net);
|
||||
expectNoFallbacksFromCUDA(net);
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "test_precomp.hpp"
|
||||
#include "npy_blob.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
#include <set>
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
@@ -58,8 +59,8 @@ public:
|
||||
double scoreDiff = 0.0, double iouDiff = 0.0)
|
||||
{
|
||||
checkBackend();
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/" + proto),
|
||||
findDataFile("dnn/" + model, false));
|
||||
Net net = readNet(findDataFile("dnn/" + proto),
|
||||
findDataFile("dnn/" + model, false));
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
Mat blob = blobFromImage(img, 1.0, Size(), Scalar(102.9801, 115.9465, 122.7717), false, false);
|
||||
Mat imInfo = (Mat_<float>(1, 3) << img.rows, img.cols, 1.6f);
|
||||
|
||||
net.setInput(blob, "data");
|
||||
net.setInput(blob);
|
||||
net.setInput(imInfo, "im_info");
|
||||
// Output has shape 1x1xNx7 where N - number of detections.
|
||||
// An every detection is a vector of values [id, classId, confidence, left, top, right, bottom]
|
||||
@@ -82,205 +83,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Test_Caffe, memory_read)
|
||||
{
|
||||
const string proto = findDataFile("dnn/bvlc_googlenet.prototxt");
|
||||
const string model = findDataFile("dnn/bvlc_googlenet.caffemodel", false);
|
||||
|
||||
std::vector<char> dataProto;
|
||||
readFileContent(proto, dataProto);
|
||||
|
||||
std::vector<char> dataModel;
|
||||
readFileContent(model, dataModel);
|
||||
|
||||
Net net = readNetFromCaffe(dataProto.data(), dataProto.size());
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
ASSERT_FALSE(net.empty());
|
||||
|
||||
Net net2 = readNetFromCaffe(dataProto.data(), dataProto.size(),
|
||||
dataModel.data(), dataModel.size());
|
||||
ASSERT_FALSE(net2.empty());
|
||||
}
|
||||
|
||||
TEST(Test_Caffe, read_gtsrb)
|
||||
{
|
||||
Net net = readNetFromCaffe(_tf("gtsrb.prototxt"));
|
||||
ASSERT_FALSE(net.empty());
|
||||
}
|
||||
|
||||
TEST(Test_Caffe, read_googlenet)
|
||||
{
|
||||
Net net = readNetFromCaffe(_tf("bvlc_googlenet.prototxt"));
|
||||
ASSERT_FALSE(net.empty());
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_nets, Axpy)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
#endif
|
||||
|
||||
String proto = _tf("axpy.prototxt");
|
||||
Net net = readNetFromCaffe(proto);
|
||||
|
||||
checkBackend();
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
|
||||
int size[] = {1, 2, 3, 4};
|
||||
int scale_size[] = {1, 2, 1, 1};
|
||||
Mat scale(4, &scale_size[0], CV_32F);
|
||||
Mat shift(4, &size[0], CV_32F);
|
||||
Mat inp(4, &size[0], CV_32F);
|
||||
randu(scale, -1.0f, 1.0f);
|
||||
randu(shift, -1.0f, 1.0f);
|
||||
randu(inp, -1.0f, 1.0f);
|
||||
|
||||
net.setInput(scale, "scale");
|
||||
net.setInput(shift, "shift");
|
||||
net.setInput(inp, "data");
|
||||
|
||||
Mat out = net.forward();
|
||||
|
||||
Mat ref(4, &size[0], inp.type());
|
||||
for (int i = 0; i < inp.size[1]; i++) {
|
||||
for (int h = 0; h < inp.size[2]; h++) {
|
||||
for (int w = 0; w < inp.size[3]; w++) {
|
||||
int idx[] = {0, i, h, w};
|
||||
int scale_idx[] = {0, i, 0, 0};
|
||||
ref.at<float>(idx) = inp.at<float>(idx) * scale.at<float>(scale_idx) +
|
||||
shift.at<float>(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
float l1 = 1e-5, lInf = 1e-4;
|
||||
if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16)
|
||||
{
|
||||
l1 = 2e-4;
|
||||
lInf = 1e-3;
|
||||
}
|
||||
if (target == DNN_TARGET_MYRIAD)
|
||||
{
|
||||
l1 = 0.001;
|
||||
lInf = 0.001;
|
||||
}
|
||||
if(target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
l1 = 0.0002;
|
||||
lInf = 0.0007;
|
||||
}
|
||||
normAssert(ref, out, "", l1, lInf);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<bool, Target> > Reproducibility_AlexNet;
|
||||
TEST_P(Reproducibility_AlexNet, Accuracy)
|
||||
{
|
||||
Target targetId = get<1>(GetParam());
|
||||
#if defined(OPENCV_32BIT_CONFIGURATION) && defined(HAVE_OPENCL)
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_2GB);
|
||||
#else
|
||||
applyTestTag(targetId == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB);
|
||||
#endif
|
||||
ASSERT_TRUE(ocl::useOpenCL() || targetId == DNN_TARGET_CPU || targetId == DNN_TARGET_CPU_FP16);
|
||||
|
||||
bool readFromMemory = get<0>(GetParam());
|
||||
Net net;
|
||||
{
|
||||
const string proto = findDataFile("dnn/bvlc_alexnet.prototxt");
|
||||
const string model = findDataFile("dnn/bvlc_alexnet.caffemodel", false);
|
||||
if (readFromMemory)
|
||||
{
|
||||
std::vector<char> dataProto;
|
||||
readFileContent(proto, dataProto);
|
||||
std::vector<char> dataModel;
|
||||
readFileContent(model, dataModel);
|
||||
|
||||
net = readNetFromCaffe(dataProto.data(), dataProto.size(),
|
||||
dataModel.data(), dataModel.size());
|
||||
}
|
||||
else
|
||||
net = readNetFromCaffe(proto, model);
|
||||
ASSERT_FALSE(net.empty());
|
||||
}
|
||||
|
||||
// Test input layer size
|
||||
std::vector<MatShape> inLayerShapes;
|
||||
std::vector<MatShape> outLayerShapes;
|
||||
net.getLayerShapes(MatShape(), CV_32F, 0, inLayerShapes, outLayerShapes);
|
||||
ASSERT_FALSE(inLayerShapes.empty());
|
||||
ASSERT_EQ(inLayerShapes[0].size(), 4);
|
||||
ASSERT_EQ(inLayerShapes[0][0], 1);
|
||||
ASSERT_EQ(inLayerShapes[0][1], 3);
|
||||
ASSERT_EQ(inLayerShapes[0][2], 227);
|
||||
ASSERT_EQ(inLayerShapes[0][3], 227);
|
||||
|
||||
const float l1 = 1e-5;
|
||||
const float lInf = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_CPU_FP16) ? 4e-3 : 1e-4;
|
||||
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
if (targetId == DNN_TARGET_CPU_FP16)
|
||||
net.enableWinograd(false);
|
||||
|
||||
Mat sample = imread(_tf("grace_hopper_227.png"));
|
||||
ASSERT_TRUE(!sample.empty());
|
||||
|
||||
net.setInput(blobFromImage(sample, 1.0f, Size(227, 227), Scalar(), false), "data");
|
||||
|
||||
Mat out;
|
||||
// BUG: https://github.com/opencv/opencv/issues/26349
|
||||
if (net.getMainGraph())
|
||||
out = net.forward();
|
||||
else
|
||||
out = net.forward("prob");
|
||||
|
||||
Mat ref = blobFromNPY(_tf("caffe_alexnet_prob.npy"));
|
||||
normAssert(ref, out, "", l1, lInf);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_AlexNet, Combine(testing::Bool(),
|
||||
testing::ValuesIn(getAvailableTargets(DNN_BACKEND_OPENCV))));
|
||||
|
||||
TEST(Reproducibility_FCN, Accuracy)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_LONG, CV_TEST_TAG_DEBUG_VERYLONG, CV_TEST_TAG_MEMORY_2GB);
|
||||
|
||||
Net net;
|
||||
{
|
||||
const string proto = findDataFile("dnn/fcn8s-heavy-pascal.prototxt");
|
||||
const string model = findDataFile("dnn/fcn8s-heavy-pascal.caffemodel", false);
|
||||
net = readNetFromCaffe(proto, model);
|
||||
ASSERT_FALSE(net.empty());
|
||||
}
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
|
||||
Mat sample = imread(_tf("street.png"));
|
||||
ASSERT_TRUE(!sample.empty());
|
||||
|
||||
std::vector<int> layerIds;
|
||||
std::vector<size_t> weights, blobs;
|
||||
net.getMemoryConsumption(shape(1,3,227,227), CV_32F, layerIds, weights, blobs);
|
||||
|
||||
net.setInput(blobFromImage(sample, 1.0f, Size(500, 500), Scalar(), false), "data");
|
||||
|
||||
Mat out;
|
||||
// BUG: https://github.com/opencv/opencv/issues/26349
|
||||
if (net.getMainGraph())
|
||||
out = net.forward();
|
||||
else
|
||||
out = net.forward("score");
|
||||
|
||||
Mat refData = imread(_tf("caffe_fcn8s_prob.png"), IMREAD_ANYDEPTH);
|
||||
int shape[] = {1, 21, 500, 500};
|
||||
Mat ref(4, shape, CV_32FC1, refData.data);
|
||||
|
||||
normAssert(ref, out, "", 0.013, 0.17);
|
||||
}
|
||||
|
||||
TEST(Reproducibility_SSD, Accuracy)
|
||||
{
|
||||
applyTestTag(
|
||||
@@ -288,13 +90,19 @@ TEST(Reproducibility_SSD, Accuracy)
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
Net net;
|
||||
// The classic engine importer no longer carries the Caffe-SSD specific
|
||||
// handling (LpNormalization/DetectionOutput); this model is supported on
|
||||
// the new engine only.
|
||||
auto engine_forced = static_cast<cv::dnn::EngineType>(
|
||||
cv::utils::getConfigurationParameterSizeT("OPENCV_FORCE_DNN_ENGINE", cv::dnn::ENGINE_AUTO));
|
||||
if (engine_forced == cv::dnn::ENGINE_CLASSIC)
|
||||
{
|
||||
const string proto = findDataFile("dnn/ssd_vgg16.prototxt");
|
||||
const string model = findDataFile("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel", false);
|
||||
net = readNetFromCaffe(proto, model);
|
||||
ASSERT_FALSE(net.empty());
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_PARSER);
|
||||
return;
|
||||
}
|
||||
|
||||
Net net = readNetFromONNX(findDataFile("dnn/onnx/models/ssd_vgg16.onnx", false));
|
||||
ASSERT_FALSE(net.empty());
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
|
||||
Mat sample = imread(_tf("street.png"));
|
||||
@@ -304,334 +112,18 @@ TEST(Reproducibility_SSD, Accuracy)
|
||||
cvtColor(sample, sample, COLOR_BGRA2BGR);
|
||||
|
||||
Mat in_blob = blobFromImage(sample, 1.0f, Size(300, 300), Scalar(), false);
|
||||
net.setInput(in_blob, "data");
|
||||
net.setInput(in_blob);
|
||||
|
||||
// BUG: https://github.com/opencv/opencv/issues/26349
|
||||
Mat out;
|
||||
if(net.getMainGraph())
|
||||
out = net.forward();
|
||||
else
|
||||
out = net.forward("detection_out");
|
||||
Mat out = net.forward();
|
||||
|
||||
Mat ref = blobFromNPY(_tf("ssd_out.npy"));
|
||||
normAssertDetections(ref, out, "", 0.06);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<Backend, Target> > Reproducibility_MobileNet_SSD;
|
||||
TEST_P(Reproducibility_MobileNet_SSD, Accuracy)
|
||||
{
|
||||
const string proto = findDataFile("dnn/MobileNetSSD_deploy_19e3ec3.prototxt", false);
|
||||
const string model = findDataFile("dnn/MobileNetSSD_deploy_19e3ec3.caffemodel", false);
|
||||
Net net = readNetFromCaffe(proto, model);
|
||||
int backendId = get<0>(GetParam());
|
||||
int targetId = get<1>(GetParam());
|
||||
|
||||
net.setPreferableBackend(backendId);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
Mat sample = imread(_tf("street.png"));
|
||||
|
||||
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
|
||||
net.setInput(inp);
|
||||
Mat out = net.forward().clone();
|
||||
|
||||
ASSERT_EQ(out.size[2], 100);
|
||||
|
||||
float scores_diff = 1e-5, boxes_iou_diff = 1e-4;
|
||||
if (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD || targetId == DNN_TARGET_CPU_FP16)
|
||||
{
|
||||
scores_diff = 1.5e-2;
|
||||
boxes_iou_diff = 6.3e-2;
|
||||
}
|
||||
else if (targetId == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
scores_diff = 0.015;
|
||||
boxes_iou_diff = 0.07;
|
||||
}
|
||||
Mat ref = blobFromNPY(_tf("mobilenet_ssd_caffe_out.npy"));
|
||||
normAssertDetections(ref, out, "", FLT_MIN, scores_diff, boxes_iou_diff);
|
||||
|
||||
// Check that detections aren't preserved.
|
||||
inp.setTo(0.0f);
|
||||
net.setInput(inp);
|
||||
Mat zerosOut = net.forward();
|
||||
zerosOut = zerosOut.reshape(1, zerosOut.total() / 7);
|
||||
|
||||
const int numDetections = zerosOut.rows;
|
||||
// TODO: fix it
|
||||
if (targetId != DNN_TARGET_MYRIAD ||
|
||||
getInferenceEngineVPUType() != CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
|
||||
{
|
||||
ASSERT_NE(numDetections, 0);
|
||||
for (int i = 0; i < numDetections; ++i)
|
||||
{
|
||||
float confidence = zerosOut.ptr<float>(i)[2];
|
||||
ASSERT_EQ(confidence, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// There is something wrong with Reshape layer in Myriad plugin.
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019
|
||||
|| backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH
|
||||
)
|
||||
{
|
||||
if (targetId == DNN_TARGET_MYRIAD || targetId == DNN_TARGET_OPENCL_FP16)
|
||||
return;
|
||||
}
|
||||
|
||||
// Check batching mode.
|
||||
inp = blobFromImages(std::vector<Mat>(2, sample), 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
|
||||
net.setInput(inp);
|
||||
Mat outBatch = net.forward();
|
||||
|
||||
// Output blob has a shape 1x1x2Nx7 where N is a number of detection for
|
||||
// a single sample in batch. The first numbers of detection vectors are batch id.
|
||||
// For Inference Engine backend there is -1 delimiter which points the end of detections.
|
||||
const int numRealDetections = ref.size[2];
|
||||
EXPECT_EQ(outBatch.size[2], 2 * numDetections);
|
||||
out = out.reshape(1, numDetections).rowRange(0, numRealDetections);
|
||||
outBatch = outBatch.reshape(1, 2 * numDetections);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
Mat pred = outBatch.rowRange(i * numRealDetections, (i + 1) * numRealDetections);
|
||||
EXPECT_EQ(countNonZero(pred.col(0) != i), 0);
|
||||
normAssert(pred.colRange(1, 7), out.colRange(1, 7));
|
||||
}
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_MobileNet_SSD, dnnBackendsAndTargets());
|
||||
|
||||
typedef testing::TestWithParam<Target> Reproducibility_ResNet50;
|
||||
TEST_P(Reproducibility_ResNet50, Accuracy)
|
||||
{
|
||||
Target targetId = GetParam();
|
||||
applyTestTag(targetId == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB);
|
||||
ASSERT_TRUE(ocl::useOpenCL() || targetId == DNN_TARGET_CPU || targetId == DNN_TARGET_CPU_FP16);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/ResNet-50-deploy.prototxt"),
|
||||
findDataFile("dnn/ResNet-50-model.caffemodel", false));
|
||||
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
if (targetId == DNN_TARGET_CPU_FP16)
|
||||
net.enableWinograd(false);
|
||||
|
||||
float l1 = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_CPU_FP16) ? 3e-5 : 1e-5;
|
||||
float lInf = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_CPU_FP16) ? 6e-3 : 1e-4;
|
||||
|
||||
Mat input = blobFromImage(imread(_tf("googlenet_0.png")), 1.0f, Size(224,224), Scalar(), false);
|
||||
ASSERT_TRUE(!input.empty());
|
||||
|
||||
net.setInput(input);
|
||||
Mat out = net.forward();
|
||||
|
||||
Mat ref = blobFromNPY(_tf("resnet50_prob.npy"));
|
||||
normAssert(ref, out, "", l1, lInf);
|
||||
|
||||
if (targetId == DNN_TARGET_OPENCL || targetId == DNN_TARGET_OPENCL_FP16)
|
||||
{
|
||||
UMat out_umat;
|
||||
net.forward(out_umat);
|
||||
normAssert(ref, out_umat, "out_umat", l1, lInf);
|
||||
|
||||
std::vector<UMat> out_umats;
|
||||
net.forward(out_umats);
|
||||
normAssert(ref, out_umats[0], "out_umat_vector", l1, lInf);
|
||||
}
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_ResNet50,
|
||||
testing::ValuesIn(getAvailableTargets(DNN_BACKEND_OPENCV)));
|
||||
|
||||
typedef testing::TestWithParam<Target> Reproducibility_SqueezeNet_v1_1;
|
||||
TEST_P(Reproducibility_SqueezeNet_v1_1, Accuracy)
|
||||
{
|
||||
int targetId = GetParam();
|
||||
if(targetId == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if(targetId == DNN_TARGET_CPU_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/squeezenet_v1.1.prototxt"),
|
||||
findDataFile("dnn/squeezenet_v1.1.caffemodel", false));
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
Mat input = blobFromImage(imread(_tf("googlenet_0.png")), 1.0f, Size(227,227), Scalar(), false, true);
|
||||
ASSERT_TRUE(!input.empty());
|
||||
|
||||
Mat out;
|
||||
if (targetId == DNN_TARGET_OPENCL)
|
||||
{
|
||||
// Firstly set a wrong input blob and run the model to receive a wrong output.
|
||||
// Then set a correct input blob to check CPU->GPU synchronization is working well.
|
||||
net.setInput(input * 2.0f);
|
||||
out = net.forward();
|
||||
}
|
||||
net.setInput(input);
|
||||
out = net.forward();
|
||||
|
||||
Mat ref = blobFromNPY(_tf("squeezenet_v1.1_prob.npy"));
|
||||
normAssert(ref, out);
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_SqueezeNet_v1_1,
|
||||
testing::ValuesIn(getAvailableTargets(DNN_BACKEND_OPENCV)));
|
||||
|
||||
TEST(Reproducibility_AlexNet_fp16, Accuracy)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
const float l1 = 1e-5;
|
||||
const float lInf = 3e-3;
|
||||
|
||||
const string proto = findDataFile("dnn/bvlc_alexnet.prototxt");
|
||||
const string model = findDataFile("dnn/bvlc_alexnet.caffemodel", false);
|
||||
|
||||
shrinkCaffeModel(model, "bvlc_alexnet.caffemodel_fp16");
|
||||
Net net = readNetFromCaffe(proto, "bvlc_alexnet.caffemodel_fp16");
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/grace_hopper_227.png"));
|
||||
|
||||
net.setInput(blobFromImage(sample, 1.0f, Size(227, 227), Scalar()));
|
||||
Mat out = net.forward();
|
||||
Mat ref = blobFromNPY(findDataFile("dnn/caffe_alexnet_prob.npy"));
|
||||
normAssert(ref, out, "", l1, lInf);
|
||||
}
|
||||
|
||||
TEST(Reproducibility_GoogLeNet_fp16, Accuracy)
|
||||
{
|
||||
const float l1 = 1e-5;
|
||||
const float lInf = 3e-3;
|
||||
|
||||
const string proto = findDataFile("dnn/bvlc_googlenet.prototxt");
|
||||
const string model = findDataFile("dnn/bvlc_googlenet.caffemodel", false);
|
||||
|
||||
shrinkCaffeModel(model, "bvlc_googlenet.caffemodel_fp16");
|
||||
Net net = readNetFromCaffe(proto, "bvlc_googlenet.caffemodel_fp16");
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
|
||||
std::vector<Mat> inpMats;
|
||||
inpMats.push_back( imread(_tf("googlenet_0.png")) );
|
||||
inpMats.push_back( imread(_tf("googlenet_1.png")) );
|
||||
ASSERT_TRUE(!inpMats[0].empty() && !inpMats[1].empty());
|
||||
|
||||
net.setInput(blobFromImages(inpMats, 1.0f, Size(), Scalar(), false), "data");
|
||||
|
||||
// BUG: https://github.com/opencv/opencv/issues/26349
|
||||
Mat out;
|
||||
if(net.getMainGraph())
|
||||
out = net.forward();
|
||||
else
|
||||
out = net.forward("prob");
|
||||
|
||||
Mat ref = blobFromNPY(_tf("googlenet_prob.npy"));
|
||||
normAssert(out, ref, "", l1, lInf);
|
||||
}
|
||||
|
||||
// https://github.com/richzhang/colorization
|
||||
TEST_P(Test_Caffe_nets, Colorization)
|
||||
{
|
||||
applyTestTag(
|
||||
target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
checkBackend();
|
||||
|
||||
Mat inp = blobFromNPY(_tf("colorization_inp.npy"));
|
||||
Mat ref = blobFromNPY(_tf("colorization_out.npy"));
|
||||
Mat kernel = blobFromNPY(_tf("colorization_pts_in_hull.npy"));
|
||||
|
||||
const string proto = findDataFile("dnn/colorization_deploy_v2.prototxt", false);
|
||||
const string model = findDataFile("dnn/colorization_release_v2.caffemodel", false);
|
||||
Net net = readNetFromCaffe(proto, model);
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
|
||||
// This model has bad accuracy when the FP16 and Winograd are enable at same time.
|
||||
if (target == DNN_TARGET_CPU_FP16)
|
||||
net.enableWinograd(false);
|
||||
|
||||
net.getLayer(net.getLayerId("class8_ab"))->blobs.push_back(kernel);
|
||||
net.getLayer(net.getLayerId("conv8_313_rh"))->blobs.push_back(Mat(1, 313, CV_32F, 2.606));
|
||||
|
||||
net.setInput(inp);
|
||||
Mat out = net.forward();
|
||||
|
||||
// Reference output values are in range [-29.1, 69.5]
|
||||
double l1 = 4e-4, lInf = 3e-3;
|
||||
if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16)
|
||||
{
|
||||
l1 = 0.25;
|
||||
lInf = 5.3;
|
||||
}
|
||||
else if (target == DNN_TARGET_MYRIAD)
|
||||
{
|
||||
l1 = (getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) ? 0.5 : 0.25;
|
||||
lInf = (getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) ? 11 : 5.3;
|
||||
}
|
||||
else if(target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
l1 = 0.21;
|
||||
lInf = 4.5;
|
||||
}
|
||||
#if defined(INF_ENGINE_RELEASE)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
{
|
||||
l1 = 0.3; lInf = 10;
|
||||
}
|
||||
#endif
|
||||
|
||||
normAssert(out, ref, "", l1, lInf);
|
||||
expectNoFallbacksFromIE(net);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_nets, DenseNet_121)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
checkBackend();
|
||||
const string proto = findDataFile("dnn/DenseNet_121.prototxt", false);
|
||||
const string weights = findDataFile("dnn/DenseNet_121.caffemodel", false);
|
||||
|
||||
Mat inp = imread(_tf("dog416.png"));
|
||||
Model model(proto, weights);
|
||||
model.setInputScale(1.0 / 255).setInputSwapRB(true).setInputCrop(true);
|
||||
std::vector<Mat> outs;
|
||||
Mat ref = blobFromNPY(_tf("densenet_121_output.npy"));
|
||||
|
||||
model.setPreferableBackend(backend);
|
||||
model.setPreferableTarget(target);
|
||||
model.predict(inp, outs);
|
||||
|
||||
// Reference is an array of 1000 values from a range [-6.16, 7.9]
|
||||
float l1 = default_l1, lInf = default_lInf;
|
||||
if (target == DNN_TARGET_OPENCL_FP16)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019020000)
|
||||
l1 = 0.05; lInf = 0.3;
|
||||
#else
|
||||
l1 = 0.017; lInf = 0.0795;
|
||||
#endif
|
||||
}
|
||||
else if (target == DNN_TARGET_MYRIAD)
|
||||
{
|
||||
l1 = 0.11; lInf = 0.5;
|
||||
}
|
||||
else if (target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
l1 = 0.04; lInf = 0.2;
|
||||
}
|
||||
else if (target == DNN_TARGET_CPU_FP16)
|
||||
{
|
||||
l1 = 0.06; lInf = 0.3;
|
||||
}
|
||||
|
||||
normAssert(outs[0], ref, "", l1, lInf);
|
||||
if (target != DNN_TARGET_MYRIAD || getInferenceEngineVPUType() != CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
|
||||
expectNoFallbacksFromIE(model.getNetwork_());
|
||||
normAssertDetections(ref, out, "", 0.06, 1e-4, 0.18);
|
||||
}
|
||||
|
||||
TEST(Test_Caffe, multiple_inputs)
|
||||
{
|
||||
const string proto = findDataFile("dnn/layers/net_input.prototxt");
|
||||
Net net = readNetFromCaffe(proto);
|
||||
const string model = findDataFile("dnn/layers/net_input.onnx");
|
||||
Net net = readNetFromONNX(model);
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
|
||||
Mat first_image(10, 11, CV_32FC3);
|
||||
@@ -656,239 +148,6 @@ TEST(Test_Caffe, multiple_inputs)
|
||||
normAssert(out, first_image + second_image);
|
||||
}
|
||||
|
||||
TEST(Test_Caffe, shared_weights)
|
||||
{
|
||||
const string proto = findDataFile("dnn/layers/shared_weights.prototxt");
|
||||
const string model = findDataFile("dnn/layers/shared_weights.caffemodel");
|
||||
|
||||
Net net = readNetFromCaffe(proto, model);
|
||||
|
||||
Mat input_1 = (Mat_<float>(2, 2) << 0., 2., 4., 6.);
|
||||
Mat input_2 = (Mat_<float>(2, 2) << 1., 3., 5., 7.);
|
||||
|
||||
Mat blob_1 = blobFromImage(input_1);
|
||||
Mat blob_2 = blobFromImage(input_2);
|
||||
|
||||
net.setInput(blob_1, "input_1");
|
||||
net.setInput(blob_2, "input_2");
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
|
||||
Mat sum = net.forward();
|
||||
|
||||
EXPECT_EQ(sum.at<float>(0,0), 12.);
|
||||
EXPECT_EQ(sum.at<float>(0,1), 16.);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<std::string, Target> > opencv_face_detector;
|
||||
TEST_P(opencv_face_detector, Accuracy)
|
||||
{
|
||||
std::string proto = findDataFile("dnn/opencv_face_detector.prototxt");
|
||||
std::string model = findDataFile(get<0>(GetParam()), false);
|
||||
dnn::Target targetId = (dnn::Target)(int)get<1>(GetParam());
|
||||
|
||||
if (targetId == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (targetId == DNN_TARGET_CPU_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
|
||||
|
||||
Net net = readNetFromCaffe(proto, model);
|
||||
Mat img = imread(findDataFile("gpu/lbpcascade/er.png"));
|
||||
Mat blob = blobFromImage(img, 1.0, Size(), Scalar(104.0, 177.0, 123.0), false, false);
|
||||
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
net.setInput(blob);
|
||||
// Output has shape 1x1xNx7 where N - number of detections.
|
||||
// An every detection is a vector of values [id, classId, confidence, left, top, right, bottom]
|
||||
Mat out = net.forward();
|
||||
Mat ref = (Mat_<float>(6, 7) << 0, 1, 0.99520785, 0.80997437, 0.16379407, 0.87996572, 0.26685631,
|
||||
0, 1, 0.9934696, 0.2831718, 0.50738752, 0.345781, 0.5985168,
|
||||
0, 1, 0.99096733, 0.13629119, 0.24892329, 0.19756334, 0.3310290,
|
||||
0, 1, 0.98977017, 0.23901358, 0.09084064, 0.29902688, 0.1769477,
|
||||
0, 1, 0.97203469, 0.67965847, 0.06876482, 0.73999709, 0.1513494,
|
||||
0, 1, 0.95097077, 0.51901293, 0.45863652, 0.5777427, 0.5347801);
|
||||
normAssertDetections(ref, out, "", 0.5, 1e-4, 2e-4);
|
||||
}
|
||||
|
||||
// False positives bug for large faces: https://github.com/opencv/opencv/issues/15106
|
||||
TEST_P(opencv_face_detector, issue_15106)
|
||||
{
|
||||
std::string proto = findDataFile("dnn/opencv_face_detector.prototxt");
|
||||
std::string model = findDataFile(get<0>(GetParam()), false);
|
||||
dnn::Target targetId = (dnn::Target)(int)get<1>(GetParam());
|
||||
|
||||
if (targetId == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (targetId == DNN_TARGET_CPU_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
|
||||
|
||||
Net net = readNetFromCaffe(proto, model);
|
||||
Mat img = imread(findDataFile("cv/shared/lena.png"));
|
||||
img = img.rowRange(img.rows / 4, 3 * img.rows / 4).colRange(img.cols / 4, 3 * img.cols / 4);
|
||||
Mat blob = blobFromImage(img, 1.0, Size(300, 300), Scalar(104.0, 177.0, 123.0), false, false);
|
||||
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
net.setInput(blob);
|
||||
// Output has shape 1x1xNx7 where N - number of detections.
|
||||
// An every detection is a vector of values [id, classId, confidence, left, top, right, bottom]
|
||||
Mat out = net.forward();
|
||||
Mat ref = (Mat_<float>(1, 7) << 0, 1, 0.9149431, 0.30424616, 0.26964942, 0.88733053, 0.99815309);
|
||||
normAssertDetections(ref, out, "", 0.89, 6e-5, 1e-4);
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(Test_Caffe, opencv_face_detector,
|
||||
Combine(
|
||||
Values("dnn/opencv_face_detector.caffemodel",
|
||||
"dnn/opencv_face_detector_fp16.caffemodel"),
|
||||
testing::ValuesIn(getAvailableTargets(DNN_BACKEND_OPENCV))
|
||||
)
|
||||
);
|
||||
|
||||
TEST_P(Test_Caffe_nets, FasterRCNN_vgg16)
|
||||
{
|
||||
applyTestTag(
|
||||
#if defined(OPENCV_32BIT_CONFIGURATION) && defined(HAVE_OPENCL)
|
||||
CV_TEST_TAG_MEMORY_2GB, // utilizes ~1Gb, but huge blobs may not be allocated on 32-bit systems due memory fragmentation
|
||||
#else
|
||||
CV_TEST_TAG_MEMORY_2GB,
|
||||
#endif
|
||||
CV_TEST_TAG_LONG,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
|
||||
if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16);
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
|
||||
#endif
|
||||
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
|
||||
// IE exception: Ngraph operation Reshape with name rpn_cls_score_reshape has dynamic output shape on 0 port, but CPU plug-in supports only static shape
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION
|
||||
);
|
||||
// Check 'backward_compatible_check || in_out_elements_equal' failed at core/src/op/reshape.cpp:390:
|
||||
// While validating node 'v1::Reshape bbox_pred_reshape (bbox_pred[0]:f32{1,84}, Constant_241202[0]:i64{4}) -> (f32{?,?,?,?})' with friendly_name 'bbox_pred_reshape':
|
||||
// Requested output shape {1,6300,4,1} is incompatible with input shape Shape{1, 84}
|
||||
if (target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
double scoreDiff = 0.0012, iouDiff = 0.03;
|
||||
#if defined(INF_ENGINE_RELEASE)
|
||||
if (target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) {
|
||||
iouDiff = 0.02;
|
||||
if (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16) {
|
||||
scoreDiff = 0.04;
|
||||
iouDiff = 0.06;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static Mat ref = (Mat_<float>(3, 7) << 0, 2, 0.949398, 99.2454, 210.141, 601.205, 462.849,
|
||||
0, 7, 0.997022, 481.841, 92.3218, 722.685, 175.953,
|
||||
0, 12, 0.993028, 133.221, 189.377, 350.994, 563.166);
|
||||
testFaster("faster_rcnn_vgg16.prototxt", "VGG16_faster_rcnn_final.caffemodel", ref, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_nets, FasterRCNN_zf)
|
||||
{
|
||||
applyTestTag(
|
||||
#if defined(OPENCV_32BIT_CONFIGURATION) && defined(HAVE_OPENCL)
|
||||
CV_TEST_TAG_MEMORY_2GB,
|
||||
#else
|
||||
(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB),
|
||||
#endif
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
|
||||
// IE exception: Ngraph operation Reshape with name rpn_cls_score_reshape has dynamic output shape on 0 port, but CPU plug-in supports only static shape
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION
|
||||
);
|
||||
#endif
|
||||
|
||||
if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 ||
|
||||
backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
|
||||
if (target == DNN_TARGET_CUDA_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16);
|
||||
if (target == DNN_TARGET_CPU_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
|
||||
static Mat ref = (Mat_<float>(3, 7) << 0, 2, 0.90121, 120.407, 115.83, 570.586, 528.395,
|
||||
0, 7, 0.988779, 469.849, 75.1756, 718.64, 186.762,
|
||||
0, 12, 0.967198, 138.588, 206.843, 329.766, 553.176);
|
||||
|
||||
double scoreDiff = 0.003, iouDiff = 0.07;
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) {
|
||||
scoreDiff = 0.02;
|
||||
iouDiff = 0.13;
|
||||
}
|
||||
|
||||
testFaster("faster_rcnn_zf.prototxt", "ZF_faster_rcnn_final.caffemodel", ref, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_nets, RFCN)
|
||||
{
|
||||
applyTestTag(
|
||||
(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_2GB),
|
||||
CV_TEST_TAG_LONG,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
float scoreDiff = default_l1, iouDiff = default_lInf;
|
||||
if (backend == DNN_BACKEND_OPENCV && (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16))
|
||||
{
|
||||
scoreDiff = 4e-3;
|
||||
iouDiff = 8e-2;
|
||||
}
|
||||
if (target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
scoreDiff = 0.0034;
|
||||
iouDiff = 0.12;
|
||||
}
|
||||
|
||||
#if defined(INF_ENGINE_RELEASE)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
{
|
||||
scoreDiff = 0.1f;
|
||||
iouDiff = 0.2f;
|
||||
}
|
||||
|
||||
// Check 'backward_compatible_check || in_out_elements_equal' failed at core/src/op/reshape.cpp:427:
|
||||
// While validating node 'v1::Reshape bbox_pred_reshape (ave_bbox_pred_rois[0]:f32{1,8,1,1}, Constant_388[0]:i64{4}) -> (f32{?,?,?,?})' with friendly_name 'bbox_pred_reshape':
|
||||
// Requested output shape {1,300,8,1} is incompatible with input shape {1, 8, 1, 1}
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#elif defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
|
||||
// Exception: Function contains several inputs and outputs with one friendly name! (HETERO bug?)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#elif defined(INF_ENGINE_RELEASE)
|
||||
if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 ||
|
||||
backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16);
|
||||
if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 ||
|
||||
backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
|
||||
#endif
|
||||
|
||||
static Mat ref = (Mat_<float>(2, 7) << 0, 7, 0.991359, 491.822, 81.1668, 702.573, 178.234,
|
||||
0, 12, 0.94786, 132.093, 223.903, 338.077, 566.16);
|
||||
testFaster("rfcn_pascal_voc_resnet50.prototxt", "resnet50_rfcn_final.caffemodel", ref, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Test_Caffe_nets, dnnBackendsAndTargets());
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "npy_blob.hpp"
|
||||
#include <opencv2/core/ocl.hpp>
|
||||
#include <opencv2/ts/ocl_test.hpp>
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
template<typename TString>
|
||||
static std::string _tf(TString filename)
|
||||
{
|
||||
return (getOpenCVExtraDir() + "/dnn/") + filename;
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<Target> Reproducibility_GoogLeNet;
|
||||
TEST_P(Reproducibility_GoogLeNet, Batching)
|
||||
{
|
||||
const int targetId = GetParam();
|
||||
if (targetId == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (targetId == DNN_TARGET_CPU_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/bvlc_googlenet.prototxt"),
|
||||
findDataFile("dnn/bvlc_googlenet.caffemodel", false));
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
if (targetId == DNN_TARGET_OPENCL)
|
||||
{
|
||||
// Initialize network for a single image in the batch but test with batch size=2.
|
||||
Mat inp = Mat(224, 224, CV_8UC3);
|
||||
randu(inp, -1, 1);
|
||||
net.setInput(blobFromImage(inp));
|
||||
net.forward();
|
||||
}
|
||||
|
||||
std::vector<Mat> inpMats;
|
||||
inpMats.push_back( imread(_tf("googlenet_0.png")) );
|
||||
inpMats.push_back( imread(_tf("googlenet_1.png")) );
|
||||
ASSERT_TRUE(!inpMats[0].empty() && !inpMats[1].empty());
|
||||
|
||||
net.setInput(blobFromImages(inpMats, 1.0f, Size(), Scalar(), false), "data");
|
||||
|
||||
// BUG: https://github.com/opencv/opencv/issues/26349
|
||||
Mat out;
|
||||
if(net.getMainGraph())
|
||||
out = net.forward();
|
||||
else
|
||||
out = net.forward("prob");
|
||||
|
||||
Mat ref = blobFromNPY(_tf("googlenet_prob.npy"));
|
||||
normAssert(out, ref);
|
||||
}
|
||||
|
||||
TEST_P(Reproducibility_GoogLeNet, IntermediateBlobs)
|
||||
{
|
||||
const int targetId = GetParam();
|
||||
if (targetId == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (targetId == DNN_TARGET_CPU_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
|
||||
// BUG: https://github.com/opencv/opencv/issues/26349
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/bvlc_googlenet.prototxt"),
|
||||
findDataFile("dnn/bvlc_googlenet.caffemodel", false), ENGINE_CLASSIC);
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
std::vector<String> blobsNames;
|
||||
blobsNames.push_back("conv1/7x7_s2");
|
||||
blobsNames.push_back("conv1/relu_7x7");
|
||||
blobsNames.push_back("inception_4c/1x1");
|
||||
blobsNames.push_back("inception_4c/relu_1x1");
|
||||
std::vector<Mat> outs;
|
||||
Mat in = blobFromImage(imread(_tf("googlenet_0.png")), 1.0f, Size(), Scalar(), false);
|
||||
net.setInput(in, "data");
|
||||
net.forward(outs, blobsNames);
|
||||
CV_Assert(outs.size() == blobsNames.size());
|
||||
|
||||
for (size_t i = 0; i < blobsNames.size(); i++)
|
||||
{
|
||||
std::string filename = blobsNames[i];
|
||||
std::replace( filename.begin(), filename.end(), '/', '#');
|
||||
Mat ref = blobFromNPY(_tf("googlenet_" + filename + ".npy"));
|
||||
|
||||
normAssert(outs[i], ref, "", 1E-4, 1E-2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Reproducibility_GoogLeNet, SeveralCalls)
|
||||
{
|
||||
const int targetId = GetParam();
|
||||
if (targetId == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (targetId == DNN_TARGET_CPU_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
|
||||
// BUG: https://github.com/opencv/opencv/issues/26349
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/bvlc_googlenet.prototxt"),
|
||||
findDataFile("dnn/bvlc_googlenet.caffemodel", false), ENGINE_CLASSIC);
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
std::vector<Mat> inpMats;
|
||||
inpMats.push_back( imread(_tf("googlenet_0.png")) );
|
||||
inpMats.push_back( imread(_tf("googlenet_1.png")) );
|
||||
ASSERT_TRUE(!inpMats[0].empty() && !inpMats[1].empty());
|
||||
|
||||
net.setInput(blobFromImages(inpMats, 1.0f, Size(), Scalar(), false), "data");
|
||||
Mat out = net.forward();
|
||||
|
||||
Mat ref = blobFromNPY(_tf("googlenet_prob.npy"));
|
||||
normAssert(out, ref);
|
||||
|
||||
std::vector<String> blobsNames;
|
||||
blobsNames.push_back("conv1/7x7_s2");
|
||||
std::vector<Mat> outs;
|
||||
Mat in = blobFromImage(inpMats[0], 1.0f, Size(), Scalar(), false);
|
||||
net.setInput(in, "data");
|
||||
net.forward(outs, blobsNames);
|
||||
CV_Assert(outs.size() == blobsNames.size());
|
||||
|
||||
ref = blobFromNPY(_tf("googlenet_conv1#7x7_s2.npy"));
|
||||
|
||||
normAssert(outs[0], ref, "", 1E-4, 1E-2);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Reproducibility_GoogLeNet,
|
||||
testing::ValuesIn(getAvailableTargets(DNN_BACKEND_OPENCV)));
|
||||
|
||||
}} // namespace
|
||||
@@ -46,16 +46,7 @@ public:
|
||||
String inpPath, outPath;
|
||||
Net net, qnet;
|
||||
|
||||
if (importer == "Caffe")
|
||||
{
|
||||
String prototxt = _tf("layers/" + basename + ".prototxt");
|
||||
String caffemodel = _tf("layers/" + basename + ".caffemodel");
|
||||
net = readNetFromCaffe(prototxt, useCaffeModel ? caffemodel : String());
|
||||
|
||||
inpPath = _tf("layers/" + (useCommonInputBlob ? "blob" : basename + ".input"));
|
||||
outPath = _tf("layers/" + basename);
|
||||
}
|
||||
else if (importer == "TensorFlow")
|
||||
if (importer == "TensorFlow")
|
||||
{
|
||||
String netPath = _tf("tensorflow/" + basename + "_net.pb");
|
||||
String netConfig = hasText ? _tf("tensorflow/" + basename + "_net.pbtxt") : "";
|
||||
@@ -768,121 +759,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(Test_Int8_nets, AlexNet)
|
||||
{
|
||||
#if defined(OPENCV_32BIT_CONFIGURATION) && defined(HAVE_OPENCL)
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_2GB);
|
||||
#else
|
||||
applyTestTag(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB);
|
||||
#endif
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/bvlc_alexnet.prototxt"),
|
||||
findDataFile("dnn/bvlc_alexnet.caffemodel", false));
|
||||
|
||||
Mat inp = imread(_tf("grace_hopper_227.png"));
|
||||
Mat blob = blobFromImage(inp, 1.0, Size(227, 227), Scalar(), false);
|
||||
Mat ref = blobFromNPY(_tf("caffe_alexnet_prob.npy"));
|
||||
|
||||
float l1 = 1e-4, lInf = 0.003;
|
||||
testClassificationNet(net, blob, ref, l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, GoogLeNet)
|
||||
{
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/bvlc_googlenet.prototxt"),
|
||||
findDataFile("dnn/bvlc_googlenet.caffemodel", false));
|
||||
|
||||
std::vector<Mat> inpMats;
|
||||
inpMats.push_back( imread(_tf("googlenet_0.png")) );
|
||||
inpMats.push_back( imread(_tf("googlenet_1.png")) );
|
||||
Mat blob = blobFromImages(inpMats, 1.0, Size(224, 224), Scalar(), false);
|
||||
Mat ref = blobFromNPY(_tf("googlenet_prob.npy"));
|
||||
|
||||
float l1 = 2e-4, lInf = 0.07;
|
||||
testClassificationNet(net, blob, ref, l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, ResNet50)
|
||||
{
|
||||
applyTestTag(
|
||||
target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/ResNet-50-deploy.prototxt"),
|
||||
findDataFile("dnn/ResNet-50-model.caffemodel", false));
|
||||
|
||||
Mat inp = imread(_tf("googlenet_0.png"));
|
||||
Mat blob = blobFromImage(inp, 1.0, Size(224, 224), Scalar(), false);
|
||||
Mat ref = blobFromNPY(_tf("resnet50_prob.npy"));
|
||||
|
||||
float l1 = 3e-4, lInf = 0.05;
|
||||
testClassificationNet(net, blob, ref, l1, lInf);
|
||||
|
||||
{
|
||||
SCOPED_TRACE("Per-tensor quantize");
|
||||
testClassificationNet(net, blob, ref, l1, lInf, false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, DenseNet121)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/DenseNet_121.prototxt", false),
|
||||
findDataFile("dnn/DenseNet_121.caffemodel", false));
|
||||
|
||||
Mat inp = imread(_tf("dog416.png"));
|
||||
Mat blob = blobFromImage(inp, 1.0 / 255.0, Size(224, 224), Scalar(), true, true);
|
||||
Mat ref = blobFromNPY(_tf("densenet_121_output.npy"));
|
||||
|
||||
float l1 = 0.76, lInf = 3.31; // seems wrong
|
||||
testClassificationNet(net, blob, ref, l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, SqueezeNet_v1_1)
|
||||
{
|
||||
if(target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/squeezenet_v1.1.prototxt"),
|
||||
findDataFile("dnn/squeezenet_v1.1.caffemodel", false));
|
||||
|
||||
Mat inp = imread(_tf("googlenet_0.png"));
|
||||
Mat blob = blobFromImage(inp, 1.0, Size(227, 227), Scalar(), false, true);
|
||||
Mat ref = blobFromNPY(_tf("squeezenet_v1.1_prob.npy"));
|
||||
|
||||
float l1 = 3e-4, lInf = 0.056;
|
||||
testClassificationNet(net, blob, ref, l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, CaffeNet)
|
||||
{
|
||||
#if defined(OPENCV_32BIT_CONFIGURATION) && (defined(HAVE_OPENCL) || defined(_WIN32))
|
||||
@@ -947,24 +823,6 @@ TEST_P(Test_Int8_nets, Shufflenet)
|
||||
testONNXNet("shufflenet", default_l1, default_lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, MobileNet_SSD)
|
||||
{
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/MobileNetSSD_deploy_19e3ec3.prototxt", false),
|
||||
findDataFile("dnn/MobileNetSSD_deploy_19e3ec3.caffemodel", false));
|
||||
|
||||
Mat inp = imread(_tf("street.png"));
|
||||
Mat blob = blobFromImage(inp, 1.0 / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
|
||||
Mat ref = blobFromNPY(_tf("mobilenet_ssd_caffe_out.npy"));
|
||||
|
||||
float confThreshold = FLT_MIN, scoreDiff = 0.084, iouDiff = 0.43;
|
||||
testDetectionNet(net, blob, ref, confThreshold, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, MobileNet_v1_SSD)
|
||||
{
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
@@ -1025,31 +883,6 @@ TEST_P(Test_Int8_nets, Inception_v2_SSD)
|
||||
testDetectionNet(net, blob, ref, confThreshold, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, opencv_face_detector)
|
||||
{
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/opencv_face_detector.prototxt"),
|
||||
findDataFile("dnn/opencv_face_detector.caffemodel", false));
|
||||
|
||||
Mat inp = imread(findDataFile("gpu/lbpcascade/er.png"));
|
||||
Mat blob = blobFromImage(inp, 1.0, Size(), Scalar(104.0, 177.0, 123.0), false, false);
|
||||
Mat ref = (Mat_<float>(6, 7) << 0, 1, 0.99520785, 0.80997437, 0.16379407, 0.87996572, 0.26685631,
|
||||
0, 1, 0.9934696, 0.2831718, 0.50738752, 0.345781, 0.5985168,
|
||||
0, 1, 0.99096733, 0.13629119, 0.24892329, 0.19756334, 0.3310290,
|
||||
0, 1, 0.98977017, 0.23901358, 0.09084064, 0.29902688, 0.1769477,
|
||||
0, 1, 0.97203469, 0.67965847, 0.06876482, 0.73999709, 0.1513494,
|
||||
0, 1, 0.95097077, 0.51901293, 0.45863652, 0.5777427, 0.5347801);
|
||||
|
||||
float confThreshold = 0.5, scoreDiff = 0.002, iouDiff = 0.4;
|
||||
testDetectionNet(net, blob, ref, confThreshold, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, EfficientDet)
|
||||
{
|
||||
if (cvtest::skipUnstableTests)
|
||||
@@ -1143,91 +976,6 @@ TEST_P(Test_Int8_nets, FasterRCNN_inceptionv2)
|
||||
testDetectionNet(net, blob, ref, confThreshold, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, FasterRCNN_vgg16)
|
||||
{
|
||||
applyTestTag(
|
||||
#if defined(OPENCV_32BIT_CONFIGURATION) && defined(HAVE_OPENCL)
|
||||
CV_TEST_TAG_MEMORY_2GB,
|
||||
#else
|
||||
CV_TEST_TAG_MEMORY_2GB,
|
||||
#endif
|
||||
CV_TEST_TAG_LONG,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/faster_rcnn_vgg16.prototxt"),
|
||||
findDataFile("dnn/VGG16_faster_rcnn_final.caffemodel", false));
|
||||
|
||||
Mat ref = (Mat_<float>(3, 7) << 0, 2, 0.949398, 99.2454, 210.141, 601.205, 462.849,
|
||||
0, 7, 0.997022, 481.841, 92.3218, 722.685, 175.953,
|
||||
0, 12, 0.993028, 133.221, 189.377, 350.994, 563.166);
|
||||
|
||||
float confThreshold = 0.8, scoreDiff = 0.048, iouDiff = 0.35;
|
||||
testFaster(net, ref, confThreshold, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, FasterRCNN_zf)
|
||||
{
|
||||
applyTestTag(
|
||||
#if defined(OPENCV_32BIT_CONFIGURATION) && defined(HAVE_OPENCL)
|
||||
CV_TEST_TAG_MEMORY_2GB,
|
||||
#else
|
||||
(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB),
|
||||
#endif
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/faster_rcnn_zf.prototxt"),
|
||||
findDataFile("dnn/ZF_faster_rcnn_final.caffemodel", false));
|
||||
|
||||
Mat ref = (Mat_<float>(3, 7) << 0, 2, 0.90121, 120.407, 115.83, 570.586, 528.395,
|
||||
0, 7, 0.988779, 469.849, 75.1756, 718.64, 186.762,
|
||||
0, 12, 0.967198, 138.588, 206.843, 329.766, 553.176);
|
||||
|
||||
float confThreshold = 0.8, scoreDiff = 0.021, iouDiff = 0.1;
|
||||
testFaster(net, ref, confThreshold, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, RFCN)
|
||||
{
|
||||
applyTestTag(
|
||||
(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_2GB),
|
||||
CV_TEST_TAG_LONG,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
if (target == DNN_TARGET_OPENCL_FP16 && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (target == DNN_TARGET_OPENCL && !ocl::Device::getDefault().isIntel())
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
|
||||
Net net = readNetFromCaffe(findDataFile("dnn/rfcn_pascal_voc_resnet50.prototxt"),
|
||||
findDataFile("dnn/resnet50_rfcn_final.caffemodel", false));
|
||||
|
||||
Mat ref = (Mat_<float>(2, 7) << 0, 7, 0.991359, 491.822, 81.1668, 702.573, 178.234,
|
||||
0, 12, 0.94786, 132.093, 223.903, 338.077, 566.16);
|
||||
|
||||
float confThreshold = 0.8, scoreDiff = 0.15, iouDiff = 0.11;
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) {
|
||||
iouDiff = 0.12;
|
||||
}
|
||||
testFaster(net, ref, confThreshold, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
TEST_P(Test_Int8_nets, YOLOv3)
|
||||
{
|
||||
applyTestTag(
|
||||
|
||||
@@ -63,155 +63,6 @@ static String _tf(TString filename)
|
||||
return (basetestdir + "dnn/layers/") + filename;
|
||||
}
|
||||
|
||||
class Test_Caffe_layers : public DNNTestLayer
|
||||
{
|
||||
public:
|
||||
void testLayerUsingCaffeModels(const String& basename, bool useCaffeModel = false,
|
||||
bool useCommonInputBlob = true, double l1 = 0.0, double lInf = 0.0,
|
||||
int numInps = 1, int numOuts = 1)
|
||||
{
|
||||
CV_Assert_N(numInps >= 1, numInps <= 10, numOuts >= 1, numOuts <= 10);
|
||||
String prototxt = _tf(basename + ".prototxt");
|
||||
String caffemodel = _tf(basename + ".caffemodel");
|
||||
|
||||
std::vector<Mat> inps, refs, outs;
|
||||
|
||||
if (numInps > 1)
|
||||
{
|
||||
for (int i = 0; i < numInps; i++)
|
||||
{
|
||||
String inpfile = _tf(basename + cv::format(".input_%d.npy", i));
|
||||
inps.push_back(blobFromNPY(inpfile));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy");
|
||||
inps.push_back(blobFromNPY(inpfile));
|
||||
}
|
||||
|
||||
if (numOuts > 1)
|
||||
{
|
||||
for (int i = 0; i < numOuts; i++)
|
||||
{
|
||||
String outfile = _tf(basename + cv::format("_%d.npy", i));
|
||||
refs.push_back(blobFromNPY(outfile));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String outfile = _tf(basename + ".npy");
|
||||
refs.push_back(blobFromNPY(outfile));
|
||||
}
|
||||
|
||||
Net net = readNetFromCaffe(prototxt, (useCaffeModel) ? caffemodel : String());
|
||||
ASSERT_FALSE(net.empty());
|
||||
checkBackend(&inps[0], &refs[0]);
|
||||
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
|
||||
String inp_name = "input";
|
||||
if (numInps > 1)
|
||||
{
|
||||
for (int i = 0; i < numInps; i++)
|
||||
{
|
||||
net.setInput(inps[i], inp_name + cv::format("_%d", i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
net.setInput(inps.back(), inp_name);
|
||||
}
|
||||
|
||||
net.forward(outs);
|
||||
for (int i = 0; i < refs.size(); i++)
|
||||
{
|
||||
normAssert(refs[i], outs[i], "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(Test_Caffe_layers, Softmax)
|
||||
{
|
||||
testLayerUsingCaffeModels("layer_softmax");
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, LRN)
|
||||
{
|
||||
double l1 = 0.0, lInf = 0.0;
|
||||
// The OpenCL kernels use the native_ math functions which have
|
||||
// implementation defined accuracy, so we use relaxed thresholds. See
|
||||
// https://github.com/opencv/opencv/issues/9821 for more details.
|
||||
if (target == DNN_TARGET_OPENCL)
|
||||
{
|
||||
l1 = 0.01;
|
||||
lInf = 0.01;
|
||||
}
|
||||
testLayerUsingCaffeModels("layer_lrn_spatial", false, true, l1, lInf);
|
||||
testLayerUsingCaffeModels("layer_lrn_channels", false, true, l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Convolution)
|
||||
{
|
||||
testLayerUsingCaffeModels("layer_convolution", true);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, DeConvolution)
|
||||
{
|
||||
if(target == DNN_TARGET_CUDA_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16);
|
||||
testLayerUsingCaffeModels("layer_deconvolution", true, false);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, InnerProduct)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
#endif
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
|
||||
// IE exception: Ngraph operation Reshape with name Reshape_4219609 has dynamic output shape on 0 port, but CPU plug-in supports only static shape
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION
|
||||
);
|
||||
#endif
|
||||
|
||||
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_CPU_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
|
||||
|
||||
double l1 = 0.0, lInf = 0.0;
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
{
|
||||
l1 = 5e-3;
|
||||
lInf = 2e-2;
|
||||
}
|
||||
testLayerUsingCaffeModels("layer_inner_product", true, true, l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Pooling_max)
|
||||
{
|
||||
testLayerUsingCaffeModels("layer_pooling_max");
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Pooling_ave)
|
||||
{
|
||||
testLayerUsingCaffeModels("layer_pooling_ave");
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, MVN)
|
||||
{
|
||||
if(backend == DNN_BACKEND_CUDA)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA); /* MVN is unsupported */
|
||||
|
||||
testLayerUsingCaffeModels("layer_mvn");
|
||||
}
|
||||
|
||||
void testReshape(const MatShape& inputShape, const MatShape& targetShape,
|
||||
int axis = 0, int num_axes = -1,
|
||||
MatShape mask = MatShape())
|
||||
@@ -259,192 +110,6 @@ TEST(Layer_Test_Reshape, Accuracy)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, BatchNorm)
|
||||
{
|
||||
testLayerUsingCaffeModels("layer_batch_norm", true);
|
||||
testLayerUsingCaffeModels("layer_batch_norm_local_stats", true, false);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, ReLU)
|
||||
{
|
||||
testLayerUsingCaffeModels("layer_relu");
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Dropout)
|
||||
{
|
||||
testLayerUsingCaffeModels("layer_dropout");
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Concat)
|
||||
{
|
||||
if (cvtest::skipUnstableTests && (backend == DNN_BACKEND_VKCOM))
|
||||
{
|
||||
throw SkipTestException("Test_Caffe_layers.Concat test produces unstable result with Vulkan");
|
||||
}
|
||||
|
||||
#if defined(INF_ENGINE_RELEASE)
|
||||
#if INF_ENGINE_VER_MAJOR_GE(2019010000) && INF_ENGINE_VER_MAJOR_LT(2019020000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#elif INF_ENGINE_VER_MAJOR_EQ(2019020000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 &&
|
||||
(target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
#if INF_ENGINE_VER_MAJOR_LT(2021040000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH &&
|
||||
(target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
testLayerUsingCaffeModels("layer_concat");
|
||||
testLayerUsingCaffeModels("layer_concat_optim", true, false);
|
||||
testLayerUsingCaffeModels("layer_concat_shared_input", true, false);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Fused_Concat)
|
||||
{
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
|
||||
checkBackend();
|
||||
|
||||
// Test case
|
||||
// input
|
||||
// |
|
||||
// v
|
||||
// some_layer
|
||||
// | |
|
||||
// v v
|
||||
// concat
|
||||
Net net;
|
||||
int interLayer;
|
||||
{
|
||||
LayerParams lp;
|
||||
lp.type = "AbsVal";
|
||||
lp.name = "someLayer";
|
||||
interLayer = net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
}
|
||||
{
|
||||
LayerParams lp;
|
||||
lp.set("axis", 1);
|
||||
lp.type = "Concat";
|
||||
lp.name = "testConcat";
|
||||
int id = net.addLayer(lp.name, lp.type, lp);
|
||||
net.connect(interLayer, 0, id, 0);
|
||||
net.connect(interLayer, 0, id, 1);
|
||||
}
|
||||
int shape[] = {1, 2, 3, 4};
|
||||
Mat input(4, shape, CV_32F);
|
||||
randu(input, 0.0f, 1.0f); // [0, 1] to make AbsVal an identity transformation.
|
||||
|
||||
net.setInput(input);
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
Mat out = net.forward();
|
||||
|
||||
normAssert(slice(out, Range::all(), Range(0, 2), Range::all(), Range::all()), input, "", default_l1, default_lInf);
|
||||
normAssert(slice(out, Range::all(), Range(2, 4), Range::all(), Range::all()), input, "", default_l1, default_lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Eltwise)
|
||||
{
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
|
||||
testLayerUsingCaffeModels("layer_eltwise");
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, PReLU)
|
||||
{
|
||||
double lInf = (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16) ? 0.021 : 0.0;
|
||||
testLayerUsingCaffeModels("layer_prelu", true, true, 0.0, lInf);
|
||||
}
|
||||
|
||||
// TODO: fix an unstable test case
|
||||
TEST_P(Test_Caffe_layers, layer_prelu_fc)
|
||||
{
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // TODO: fix this test for OpenVINO
|
||||
|
||||
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
// Reference output values are in range [-0.0001, 10.3906]
|
||||
double l1 = (target == DNN_TARGET_MYRIAD) ? 0.005 : 0.0;
|
||||
double lInf = (target == DNN_TARGET_MYRIAD) ? 0.021 : 0.0;
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2020040000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
|
||||
{
|
||||
l1 = 0.006f; lInf = 0.05f;
|
||||
}
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
{
|
||||
l1 = 0.01f; lInf = 0.05f;
|
||||
}
|
||||
#endif
|
||||
testLayerUsingCaffeModels("layer_prelu_fc", true, false, l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Reshape_Split_Slice)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2023000000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
#endif
|
||||
|
||||
Net net = readNetFromCaffe(_tf("reshape_and_slice_routines.prototxt"));
|
||||
ASSERT_FALSE(net.empty());
|
||||
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
|
||||
Mat input(6, 12, CV_32F);
|
||||
RNG rng(0);
|
||||
rng.fill(input, RNG::UNIFORM, -1, 1);
|
||||
|
||||
net.setInput(input, "input");
|
||||
Mat output;
|
||||
if (net.getMainGraph())
|
||||
output = net.forward();
|
||||
else
|
||||
output = net.forward("output");
|
||||
|
||||
normAssert(input, output, "", default_l1, default_lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Conv_Elu)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE <= 2018050000
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
Net net = readNetFromTensorflow(_tf("layer_elu_model.pb"));
|
||||
ASSERT_FALSE(net.empty());
|
||||
|
||||
Mat inp = blobFromNPY(_tf("layer_elu_in.npy"));
|
||||
Mat ref = blobFromNPY(_tf("layer_elu_out.npy"));
|
||||
|
||||
net.setInput(inp, "input");
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
Mat out = net.forward();
|
||||
|
||||
double l1 = default_l1, lInf = default_lInf;
|
||||
if (target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
l1 = 0.0002;
|
||||
lInf = 0.0005;
|
||||
}
|
||||
normAssert(ref, out, "", l1, lInf);
|
||||
}
|
||||
|
||||
class Layer_LSTM_Test : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
@@ -768,148 +433,6 @@ TEST(Layer_MHARoPe_Test_Accuracy_with_, Pytorch)
|
||||
normAssert(h_t_reference, outputs[0]);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Accum)
|
||||
{
|
||||
#ifdef OPENCV_DNN_EXTERNAL_PROTOBUF
|
||||
throw SkipTestException("Requires patched protobuf");
|
||||
#else
|
||||
if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL, CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
|
||||
testLayerUsingCaffeModels("accum", false, false, 0.0, 0.0, 2);
|
||||
testLayerUsingCaffeModels("accum_ref", false, false, 0.0, 0.0, 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, FlowWarp)
|
||||
{
|
||||
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
|
||||
testLayerUsingCaffeModels("flow_warp", false, false, 0.0, 0.0, 2);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, ChannelNorm)
|
||||
{
|
||||
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
testLayerUsingCaffeModels("channel_norm", false, false);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, DataAugmentation)
|
||||
{
|
||||
#ifdef OPENCV_DNN_EXTERNAL_PROTOBUF
|
||||
throw SkipTestException("Requires patched protobuf");
|
||||
#else
|
||||
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
testLayerUsingCaffeModels("data_augmentation", true, false);
|
||||
testLayerUsingCaffeModels("data_augmentation_2x1", true, false);
|
||||
testLayerUsingCaffeModels("data_augmentation_8x6", true, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Resample)
|
||||
{
|
||||
#ifdef OPENCV_DNN_EXTERNAL_PROTOBUF
|
||||
throw SkipTestException("Requires patched protobuf");
|
||||
#else
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2023000000)
|
||||
if (backend != DNN_BACKEND_OPENCV)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
#endif
|
||||
testLayerUsingCaffeModels("nearest_2inps", false, false, 0.0, 0.0, 2);
|
||||
testLayerUsingCaffeModels("nearest", false, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Correlation)
|
||||
{
|
||||
#ifdef OPENCV_DNN_EXTERNAL_PROTOBUF
|
||||
throw SkipTestException("Requires patched protobuf");
|
||||
#else
|
||||
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER,
|
||||
CV_TEST_TAG_DNN_SKIP_OPENCL, CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
testLayerUsingCaffeModels("correlation", false, false, 0.0, 0.0, 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, Convolution2Inputs)
|
||||
{
|
||||
testLayerUsingCaffeModels("conv_2_inps", true, false, 0.0, 0.0, 2);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, ROIPooling_Accuracy)
|
||||
{
|
||||
Net net = readNetFromCaffe(_tf("net_roi_pooling.prototxt"));
|
||||
ASSERT_FALSE(net.empty());
|
||||
|
||||
Mat inp = blobFromNPY(_tf("net_roi_pooling.input.npy"));
|
||||
Mat rois = blobFromNPY(_tf("net_roi_pooling.rois.npy"));
|
||||
Mat ref = blobFromNPY(_tf("net_roi_pooling.npy"));
|
||||
|
||||
checkBackend(&inp, &ref);
|
||||
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
|
||||
net.setInput(inp, "input");
|
||||
net.setInput(rois, "rois");
|
||||
|
||||
Mat out = net.forward();
|
||||
|
||||
double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-5;
|
||||
double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-4;
|
||||
if (target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
l1 = 2e-4;
|
||||
lInf = 9e-4;
|
||||
}
|
||||
normAssert(out, ref, "", l1, lInf);
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, FasterRCNN_Proposal)
|
||||
{
|
||||
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
if(backend == DNN_BACKEND_CUDA)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA); /* Proposal layer is unsupported */
|
||||
|
||||
Net net = readNetFromCaffe(_tf("net_faster_rcnn_proposal.prototxt"));
|
||||
|
||||
Mat scores = blobFromNPY(_tf("net_faster_rcnn_proposal.scores.npy"));
|
||||
Mat deltas = blobFromNPY(_tf("net_faster_rcnn_proposal.deltas.npy"));
|
||||
Mat imInfo = (Mat_<float>(1, 3) << 600, 800, 1.6f);
|
||||
|
||||
net.setInput(scores, "rpn_cls_prob_reshape");
|
||||
net.setInput(deltas, "rpn_bbox_pred");
|
||||
net.setInput(imInfo, "im_info");
|
||||
|
||||
std::vector<Mat> outs;
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
net.forward(outs);
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
Mat ref = blobFromNPY(_tf(i == 0 ? "net_faster_rcnn_proposal.out_rois.npy" :
|
||||
"net_faster_rcnn_proposal.out_scores.npy"));
|
||||
const int numDets = ref.size[0];
|
||||
EXPECT_LE(numDets, outs[i].size[0]);
|
||||
normAssert(outs[i].rowRange(0, numDets), ref);
|
||||
|
||||
if (numDets < outs[i].size[0])
|
||||
{
|
||||
EXPECT_EQ(countNonZero(outs[i].rowRange(numDets, outs[i].size[0])), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<Vec4i, Vec2i, bool> > Scale_untrainable;
|
||||
TEST_P(Scale_untrainable, Accuracy)
|
||||
{
|
||||
@@ -1072,6 +595,8 @@ INSTANTIATE_TEST_CASE_P(Layer_Test, Crop, Combine(
|
||||
/*offset value*/ Values(3, 4)
|
||||
));
|
||||
|
||||
class Test_Caffe_layers : public DNNTestLayer {};
|
||||
|
||||
// Check that by default average pooling layer should not count zero padded values
|
||||
// into the normalization area.
|
||||
TEST_P(Test_Caffe_layers, Average_pooling_kernel_area)
|
||||
@@ -1099,32 +624,6 @@ TEST_P(Test_Caffe_layers, Average_pooling_kernel_area)
|
||||
normAssert(out, blobFromImage(ref));
|
||||
}
|
||||
|
||||
TEST_P(Test_Caffe_layers, PriorBox_repeated)
|
||||
{
|
||||
Net net = readNet(_tf("prior_box.prototxt"));
|
||||
int inp_size[] = {1, 3, 10, 10};
|
||||
int shape_size[] = {1, 2, 3, 4};
|
||||
Mat inp(4, inp_size, CV_32F);
|
||||
randu(inp, -1.0f, 1.0f);
|
||||
Mat shape(4, shape_size, CV_32F);
|
||||
randu(shape, -1.0f, 1.0f);
|
||||
net.setInput(inp, "data");
|
||||
net.setInput(shape, "shape");
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
Mat out = net.forward();
|
||||
Mat ref = blobFromNPY(_tf("priorbox_output.npy"));
|
||||
|
||||
double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-5;
|
||||
double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-4;
|
||||
if (target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
l1 = 7e-5;
|
||||
lInf = 0.0005;
|
||||
}
|
||||
normAssert(out, ref, "", l1, lInf);
|
||||
}
|
||||
|
||||
// Test PriorBoxLayer in case of no aspect ratios (just squared proposals).
|
||||
TEST_P(Test_Caffe_layers, PriorBox_squares)
|
||||
{
|
||||
@@ -1289,46 +788,6 @@ INSTANTIATE_TEST_CASE_P(/**/, Layer_Test_DWconv_Prelu, Combine(Values(3, 6), Val
|
||||
// ./ModelOptimizer -w /path/to/caffemodel -d /path/to/prototxt \
|
||||
// -p FP32 -i -b ${batch_size} -o /path/to/output/folder
|
||||
typedef testing::TestWithParam<tuple<Backend, Target> > Layer_Test_Convolution_DLDT;
|
||||
TEST_P(Layer_Test_Convolution_DLDT, Accuracy)
|
||||
{
|
||||
const Backend backendId = get<0>(GetParam());
|
||||
const Target targetId = get<1>(GetParam());
|
||||
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
|
||||
if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
throw SkipTestException("No support for async forward");
|
||||
|
||||
ASSERT_EQ(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, backendId);
|
||||
|
||||
Net netDefault = readNet(_tf("layer_convolution.caffemodel"), _tf("layer_convolution.prototxt"));
|
||||
Net net = readNet(_tf("layer_convolution.xml"), _tf("layer_convolution.bin"));
|
||||
|
||||
Mat inp = blobFromNPY(_tf("blob.npy"));
|
||||
|
||||
netDefault.setInput(inp);
|
||||
netDefault.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
Mat outDefault = netDefault.forward();
|
||||
|
||||
net.setInput(inp);
|
||||
net.setPreferableBackend(backendId);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
Mat out = net.forward();
|
||||
|
||||
double l1 = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 1.5e-3 : 1e-5;
|
||||
double lInf = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 1.8e-2 : 1e-4;
|
||||
normAssert(outDefault, out, "", l1, lInf);
|
||||
|
||||
std::vector<int> outLayers = net.getUnconnectedOutLayers();
|
||||
ASSERT_EQ(net.getLayer(outLayers[0])->name, "output");
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
ASSERT_EQ(net.getLayer(outLayers[0])->type, "Convolution");
|
||||
else
|
||||
ASSERT_EQ(net.getLayer(outLayers[0])->type, "Result");
|
||||
}
|
||||
|
||||
TEST_P(Layer_Test_Convolution_DLDT, multithreading)
|
||||
{
|
||||
const Backend backendId = get<0>(GetParam());
|
||||
@@ -1640,43 +1099,6 @@ private:
|
||||
int outWidth, outHeight, zoomFactor;
|
||||
};
|
||||
|
||||
// BUG: https://github.com/opencv/opencv/issues/26194
|
||||
// After unregistration of the custom 'Interp' the model uses the standard Resize layer.
|
||||
// According to the graph, the model must produce 2 x 3 x 18 x 16 tensor with Resize layer,
|
||||
// but the result is compared with 2 x 3 x 17 x 15 tensor, just like the custom 'Interp' layer produced,
|
||||
// so we get the test failure. It looks like the test needs to be fixed.
|
||||
TEST_P(Test_Caffe_layers, DISABLED_Interp)
|
||||
{
|
||||
#ifdef OPENCV_DNN_EXTERNAL_PROTOBUF
|
||||
throw SkipTestException("Requires patched protobuf");
|
||||
#else
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
#endif
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
|
||||
|
||||
// Test a custom layer.
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Interp, CustomInterpLayer);
|
||||
try
|
||||
{
|
||||
testLayerUsingCaffeModels("layer_interp", false, false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LayerFactory::unregisterLayer("Interp");
|
||||
throw;
|
||||
}
|
||||
LayerFactory::unregisterLayer("Interp");
|
||||
|
||||
// Test an implemented layer.
|
||||
|
||||
testLayerUsingCaffeModels("layer_interp", false, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_Caffe_layers, dnnBackendsAndTargets());
|
||||
|
||||
TEST(Layer_Test_PoolingIndices, Accuracy)
|
||||
|
||||
@@ -245,8 +245,7 @@ TEST(blobFromImagesWithParams_4ch, multi_image)
|
||||
|
||||
TEST(readNet, Regression)
|
||||
{
|
||||
Net net = readNet(findDataFile("dnn/squeezenet_v1.1.prototxt"),
|
||||
findDataFile("dnn/squeezenet_v1.1.caffemodel", false));
|
||||
Net net = readNet(findDataFile("dnn/onnx/models/squeezenet.onnx", false));
|
||||
EXPECT_FALSE(net.empty());
|
||||
net = readNet(findDataFile("dnn/ssd_mobilenet_v1_coco.pbtxt"),
|
||||
findDataFile("dnn/ssd_mobilenet_v1_coco.pb", false));
|
||||
@@ -256,9 +255,7 @@ TEST(readNet, Regression)
|
||||
TEST(readNet, do_not_call_setInput) // https://github.com/opencv/opencv/issues/16618
|
||||
{
|
||||
// 1. load network
|
||||
const string proto = findDataFile("dnn/squeezenet_v1.1.prototxt");
|
||||
const string model = findDataFile("dnn/squeezenet_v1.1.caffemodel", false);
|
||||
Net net = readNetFromCaffe(proto, model);
|
||||
Net net = readNet(findDataFile("dnn/onnx/models/squeezenet.onnx", false));
|
||||
|
||||
// 2. mistake: no inputs are specified through .setInput()
|
||||
|
||||
@@ -325,13 +322,7 @@ TEST_P(dump, Regression)
|
||||
{
|
||||
const int backend = get<0>(GetParam());
|
||||
const int target = get<1>(GetParam());
|
||||
Net net = readNet(findDataFile("dnn/squeezenet_v1.1.prototxt"),
|
||||
findDataFile("dnn/squeezenet_v1.1.caffemodel", false));
|
||||
|
||||
if (net.getMainGraph())
|
||||
ASSERT_EQ(net.getLayer(net.getLayerId("fire2/concat"))->inputs.size(), 2);
|
||||
else
|
||||
ASSERT_EQ(net.getLayerInputs(net.getLayerId("fire2/concat")).size(), 2);
|
||||
Net net = readNet(findDataFile("dnn/onnx/models/squeezenet.onnx", false));
|
||||
|
||||
int size[] = {1, 3, 227, 227};
|
||||
Mat input = cv::Mat::ones(4, size, CV_32F);
|
||||
@@ -579,20 +570,17 @@ INSTANTIATE_TEST_CASE_P(/**/, DeprecatedForward, dnnBackendsAndTargets());
|
||||
|
||||
TEST(Net, forwardAndRetrieve)
|
||||
{
|
||||
std::string prototxt =
|
||||
"input: \"data\"\n"
|
||||
"layer {\n"
|
||||
" name: \"testLayer\"\n"
|
||||
" type: \"Slice\"\n"
|
||||
" bottom: \"data\"\n"
|
||||
" top: \"firstCopy\"\n"
|
||||
" top: \"secondCopy\"\n"
|
||||
" slice_param {\n"
|
||||
" axis: 0\n"
|
||||
" slice_point: 2\n"
|
||||
" }\n"
|
||||
"}";
|
||||
Net net = readNetFromCaffe(&prototxt[0], prototxt.size());
|
||||
LayerParams lpSlice;
|
||||
lpSlice.name = "testLayer";
|
||||
lpSlice.type = "Slice";
|
||||
lpSlice.set("axis", 0);
|
||||
Mat slicePoint = (Mat_<int>(1, 1) << 2);
|
||||
lpSlice.set("slice_point", DictValue::arrayInt<int*>((int*)slicePoint.data, 1));
|
||||
|
||||
Net net;
|
||||
int sliceId = net.addLayer(lpSlice.name, lpSlice.type, lpSlice);
|
||||
net.connect(0, 0, sliceId, 0);
|
||||
|
||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||
|
||||
Mat inp(4, 5, CV_32F);
|
||||
|
||||
+92
-165
@@ -21,7 +21,7 @@ static std::string _tf(TString filename, bool required = true)
|
||||
class Test_Model : public DNNTestLayer
|
||||
{
|
||||
public:
|
||||
void testDetectModel(const std::string& weights, const std::string& cfg,
|
||||
void testDetectModel(const std::string& weights, const std::string& /*cfg*/,
|
||||
const std::string& imgPath, const std::vector<int>& refClassIds,
|
||||
const std::vector<float>& refConfidences,
|
||||
const std::vector<Rect2d>& refBoxes,
|
||||
@@ -29,35 +29,67 @@ public:
|
||||
double confThreshold = 0.24, double nmsThreshold = 0.0,
|
||||
const Size& size = {-1, -1}, Scalar mean = Scalar(),
|
||||
double scale = 1.0, bool swapRB = false, bool crop = false,
|
||||
bool nmsAcrossClasses = false)
|
||||
const std::vector<String>& outNames = {"boxes", "scores", "class_idx"})
|
||||
{
|
||||
checkBackend();
|
||||
CV_Assert(outNames.size() == 3);
|
||||
|
||||
Mat frame = imread(imgPath);
|
||||
DetectionModel model(weights, cfg);
|
||||
Net net = readNet(weights);
|
||||
|
||||
model.setInputSize(size).setInputMean(mean).setInputScale(scale)
|
||||
.setInputSwapRB(swapRB).setInputCrop(crop);
|
||||
|
||||
model.setPreferableBackend(backend);
|
||||
model.setPreferableTarget(target);
|
||||
|
||||
model.setNmsAcrossClasses(nmsAcrossClasses);
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
if (target == DNN_TARGET_CPU_FP16)
|
||||
model.enableWinograd(false);
|
||||
net.enableWinograd(false);
|
||||
|
||||
std::vector<int> classIds;
|
||||
net.setInput(blobFromImage(frame, scale, size, mean, swapRB, crop, CV_32F));
|
||||
|
||||
std::vector<Mat> outs;
|
||||
net.forward(outs, outNames);
|
||||
ASSERT_EQ(outs.size(), 3u);
|
||||
|
||||
Mat outBoxes = outs[0].reshape(1, (int)outs[0].total() / 4);
|
||||
const Mat& outScores = outs[1];
|
||||
const Mat& outClsIds = outs[2];
|
||||
|
||||
std::vector<Rect2d> boxes;
|
||||
std::vector<float> confidences;
|
||||
std::vector<Rect> boxes;
|
||||
std::vector<int> classIds;
|
||||
for (int i = 0; i < outBoxes.rows; ++i)
|
||||
{
|
||||
float confidence = outScores.at<float>(i);
|
||||
if (confidence < confThreshold)
|
||||
continue;
|
||||
|
||||
model.detect(frame, classIds, confidences, boxes, confThreshold, nmsThreshold);
|
||||
|
||||
std::vector<Rect2d> boxesDouble(boxes.size());
|
||||
for (int i = 0; i < boxes.size(); i++) {
|
||||
boxesDouble[i] = boxes[i];
|
||||
const float* box = outBoxes.ptr<float>(i);
|
||||
boxes.emplace_back(box[0] / size.width, box[1] / size.height,
|
||||
(box[2] - box[0]) / size.width, (box[3] - box[1]) / size.height);
|
||||
confidences.push_back(confidence);
|
||||
classIds.push_back((int)outClsIds.at<float>(i));
|
||||
}
|
||||
normAssertDetections(refClassIds, refConfidences, refBoxes, classIds,
|
||||
confidences, boxesDouble, "",
|
||||
|
||||
if (nmsThreshold > 0)
|
||||
{
|
||||
std::vector<int> keep;
|
||||
NMSBoxesBatched(boxes, confidences, classIds,
|
||||
(float)confThreshold, (float)nmsThreshold, keep);
|
||||
|
||||
std::vector<Rect2d> nmsBoxes;
|
||||
std::vector<float> nmsConfidences;
|
||||
std::vector<int> nmsClassIds;
|
||||
for (int idx : keep)
|
||||
{
|
||||
nmsBoxes.push_back(boxes[idx]);
|
||||
nmsConfidences.push_back(confidences[idx]);
|
||||
nmsClassIds.push_back(classIds[idx]);
|
||||
}
|
||||
boxes = std::move(nmsBoxes);
|
||||
confidences = std::move(nmsConfidences);
|
||||
classIds = std::move(nmsClassIds);
|
||||
}
|
||||
|
||||
normAssertDetections(refClassIds, refConfidences, refBoxes,
|
||||
classIds, confidences, boxes, "",
|
||||
confThreshold, scoreDiff, iouDiff);
|
||||
}
|
||||
|
||||
@@ -282,133 +314,66 @@ TEST_P(Test_Model, Classify)
|
||||
std::pair<int, float> ref(652, 0.641789);
|
||||
|
||||
std::string img_path = _tf("grace_hopper_227.png");
|
||||
std::string config_file = _tf("bvlc_alexnet.prototxt");
|
||||
std::string weights_file = _tf("bvlc_alexnet.caffemodel", false);
|
||||
std::string weights_file = _tf("onnx/models/alexnet.onnx", false);
|
||||
|
||||
Size size{227, 227};
|
||||
float norm = 1e-4;
|
||||
|
||||
testClassifyModel(weights_file, config_file, img_path, ref, norm, size);
|
||||
testClassifyModel(weights_file, "", img_path, ref, norm, size);
|
||||
}
|
||||
|
||||
|
||||
TEST_P(Test_Model, DetectionOutput)
|
||||
TEST_P(Test_Model, YOLOv3)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DEBUG_VERYLONG);
|
||||
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2022010000)
|
||||
// Check 'backward_compatible_check || in_out_elements_equal' failed at core/src/op/reshape.cpp:427:
|
||||
// While validating node 'v1::Reshape bbox_pred_reshape (ave_bbox_pred_rois[0]:f32{1,8,1,1}, Constant_388[0]:i64{4}) -> (f32{?,?,?,?})' with friendly_name 'bbox_pred_reshape':
|
||||
// Requested output shape {1,300,8,1} is incompatible with input shape {1, 8, 1, 1}
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#elif defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
|
||||
// Exception: Function contains several inputs and outputs with one friendly name! (HETERO bug?)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
applyTestTag(
|
||||
CV_TEST_TAG_LONG,
|
||||
CV_TEST_TAG_MEMORY_2GB,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#elif defined(INF_ENGINE_RELEASE)
|
||||
// FIXIT DNN_BACKEND_INFERENCE_ENGINE is misused
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16);
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
if (target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
|
||||
#endif
|
||||
// The in-graph YOLO decode (Split) is not evaluable by the OpenVINO backend.
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
std::vector<int> refClassIds = {7, 12};
|
||||
std::vector<float> refConfidences = {0.991359f, 0.94786f};
|
||||
std::vector<Rect2d> refBoxes = {Rect2d(491, 81, 212, 98),
|
||||
Rect2d(132, 223, 207, 344)};
|
||||
std::string model_file = _tf("yolov3.onnx", false);
|
||||
std::string img_path = _tf("dog416.png"); // Matches standard YOLO inference classes
|
||||
|
||||
std::string img_path = _tf("dog416.png");
|
||||
std::string weights_file = _tf("resnet50_rfcn_final.caffemodel", false);
|
||||
std::string config_file = _tf("rfcn_pascal_voc_resnet50.prototxt");
|
||||
// Extracted from original flat ref_ array: batchId, classId, confidence, left, top, right, bottom
|
||||
std::vector<int> refClassIds = {7, 16, 1};
|
||||
std::vector<float> refConfidences = {0.606292f, 0.55195f, 0.433444f};
|
||||
|
||||
Scalar mean = Scalar(102.9801, 115.9465, 122.7717);
|
||||
Size size{800, 600};
|
||||
// Rect2d requires (x, y, width, height) format
|
||||
std::vector<Rect2d> refBoxes = {
|
||||
Rect2d(0.612037f, 0.149921f, 0.910763f - 0.612037f, 0.300503f - 0.149921f), // Class 7
|
||||
Rect2d(0.170690f, 0.356024f, 0.471459f - 0.170690f, 0.877178f - 0.356024f), // Class 16
|
||||
Rect2d(0.199235f, 0.301175f, 0.753253f - 0.199235f, 0.744156f - 0.301175f) // Class 1
|
||||
};
|
||||
|
||||
double scoreDiff = default_l1, iouDiff = 1e-5;
|
||||
float confThreshold = 0.8;
|
||||
double nmsThreshold = 0.0;
|
||||
if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CUDA_FP16 || target == DNN_TARGET_CPU_FP16)
|
||||
// Setting precision tolerances
|
||||
double scoreDiff = 8e-5, iouDiff = 3e-4;
|
||||
if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16)
|
||||
{
|
||||
if (backend == DNN_BACKEND_OPENCV)
|
||||
scoreDiff = 4e-3;
|
||||
else
|
||||
scoreDiff = 2e-2;
|
||||
iouDiff = 1.8e-1;
|
||||
}
|
||||
#if defined(INF_ENGINE_RELEASE)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
{
|
||||
scoreDiff = 0.05;
|
||||
iouDiff = 0.08;
|
||||
}
|
||||
#endif
|
||||
|
||||
testDetectModel(weights_file, config_file, img_path, refClassIds, refConfidences, refBoxes,
|
||||
scoreDiff, iouDiff, confThreshold, nmsThreshold, size, mean);
|
||||
}
|
||||
|
||||
|
||||
TEST_P(Test_Model, DetectionMobilenetSSD)
|
||||
{
|
||||
Mat ref = blobFromNPY(_tf("mobilenet_ssd_caffe_out.npy"));
|
||||
ref = ref.reshape(1, ref.size[2]);
|
||||
|
||||
std::string img_path = _tf("street.png");
|
||||
Mat frame = imread(img_path);
|
||||
int frameWidth = frame.cols;
|
||||
int frameHeight = frame.rows;
|
||||
|
||||
std::vector<int> refClassIds;
|
||||
std::vector<float> refConfidences;
|
||||
std::vector<Rect2d> refBoxes;
|
||||
for (int i = 0; i < ref.rows; i++)
|
||||
{
|
||||
refClassIds.emplace_back(ref.at<float>(i, 1));
|
||||
refConfidences.emplace_back(ref.at<float>(i, 2));
|
||||
int left = ref.at<float>(i, 3) * frameWidth;
|
||||
int top = ref.at<float>(i, 4) * frameHeight;
|
||||
int right = ref.at<float>(i, 5) * frameWidth;
|
||||
int bottom = ref.at<float>(i, 6) * frameHeight;
|
||||
int width = right - left + 1;
|
||||
int height = bottom - top + 1;
|
||||
refBoxes.emplace_back(left, top, width, height);
|
||||
}
|
||||
|
||||
std::string weights_file = _tf("MobileNetSSD_deploy_19e3ec3.caffemodel", false);
|
||||
std::string config_file = _tf("MobileNetSSD_deploy_19e3ec3.prototxt");
|
||||
|
||||
Scalar mean = Scalar(127.5, 127.5, 127.5);
|
||||
double scale = 1.0 / 127.5;
|
||||
Size size{300, 300};
|
||||
|
||||
double scoreDiff = 1e-5, iouDiff = 1e-5;
|
||||
if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16)
|
||||
{
|
||||
scoreDiff = 1.7e-2;
|
||||
iouDiff = 6.91e-2;
|
||||
}
|
||||
else if (target == DNN_TARGET_MYRIAD)
|
||||
{
|
||||
scoreDiff = 0.017;
|
||||
if (getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
|
||||
iouDiff = 0.1;
|
||||
scoreDiff = 0.006;
|
||||
iouDiff = 0.042;
|
||||
}
|
||||
else if (target == DNN_TARGET_CUDA_FP16)
|
||||
{
|
||||
scoreDiff = 0.0028;
|
||||
iouDiff = 1e-2;
|
||||
scoreDiff = 0.04;
|
||||
iouDiff = 0.03;
|
||||
}
|
||||
float confThreshold = FLT_MIN;
|
||||
double nmsThreshold = 0.0;
|
||||
|
||||
testDetectModel(weights_file, config_file, img_path, refClassIds, refConfidences, refBoxes,
|
||||
scoreDiff, iouDiff, confThreshold, nmsThreshold, size, mean, scale);
|
||||
// Model parameters
|
||||
double confThreshold = 0.24;
|
||||
double nmsThreshold = 0.4;
|
||||
Size size{640, 640};
|
||||
double scale = 1.0 / 255.0; // Standard image scaling for YOLO models
|
||||
Scalar mean = Scalar();
|
||||
bool swapRB = true; // YOLO expects RGB
|
||||
|
||||
testDetectModel(model_file, "", img_path, refClassIds, refConfidences, refBoxes,
|
||||
scoreDiff, iouDiff, confThreshold, nmsThreshold, size, mean, scale, swapRB);
|
||||
}
|
||||
|
||||
TEST_P(Test_Model, Keypoints_pose)
|
||||
@@ -478,44 +443,6 @@ TEST_P(Test_Model, Keypoints_face)
|
||||
testKeypointsModel(weights, "", inp, exp, norm, size, mean, scale, swapRB);
|
||||
}
|
||||
|
||||
TEST_P(Test_Model, Detection_normalized)
|
||||
{
|
||||
std::string img_path = _tf("grace_hopper_227.png");
|
||||
std::vector<int> refClassIds = {15};
|
||||
std::vector<float> refConfidences = {0.999222f};
|
||||
std::vector<Rect2d> refBoxes = {Rect2d(0, 4, 227, 222)};
|
||||
|
||||
std::string weights_file = _tf("MobileNetSSD_deploy_19e3ec3.caffemodel", false);
|
||||
std::string config_file = _tf("MobileNetSSD_deploy_19e3ec3.prototxt");
|
||||
|
||||
Scalar mean = Scalar(127.5, 127.5, 127.5);
|
||||
double scale = 1.0 / 127.5;
|
||||
Size size{300, 300};
|
||||
|
||||
double scoreDiff = 1e-5, iouDiff = 1e-5;
|
||||
float confThreshold = FLT_MIN;
|
||||
double nmsThreshold = 0.0;
|
||||
if (target == DNN_TARGET_CUDA)
|
||||
{
|
||||
scoreDiff = 3e-4;
|
||||
iouDiff = 0.018;
|
||||
}
|
||||
if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CUDA_FP16 || target == DNN_TARGET_CPU_FP16)
|
||||
{
|
||||
scoreDiff = 5e-3;
|
||||
iouDiff = 0.09;
|
||||
}
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2020040000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
{
|
||||
scoreDiff = 0.02;
|
||||
iouDiff = 0.1f;
|
||||
}
|
||||
#endif
|
||||
testDetectModel(weights_file, config_file, img_path, refClassIds, refConfidences, refBoxes,
|
||||
scoreDiff, iouDiff, confThreshold, nmsThreshold, size, mean, scale);
|
||||
}
|
||||
|
||||
TEST_P(Test_Model, Segmentation)
|
||||
{
|
||||
applyTestTag(
|
||||
|
||||
@@ -348,11 +348,13 @@ BarcodeDetector::BarcodeDetector(const string &prototxt_path, const string &mode
|
||||
Ptr<BarcodeImpl> p_ = new BarcodeImpl();
|
||||
p = p_;
|
||||
p_->sr = make_shared<SuperScale>();
|
||||
if (!prototxt_path.empty() && !model_path.empty())
|
||||
// The Super Resolution model is now a single-file ONNX network; the legacy Caffe
|
||||
// prototxt argument is retained for API compatibility but is no longer used.
|
||||
CV_UNUSED(prototxt_path);
|
||||
if (!model_path.empty())
|
||||
{
|
||||
CV_Assert(utils::fs::exists(prototxt_path));
|
||||
CV_Assert(utils::fs::exists(model_path));
|
||||
int res = p_->sr->init(prototxt_path, model_path);
|
||||
int res = p_->sr->init(model_path);
|
||||
CV_Assert(res == 0);
|
||||
p_->use_nn_sr = true;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@ namespace barcode {
|
||||
|
||||
constexpr static float MAX_SCALE = 4.0f;
|
||||
|
||||
int SuperScale::init(const std::string &proto_path, const std::string &model_path)
|
||||
int SuperScale::init(const std::string &model_path)
|
||||
{
|
||||
srnet_ = dnn::readNetFromCaffe(proto_path, model_path);
|
||||
// Super Resolution is loaded from a single-file ONNX model (e.g. dnn/wechat_2021-01/sr.onnx).
|
||||
srnet_ = dnn::readNetFromONNX(model_path);
|
||||
net_loaded_ = true;
|
||||
return 0;
|
||||
}
|
||||
@@ -77,9 +78,8 @@ int SuperScale::superResolutionScale(const Mat &src, Mat &dst)
|
||||
|
||||
#else // HAVE_OPENCV_DNN
|
||||
|
||||
int SuperScale::init(const std::string &proto_path, const std::string &model_path)
|
||||
int SuperScale::init(const std::string &model_path)
|
||||
{
|
||||
CV_UNUSED(proto_path);
|
||||
CV_UNUSED(model_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
|
||||
~SuperScale() = default;
|
||||
|
||||
int init(const std::string &proto_path, const std::string &model_path);
|
||||
int init(const std::string &model_path);
|
||||
|
||||
void processImageScale(const Mat &src, Mat &dst, float scale, const bool &use_sr, int sr_max_size = 160);
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ video = {
|
||||
}
|
||||
|
||||
dnn = {'dnn_Net': ['setInput', 'forward', 'setPreferableBackend','getUnconnectedOutLayersNames'],
|
||||
'': ['readNetFromCaffe', 'readNetFromTensorflow',
|
||||
'': ['readNetFromTensorflow',
|
||||
'readNetFromONNX', 'readNetFromTFLite', 'readNet', 'blobFromImage']}
|
||||
|
||||
features = {'Feature2D': ['detect', 'compute', 'detectAndCompute', 'descriptorSize', 'descriptorType', 'defaultNorm', 'empty', 'getDefaultName'],
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
set(sample example-mobilenet-objdetect)
|
||||
|
||||
ocv_download(FILENAME "mobilenet_iter_73000.caffemodel"
|
||||
HASH "bbcb3b6a0afe1ec89e1288096b5b8c66"
|
||||
URL
|
||||
"${OPENCV_MOBILENET_SSD_WEIGHTS_URL}"
|
||||
"$ENV{OPENCV_MOBILENET_SSD_WEIGHTS_URL}"
|
||||
"https://raw.githubusercontent.com/chuanqi305/MobileNet-SSD/97406996b1eee2d40eb0a00ae567cf41e23369f9/mobilenet_iter_73000.caffemodel"
|
||||
DESTINATION_DIR "${CMAKE_CURRENT_LIST_DIR}/res/raw"
|
||||
ID OPENCV_MOBILENET_SSD_WEIGHTS
|
||||
STATUS res)
|
||||
# Explicitly ensure resource directories exist to guarantee smooth resource compiling
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/res/raw")
|
||||
|
||||
ocv_download(FILENAME "deploy.prototxt"
|
||||
HASH "f1978dc4fe20c680e850ce99830c5945"
|
||||
URL
|
||||
"${OPENCV_MOBILENET_SSD_CONFIG_URL}"
|
||||
"$ENV{OPENCV_MOBILENET_SSD_CONFIG_URL}"
|
||||
"https://raw.githubusercontent.com/chuanqi305/MobileNet-SSD/97406996b1eee2d40eb0a00ae567cf41e23369f9/deploy.prototxt"
|
||||
DESTINATION_DIR "${CMAKE_CURRENT_LIST_DIR}/res/raw"
|
||||
ID OPENCV_MOBILENET_SSD_CONFIG
|
||||
STATUS res)
|
||||
# The Caffe MobileNet-SSD (mobilenet_iter_73000.caffemodel + deploy.prototxt) has been
|
||||
# replaced by a single-file ONNX model. The sample now loads "res/raw/mobilenet.onnx".
|
||||
if((DEFINED ENV{OPENCV_MOBILENET_SSD_ONNX_URL} OR DEFINED OPENCV_MOBILENET_SSD_ONNX_URL) AND OPENCV_MOBILENET_SSD_ONNX_HASH)
|
||||
ocv_download(FILENAME "mobilenet.onnx"
|
||||
HASH "${OPENCV_MOBILENET_SSD_ONNX_HASH}"
|
||||
URL
|
||||
"${OPENCV_MOBILENET_SSD_ONNX_URL}"
|
||||
"$ENV{OPENCV_MOBILENET_SSD_ONNX_URL}"
|
||||
DESTINATION_DIR "${CMAKE_CURRENT_SOURCE_DIR}/res/raw"
|
||||
ID OPENCV_MOBILENET_SSD_ONNX
|
||||
STATUS res)
|
||||
endif()
|
||||
|
||||
add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS "${OPENCV_ANDROID_LIB_DIR}" SDK_TARGET 11 "${ANDROID_SDK_TARGET}")
|
||||
if(TARGET ${sample})
|
||||
|
||||
+18
-12
@@ -54,15 +54,19 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener
|
||||
}
|
||||
|
||||
//! [init_model_from_memory]
|
||||
mModelBuffer = loadFileFromResource(R.raw.mobilenet_iter_73000);
|
||||
mConfigBuffer = loadFileFromResource(R.raw.deploy);
|
||||
if (mModelBuffer == null || mConfigBuffer == null) {
|
||||
Log.e(TAG, "Failed to load model from resources");
|
||||
} else
|
||||
Log.i(TAG, "Model files loaded successfully");
|
||||
// Load a single-file MobileNet-SSD ONNX model from res/raw/mobilenet.onnx.
|
||||
// The resource is resolved by name at runtime so the sample still builds when the
|
||||
// (optionally downloaded) model is absent; object detection is simply disabled then.
|
||||
int modelResId = getResources().getIdentifier("mobilenet", "raw", getPackageName());
|
||||
if (modelResId != 0)
|
||||
mModelBuffer = loadFileFromResource(modelResId);
|
||||
|
||||
net = Dnn.readNet("caffe", mModelBuffer, mConfigBuffer);
|
||||
Log.i(TAG, "Network loaded successfully");
|
||||
if (mModelBuffer == null) {
|
||||
Log.e(TAG, "MobileNet ONNX model (res/raw/mobilenet.onnx) not found - object detection disabled");
|
||||
} else {
|
||||
net = Dnn.readNetFromONNX(mModelBuffer);
|
||||
Log.i(TAG, "Network loaded successfully");
|
||||
}
|
||||
//! [init_model_from_memory]
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
@@ -91,8 +95,8 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
|
||||
mModelBuffer.release();
|
||||
mConfigBuffer.release();
|
||||
if (mModelBuffer != null)
|
||||
mModelBuffer.release();
|
||||
}
|
||||
|
||||
// Load a network.
|
||||
@@ -107,7 +111,10 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener
|
||||
final double MEAN_VAL = 127.5;
|
||||
final double THRESHOLD = 0.2;
|
||||
|
||||
// Get a new frame
|
||||
if (net == null) {
|
||||
return inputFrame.rgba();
|
||||
}
|
||||
|
||||
Log.d(TAG, "handle new frame!");
|
||||
Mat frame = inputFrame.rgba();
|
||||
Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2RGB);
|
||||
@@ -188,7 +195,6 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener
|
||||
"motorbike", "person", "pottedplant",
|
||||
"sheep", "sofa", "train", "tvmonitor"};
|
||||
|
||||
private MatOfByte mConfigBuffer;
|
||||
private MatOfByte mModelBuffer;
|
||||
private Net net;
|
||||
private CameraBridgeViewBase mOpenCvCameraView;
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
This sample using FlowNet v2 and RAFT model to calculate optical flow.
|
||||
|
||||
FlowNet v2 Original Paper: https://arxiv.org/abs/1612.01925.
|
||||
FlowNet v2 Repo: https://github.com/lmb-freiburg/flownet2.
|
||||
|
||||
Download the converted .caffemodel model from https://drive.google.com/open?id=16qvE9VNmU39NttpZwZs81Ga8VYQJDaWZ
|
||||
and .prototxt from https://drive.google.com/file/d/1RyNIUsan1ZOh2hpYIH36A-jofAvJlT6a/view?usp=sharing.
|
||||
Otherwise download original model from https://lmb.informatik.uni-freiburg.de/resources/binaries/flownet2/flownet2-models.tar.gz,
|
||||
convert .h5 model to .caffemodel and modify original .prototxt using .prototxt from link above.
|
||||
This sample uses the RAFT model to calculate optical flow.
|
||||
|
||||
RAFT Original Paper: https://arxiv.org/pdf/2003.12039.pdf
|
||||
RAFT Repo: https://github.com/princeton-vl/RAFT
|
||||
|
||||
Download the .onnx model from here https://github.com/opencv/opencv_zoo/raw/281d232cd99cd920853106d853c440edd35eb442/models/optical_flow_estimation_raft/optical_flow_estimation_raft_2023aug.onnx.
|
||||
|
||||
Note: the legacy FlowNet v2 Caffe pipeline (--proto/.caffemodel) has been removed together
|
||||
with the Caffe importer. Please provide a single ONNX model.
|
||||
'''
|
||||
|
||||
import argparse
|
||||
@@ -25,9 +20,8 @@ import cv2 as cv
|
||||
class OpticalFlow(object):
|
||||
def __init__(self, model, height, width, proto=""):
|
||||
if proto:
|
||||
self.net = cv.dnn.readNetFromCaffe(proto, model)
|
||||
else:
|
||||
self.net = cv.dnn.readNet(model)
|
||||
raise cv.error("Caffe support has been removed. Please provide a single ONNX model path (e.g. RAFT).")
|
||||
self.net = cv.dnn.readNet(model)
|
||||
self.net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
|
||||
self.height = height
|
||||
self.width = width
|
||||
@@ -75,41 +69,18 @@ if __name__ == '__main__':
|
||||
parser.add_argument('-input', '-i', required=True, help='Path to input video file. Skip this argument to capture frames from a camera.')
|
||||
parser.add_argument('--height', default=320, type=int, help='Input height')
|
||||
parser.add_argument('--width', default=448, type=int, help='Input width')
|
||||
parser.add_argument('--proto', '-p', default='', help='Path to prototxt.')
|
||||
parser.add_argument('--model', '-m', required=True, help='Path to model.')
|
||||
parser.add_argument('--model', '-m', required=True, help='Path to a single ONNX model (e.g. RAFT).')
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
if not os.path.isfile(args.model):
|
||||
raise OSError("Model does not exist")
|
||||
if args.proto and not os.path.isfile(args.proto):
|
||||
raise OSError("Prototxt does not exist")
|
||||
|
||||
winName = 'Calculation optical flow in OpenCV'
|
||||
cv.namedWindow(winName, cv.WINDOW_NORMAL)
|
||||
cap = cv.VideoCapture(args.input if args.input else 0)
|
||||
hasFrame, first_frame = cap.read()
|
||||
|
||||
if args.proto:
|
||||
divisor = 64.
|
||||
var = {}
|
||||
var['ADAPTED_WIDTH'] = int(np.ceil(args.width/divisor) * divisor)
|
||||
var['ADAPTED_HEIGHT'] = int(np.ceil(args.height/divisor) * divisor)
|
||||
var['SCALE_WIDTH'] = args.width / float(var['ADAPTED_WIDTH'])
|
||||
var['SCALE_HEIGHT'] = args.height / float(var['ADAPTED_HEIGHT'])
|
||||
|
||||
config = ''
|
||||
proto = open(args.proto).readlines()
|
||||
for line in proto:
|
||||
for key, value in var.items():
|
||||
tag = "$%s$" % key
|
||||
line = line.replace(tag, str(value))
|
||||
config += line
|
||||
|
||||
caffemodel = open(args.model, 'rb').read()
|
||||
|
||||
opt_flow = OpticalFlow(caffemodel, var['ADAPTED_HEIGHT'], var['ADAPTED_WIDTH'], bytearray(config.encode()))
|
||||
else:
|
||||
opt_flow = OpticalFlow(args.model, 360, 480)
|
||||
opt_flow = OpticalFlow(args.model, 360, 480)
|
||||
|
||||
while cv.waitKey(1) < 0:
|
||||
hasFrame, second_frame = cap.read()
|
||||
|
||||
Reference in New Issue
Block a user