mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge pull request #23319 from fengyuentau:fix_zoo_issue_136
Related issue: https://github.com/opencv/opencv_zoo/issues/136 Features added: - Support operators with multiple output: ONNX Split. - Support Slice without steps. Bugs fixed: - Wrong settings in ClipByValue (Relu6). - Wrong calculation of pads in convolution layer (It is wrong generally but only fixed specifically for CANN for now). ### 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 Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -124,6 +124,30 @@ void NetImplCann::initBackend(const std::vector<LayerPin>& blobsToKeep_)
|
||||
if (!newWasSupported)
|
||||
return ;
|
||||
|
||||
// initialize each blob wrappers' names
|
||||
for (MapIdToLayerData::const_iterator it = layers.begin(); it != layers.end(); ++it)
|
||||
{
|
||||
const LayerData& ld = it->second;
|
||||
if (ld.id == 0)
|
||||
{
|
||||
for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i)
|
||||
{
|
||||
auto cannWrapper = ld.outputBlobsWrappers[i].dynamicCast<CannBackendWrapper>();
|
||||
// cannWrapper->name = netInputLayer->outNames.empty() ? cv::format("%s_%d", ld.name.c_str(), i) : netInputLayer->outNames[i];
|
||||
cannWrapper->name = std::string("y");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i)
|
||||
{
|
||||
auto cannWrapper = ld.outputBlobsWrappers[i].dynamicCast<CannBackendWrapper>();
|
||||
// cannWrapper->name = ld.outputBlobsWrappers.size() > 1 ? (ld.name + ":" + std::to_string(i)) : ld.name;
|
||||
cannWrapper->name = ld.outputBlobsWrappers.size() > 1 ? (std::string("y") + std::to_string(i)) : std::string("y");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert layers to CANN operators,
|
||||
// collect graph input and output operators,
|
||||
// collect and input and output wrappers
|
||||
@@ -141,15 +165,16 @@ void NetImplCann::initBackend(const std::vector<LayerPin>& blobsToKeep_)
|
||||
{
|
||||
for (int i = 0; i < ld.outputBlobsWrappers.size(); i++)
|
||||
{
|
||||
std::string inputName = netInputLayer->outNames.empty() ? cv::format("%s_%d", ld.name.c_str(), i) : netInputLayer->outNames[i];
|
||||
auto inputOp = std::make_shared<ge::op::Data>(inputName);
|
||||
|
||||
// retrieve tensor description
|
||||
auto wrapper = ld.outputBlobsWrappers[i];
|
||||
graphInputWrappers.push_back(wrapper);
|
||||
auto cannWrapper = wrapper.dynamicCast<CannBackendWrapper>();
|
||||
CV_Assert(!cannWrapper.empty());
|
||||
|
||||
// create graph input op
|
||||
std::string inputOpName = netInputLayer->outNames.empty() ? cv::format("%s_%d", ld.name.c_str(), i) : netInputLayer->outNames[i];
|
||||
auto inputOp = std::make_shared<ge::op::Data>(inputOpName);
|
||||
|
||||
inputOp->update_input_desc_x(*(cannWrapper->desc_));
|
||||
inputOp->update_output_desc_y(*(cannWrapper->desc_));
|
||||
|
||||
@@ -170,14 +195,14 @@ void NetImplCann::initBackend(const std::vector<LayerPin>& blobsToKeep_)
|
||||
{
|
||||
layerInputNodes.push_back(netInputNodes[layerInputOid]);
|
||||
}
|
||||
else // here we do not consider an op with multiple outputs
|
||||
else
|
||||
{
|
||||
layerInputNodes.push_back(layers[layerInputLid].backendNodes[preferableBackend]);
|
||||
}
|
||||
}
|
||||
|
||||
CV_LOG_INFO(NULL, "DNN/CANN: converting layer " << ld.name << "@" << ld.type << "@" << ld.id << " to CANN operator");
|
||||
auto backendNode = layer->initCann(ld.inputBlobsWrappers, ld.id, layerInputNodes);
|
||||
auto backendNode = layer->initCann(ld.inputBlobsWrappers, layerInputNodes); // it's ok if ld.name is empty
|
||||
|
||||
// collect outputs
|
||||
bool isOutputNode = ld.consumers.size() == 0 ? true : false;
|
||||
@@ -201,7 +226,7 @@ void NetImplCann::initBackend(const std::vector<LayerPin>& blobsToKeep_)
|
||||
|
||||
// build graph from collected graph inputs and outputs
|
||||
CV_LOG_INFO(NULL, "DNN/CANN: building ge::Graph");
|
||||
std::string graphName = cv::format("graph_%d", 0);
|
||||
std::string graphName = cv::format("graph_%d", networkId);
|
||||
std::shared_ptr<ge::Graph> graph = std::make_shared<ge::Graph>(graphName.c_str());
|
||||
(void)graph->SetInputs(graphInputOps);
|
||||
(void)graph->SetOutputs(graphOutputOps);
|
||||
@@ -292,9 +317,9 @@ std::shared_ptr<ge::ModelBufferData> compileCannGraph(std::shared_ptr<ge::Graph>
|
||||
|
||||
#if 0
|
||||
// (optional). Dump model
|
||||
AscendString graph_name;
|
||||
graph.GetName(graph_name);
|
||||
aclgrphDumpGraph(graph, graph_name.GetString(), 7);
|
||||
ge::AscendString graph_name;
|
||||
graph->GetName(graph_name);
|
||||
aclgrphDumpGraph(*graph, graph_name.GetString(), 7);
|
||||
// (optional). Save model
|
||||
aclgrphSaveModel(graph_name.GetString(), *om_model);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user