mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
dnn: reading IR models from buffer
This commit is contained in:
parent
7523c777c5
commit
aa80f754f4
@ -384,7 +384,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
|
|||||||
CV_WRAP Net(); //!< Default constructor.
|
CV_WRAP Net(); //!< Default constructor.
|
||||||
CV_WRAP ~Net(); //!< Destructor frees the net only if there aren't references to the net anymore.
|
CV_WRAP ~Net(); //!< Destructor frees the net only if there aren't references to the net anymore.
|
||||||
|
|
||||||
/** @brief Create a network from Intel's Model Optimizer intermediate representation.
|
/** @brief Create a network from Intel's Model Optimizer intermediate representation (IR).
|
||||||
* @param[in] xml XML configuration file with network's topology.
|
* @param[in] xml XML configuration file with network's topology.
|
||||||
* @param[in] bin Binary file with trained weights.
|
* @param[in] bin Binary file with trained weights.
|
||||||
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
|
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
|
||||||
@ -392,6 +392,25 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
|
|||||||
*/
|
*/
|
||||||
CV_WRAP static Net readFromModelOptimizer(const String& xml, const String& bin);
|
CV_WRAP static Net readFromModelOptimizer(const String& xml, const String& bin);
|
||||||
|
|
||||||
|
/** @brief Create a network from Intel's Model Optimizer in-memory buffers with intermediate representation (IR).
|
||||||
|
* @param[in] bufferModelConfig buffer with model's configuration.
|
||||||
|
* @param[in] bufferWeights buffer with model's trained weights.
|
||||||
|
* @returns Net object.
|
||||||
|
*/
|
||||||
|
CV_WRAP static
|
||||||
|
Net readFromModelOptimizer(const std::vector<uchar>& bufferModelConfig, const std::vector<uchar>& bufferWeights);
|
||||||
|
|
||||||
|
/** @brief Create a network from Intel's Model Optimizer in-memory buffers with intermediate representation (IR).
|
||||||
|
* @param[in] bufferModelConfigPtr buffer pointer of model's configuration.
|
||||||
|
* @param[in] bufferModelConfigSize buffer size of model's configuration.
|
||||||
|
* @param[in] bufferWeightsPtr buffer pointer of model's trained weights.
|
||||||
|
* @param[in] bufferWeightsSize buffer size of model's trained weights.
|
||||||
|
* @returns Net object.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
Net readFromModelOptimizer(const uchar* bufferModelConfigPtr, size_t bufferModelConfigSize,
|
||||||
|
const uchar* bufferWeightsPtr, size_t bufferWeightsSize);
|
||||||
|
|
||||||
/** Returns true if there are no layers in the network. */
|
/** Returns true if there are no layers in the network. */
|
||||||
CV_WRAP bool empty() const;
|
CV_WRAP bool empty() const;
|
||||||
|
|
||||||
@ -857,7 +876,31 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
|
|||||||
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
|
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
|
||||||
* backend.
|
* backend.
|
||||||
*/
|
*/
|
||||||
CV_EXPORTS_W Net readNetFromModelOptimizer(const String &xml, const String &bin);
|
CV_EXPORTS_W
|
||||||
|
Net readNetFromModelOptimizer(const String &xml, const String &bin);
|
||||||
|
|
||||||
|
/** @brief Load a network from Intel's Model Optimizer intermediate representation.
|
||||||
|
* @param[in] bufferModelConfig Buffer contains XML configuration with network's topology.
|
||||||
|
* @param[in] bufferWeights Buffer contains binary data with trained weights.
|
||||||
|
* @returns Net object.
|
||||||
|
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
|
||||||
|
* backend.
|
||||||
|
*/
|
||||||
|
CV_EXPORTS_W
|
||||||
|
Net readNetFromModelOptimizer(const std::vector<uchar>& bufferModelConfig, const std::vector<uchar>& bufferWeights);
|
||||||
|
|
||||||
|
/** @brief Load a network from Intel's Model Optimizer intermediate representation.
|
||||||
|
* @param[in] bufferModelConfigPtr Pointer to buffer which contains XML configuration with network's topology.
|
||||||
|
* @param[in] bufferModelConfigSize Binary size of XML configuration data.
|
||||||
|
* @param[in] bufferWeightsPtr Pointer to buffer which contains binary data with trained weights.
|
||||||
|
* @param[in] bufferWeightsSize Binary size of trained weights data.
|
||||||
|
* @returns Net object.
|
||||||
|
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
|
||||||
|
* backend.
|
||||||
|
*/
|
||||||
|
CV_EXPORTS
|
||||||
|
Net readNetFromModelOptimizer(const uchar* bufferModelConfigPtr, size_t bufferModelConfigSize,
|
||||||
|
const uchar* bufferWeightsPtr, size_t bufferWeightsSize);
|
||||||
|
|
||||||
/** @brief Reads a network model <a href="https://onnx.ai/">ONNX</a>.
|
/** @brief Reads a network model <a href="https://onnx.ai/">ONNX</a>.
|
||||||
* @param onnxFile path to the .onnx file with text description of the network architecture.
|
* @param onnxFile path to the .onnx file with text description of the network architecture.
|
||||||
|
@ -2910,28 +2910,22 @@ struct Net::Impl
|
|||||||
return getBlobAsync(getPinByAlias(outputName));
|
return getBlobAsync(getPinByAlias(outputName));
|
||||||
}
|
}
|
||||||
#endif // CV_CXX11
|
#endif // CV_CXX11
|
||||||
|
|
||||||
|
#ifdef HAVE_INF_ENGINE
|
||||||
|
static
|
||||||
|
Net createNetworkFromModelOptimizer(InferenceEngine::CNNNetwork& ieNet);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
Net::Net() : impl(new Net::Impl)
|
Net::Net() : impl(new Net::Impl)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Net Net::readFromModelOptimizer(const String& xml, const String& bin)
|
#ifdef HAVE_INF_ENGINE
|
||||||
|
/*static*/
|
||||||
|
Net Net::Impl::createNetworkFromModelOptimizer(InferenceEngine::CNNNetwork& ieNet)
|
||||||
{
|
{
|
||||||
#ifndef HAVE_INF_ENGINE
|
CV_TRACE_FUNCTION();
|
||||||
CV_Error(Error::StsError, "Build OpenCV with Inference Engine to enable loading models from Model Optimizer.");
|
|
||||||
#else
|
|
||||||
|
|
||||||
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R3)
|
|
||||||
InferenceEngine::CNNNetReader reader;
|
|
||||||
reader.ReadNetwork(xml);
|
|
||||||
reader.ReadWeights(bin);
|
|
||||||
|
|
||||||
InferenceEngine::CNNNetwork ieNet = reader.getNetwork();
|
|
||||||
#else
|
|
||||||
InferenceEngine::Core& ie = getCore();
|
|
||||||
InferenceEngine::CNNNetwork ieNet = ie.ReadNetwork(xml, bin);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::vector<String> inputsNames;
|
std::vector<String> inputsNames;
|
||||||
for (auto& it : ieNet.getInputsInfo())
|
for (auto& it : ieNet.getInputsInfo())
|
||||||
@ -3001,9 +2995,95 @@ Net Net::readFromModelOptimizer(const String& xml, const String& bin)
|
|||||||
|
|
||||||
cvNet.impl->skipInfEngineInit = true;
|
cvNet.impl->skipInfEngineInit = true;
|
||||||
return cvNet;
|
return cvNet;
|
||||||
|
}
|
||||||
|
#endif // HAVE_INF_ENGINE
|
||||||
|
|
||||||
|
Net Net::readFromModelOptimizer(const String& xml, const String& bin)
|
||||||
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
|
#ifndef HAVE_INF_ENGINE
|
||||||
|
CV_UNUSED(xml); CV_UNUSED(bin);
|
||||||
|
CV_Error(Error::StsError, "Build OpenCV with Inference Engine to enable loading models from Model Optimizer.");
|
||||||
|
#else
|
||||||
|
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R3)
|
||||||
|
InferenceEngine::CNNNetReader reader;
|
||||||
|
reader.ReadNetwork(xml);
|
||||||
|
reader.ReadWeights(bin);
|
||||||
|
|
||||||
|
InferenceEngine::CNNNetwork ieNet = reader.getNetwork();
|
||||||
|
#else
|
||||||
|
InferenceEngine::Core& ie = getCore();
|
||||||
|
InferenceEngine::CNNNetwork ieNet = ie.ReadNetwork(xml, bin);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return Impl::createNetworkFromModelOptimizer(ieNet);
|
||||||
#endif // HAVE_INF_ENGINE
|
#endif // HAVE_INF_ENGINE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Net Net::readFromModelOptimizer(const std::vector<uchar>& bufferModelConfig, const std::vector<uchar>& bufferWeights)
|
||||||
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
|
CV_Assert(!bufferModelConfig.empty());
|
||||||
|
CV_Assert(!bufferWeights.empty());
|
||||||
|
return readFromModelOptimizer(bufferModelConfig.data(), bufferModelConfig.size(),
|
||||||
|
bufferWeights.data(), bufferWeights.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
Net Net::readFromModelOptimizer(
|
||||||
|
const uchar* bufferModelConfigPtr, size_t bufferModelConfigSize,
|
||||||
|
const uchar* bufferWeightsPtr, size_t bufferWeightsSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
|
#ifndef HAVE_INF_ENGINE
|
||||||
|
CV_UNUSED(bufferModelConfigPtr); CV_UNUSED(bufferWeightsPtr);
|
||||||
|
CV_UNUSED(bufferModelConfigSize); CV_UNUSED(bufferModelConfigSize);
|
||||||
|
CV_Error(Error::StsError, "Build OpenCV with Inference Engine to enable loading models from Model Optimizer.");
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R3)
|
||||||
|
InferenceEngine::CNNNetReader reader;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
reader.ReadNetwork(bufferModelConfigPtr, bufferModelConfigSize);
|
||||||
|
|
||||||
|
InferenceEngine::TensorDesc tensorDesc(InferenceEngine::Precision::U8, { bufferWeightsSize }, InferenceEngine::Layout::C);
|
||||||
|
InferenceEngine::TBlob<uint8_t>::Ptr weightsBlobPtr(new InferenceEngine::TBlob<uint8_t>(tensorDesc));
|
||||||
|
weightsBlobPtr->allocate();
|
||||||
|
std::memcpy(weightsBlobPtr->buffer(), (uchar*)bufferWeightsPtr, bufferWeightsSize);
|
||||||
|
reader.SetWeights(weightsBlobPtr);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
CV_Error(Error::StsError, std::string("DNN: IE failed to load model: ") + e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
InferenceEngine::CNNNetwork ieNet = reader.getNetwork();
|
||||||
|
#else
|
||||||
|
InferenceEngine::Core& ie = getCore();
|
||||||
|
|
||||||
|
std::string model; model.assign((char*)bufferModelConfigPtr, bufferModelConfigSize);
|
||||||
|
|
||||||
|
InferenceEngine::CNNNetwork ieNet;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InferenceEngine::TensorDesc tensorDesc(InferenceEngine::Precision::U8, { bufferWeightsSize }, InferenceEngine::Layout::C);
|
||||||
|
InferenceEngine::Blob::CPtr weights_blob = InferenceEngine::make_shared_blob<uint8_t>(tensorDesc, (uint8_t*)bufferWeightsPtr, bufferWeightsSize);
|
||||||
|
|
||||||
|
ieNet = ie.ReadNetwork(model, weights_blob);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
CV_Error(Error::StsError, std::string("DNN: IE failed to load model: ") + e.what());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return Impl::createNetworkFromModelOptimizer(ieNet);
|
||||||
|
#endif // HAVE_INF_ENGINE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Net::~Net()
|
Net::~Net()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -4344,7 +4424,7 @@ Net readNet(const String& _framework, const std::vector<uchar>& bufferModel,
|
|||||||
else if (framework == "torch")
|
else if (framework == "torch")
|
||||||
CV_Error(Error::StsNotImplemented, "Reading Torch models from buffers");
|
CV_Error(Error::StsNotImplemented, "Reading Torch models from buffers");
|
||||||
else if (framework == "dldt")
|
else if (framework == "dldt")
|
||||||
CV_Error(Error::StsNotImplemented, "Reading Intel's Model Optimizer models from buffers");
|
return readNetFromModelOptimizer(bufferConfig, bufferModel);
|
||||||
CV_Error(Error::StsError, "Cannot determine an origin framework with a name " + framework);
|
CV_Error(Error::StsError, "Cannot determine an origin framework with a name " + framework);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4353,5 +4433,21 @@ Net readNetFromModelOptimizer(const String &xml, const String &bin)
|
|||||||
return Net::readFromModelOptimizer(xml, bin);
|
return Net::readFromModelOptimizer(xml, bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Net readNetFromModelOptimizer(const std::vector<uchar>& bufferCfg, const std::vector<uchar>& bufferModel)
|
||||||
|
{
|
||||||
|
return Net::readFromModelOptimizer(bufferCfg, bufferModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Net readNetFromModelOptimizer(
|
||||||
|
const uchar* bufferModelConfigPtr, size_t bufferModelConfigSize,
|
||||||
|
const uchar* bufferWeightsPtr, size_t bufferWeightsSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return Net::readFromModelOptimizer(
|
||||||
|
bufferModelConfigPtr, bufferModelConfigSize,
|
||||||
|
bufferWeightsPtr, bufferWeightsSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
CV__DNN_EXPERIMENTAL_NS_END
|
CV__DNN_EXPERIMENTAL_NS_END
|
||||||
}} // namespace
|
}} // namespace
|
||||||
|
@ -637,6 +637,60 @@ TEST_P(Test_Model_Optimizer, forward_two_nets)
|
|||||||
|
|
||||||
normAssert(ref0, ref2, 0, 0);
|
normAssert(ref0, ref2, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(Test_Model_Optimizer, readFromBuffer)
|
||||||
|
{
|
||||||
|
const Backend backendId = get<0>(GetParam());
|
||||||
|
const Target targetId = get<1>(GetParam());
|
||||||
|
|
||||||
|
if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||||
|
throw SkipTestException("No support for async forward");
|
||||||
|
|
||||||
|
const std::string suffix = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? "_fp16" : "";
|
||||||
|
const std::string& weightsFile = findDataFile("dnn/layers/layer_convolution" + suffix + ".bin");
|
||||||
|
const std::string& modelFile = findDataFile("dnn/layers/layer_convolution" + suffix + ".xml");
|
||||||
|
|
||||||
|
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||||
|
setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API);
|
||||||
|
else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||||
|
setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH);
|
||||||
|
else
|
||||||
|
FAIL() << "Unknown backendId";
|
||||||
|
|
||||||
|
Net net1 = readNetFromModelOptimizer(modelFile, weightsFile);
|
||||||
|
net1.setPreferableBackend(backendId);
|
||||||
|
net1.setPreferableTarget(targetId);
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<char> modelConfig;
|
||||||
|
readFileContent(modelFile, modelConfig);
|
||||||
|
std::vector<char> weights;
|
||||||
|
readFileContent(weightsFile, weights);
|
||||||
|
|
||||||
|
Net net2 = readNetFromModelOptimizer(
|
||||||
|
(const uchar*)modelConfig.data(), modelConfig.size(),
|
||||||
|
(const uchar*)weights.data(), weights.size()
|
||||||
|
);
|
||||||
|
net2.setPreferableBackend(backendId);
|
||||||
|
net2.setPreferableTarget(targetId);
|
||||||
|
|
||||||
|
int blobSize[] = {2, 6, 75, 113};
|
||||||
|
Mat input(4, &blobSize[0], CV_32F);
|
||||||
|
randu(input, 0, 255);
|
||||||
|
|
||||||
|
Mat ref, actual;
|
||||||
|
{
|
||||||
|
net1.setInput(input);
|
||||||
|
ref = net1.forward();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
net2.setInput(input);
|
||||||
|
actual = net2.forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
normAssert(ref, actual, "", 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(/**/, Test_Model_Optimizer,
|
INSTANTIATE_TEST_CASE_P(/**/, Test_Model_Optimizer,
|
||||||
dnnBackendsAndTargetsIE()
|
dnnBackendsAndTargetsIE()
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user