1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #28058 from nklskyoy:onnx-importer2-dispatch-map

Onnx importer2 dispatch map #28058

I have noticed that PR[28032]( https://github.com/opencv/opencv/pull/28032) was incomplete - it fixed only the new ONNX importer. Also, building the dispatch map based on the parsed opset version hypotetically can cause trouble if the graph simplifier inserts a node with a different opset version which is not included in the dispatch map. So I removed this parameter in `buildDispatchMap_COM_MICROSOFT` and `buildDispatchMap_ONNX_AI` for now. It was marked as `CV_UNUSED` anyway. 

### 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
- [ ] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
nklskyoy
2025-11-26 11:56:02 +01:00
committed by GitHub
parent 74fae2770e
commit b258926e54
5 changed files with 49 additions and 60 deletions
+1 -1
View File
@@ -64,7 +64,7 @@ Net::Impl::Impl()
modelFormat = DNN_MODEL_GENERIC;
originalLayout = DATA_LAYOUT_NCHW;
onnx_opset = 0;
// onnx_opset = 0;
accuracy = CV_32F;
enableFP16 = haveFP16 = false;
+1 -1
View File
@@ -73,7 +73,7 @@ struct Net::Impl : public detail::NetImplBase
std::string modelFileName;
ModelFormat modelFormat;
DataLayout originalLayout;
int onnx_opset;
// int onnx_opset;
NamesHash argnames;
NamesHash dimnames;
-4
View File
@@ -1119,10 +1119,6 @@ std::ostream& Net::Impl::dump(std::ostream& strm)
strm << "{\n";
prindent(strm, indent);
strm << "model_format: \"" << modelFormatToString(modelFormat) << "\",\n";
if (modelFormat == DNN_MODEL_ONNX) {
prindent(strm, indent);
strm << "onnx_opset: " << onnx_opset << ",\n";
}
prindent(strm, indent);
strm << "layout: \"" << layoutToString(originalLayout) << "\",\n";
if (mainGraph) {
+23 -22
View File
@@ -141,8 +141,8 @@ private:
DomainDispatchMap domain_dispatch_map;
std::string getLayerTypeDomain(const opencv_onnx::NodeProto& node_proto);
const DispatchMap& getDispatchMap(const opencv_onnx::NodeProto& node_proto);
void buildDispatchMap_ONNX_AI(int opset_version);
void buildDispatchMap_COM_MICROSOFT(int opset_version);
void buildDispatchMap_ONNX_AI();
void buildDispatchMap_COM_MICROSOFT();
// Domain: 'ai.onnx' (default)
// URL: https://github.com/onnx/onnx/blob/master/docs/Operators.md
@@ -220,12 +220,11 @@ private:
// '???' domain or '???' layer type
void parseCustomLayer (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
int onnx_opset; // OperatorSetIdProto for 'onnx' domain
std::map<std::string, int> onnx_opset_map; // map from OperatorSetIdProto
void parseOperatorSet();
const std::string str_domain_ai_onnx = "ai.onnx";
const std::string str_domain_com_microsoft = "com.microsoft";
bool useLegacyNames;
bool getParamUseLegacyNames()
@@ -272,7 +271,6 @@ void ONNXLayerHandler::fillRegistry(const opencv_onnx::GraphProto &net)
ONNXImporter::ONNXImporter(Net& net, const char *onnxFile)
: layerHandler(DNN_DIAGNOSTICS_RUN ? new ONNXLayerHandler(this) : nullptr)
, dstNet(net)
, onnx_opset(0)
, useLegacyNames(getParamUseLegacyNames())
{
hasDynamicShapes = false;
@@ -296,7 +294,6 @@ ONNXImporter::ONNXImporter(Net& net, const char *onnxFile)
ONNXImporter::ONNXImporter(Net& net, const char* buffer, size_t sizeBuffer)
: layerHandler(DNN_DIAGNOSTICS_RUN ? new ONNXLayerHandler(this) : nullptr)
, dstNet(net)
, onnx_opset(0)
, useLegacyNames(getParamUseLegacyNames())
{
hasDynamicShapes = false;
@@ -705,22 +702,24 @@ void ONNXImporter::parseOperatorSet()
const ::opencv_onnx::OperatorSetIdProto& opset_entry = model_proto.opset_import(i);
const std::string& domain = opset_entry.has_domain() ? opset_entry.domain() : std::string();
int version = opset_entry.has_version() ? opset_entry.version() : -1;
if (domain.empty() || domain == str_domain_ai_onnx)
{
// ONNX opset covered by specification: https://github.com/onnx/onnx/blob/master/docs/Operators.md
onnx_opset = std::max(onnx_opset, version);
onnx_opset_map[str_domain_ai_onnx] = onnx_opset;
}
const std::string domain_key = domain.empty() ? str_domain_ai_onnx : domain;
if (onnx_opset_map.find(domain_key) == onnx_opset_map.end())
onnx_opset_map[domain_key] = version;
else
onnx_opset_map[domain_key] = std::max(
onnx_opset_map[domain_key], version);
if (
domain_key != str_domain_ai_onnx &&
domain_key != str_domain_com_microsoft)
{
CV_LOG_DEBUG(NULL, "DNN/ONNX: using non-standard ONNX opset[" << i << "]: domain='" << domain << "' version=" << version);
onnx_opset_map[domain] = onnx_opset;
CV_LOG_INFO(NULL, "DNN/ONNX: found opset[" << i << "]: domain='" << domain_key << "' version=" << version);
}
}
CV_LOG_INFO(NULL, "DNN/ONNX: ONNX opset version = " << onnx_opset);
// CV_LOG_INFO(NULL, "DNN/ONNX: ONNX opset version = " << onnx_opset);
buildDispatchMap_ONNX_AI(onnx_opset);
buildDispatchMap_ONNX_AI(); // onnx_opset_map[str_domain_ai_onnx]);
buildDispatchMap_COM_MICROSOFT(); // onnx_opset_map[str_domain_com_microsoft]);
for (const auto& pair : onnx_opset_map)
{
if (pair.first == str_domain_ai_onnx)
@@ -729,7 +728,7 @@ void ONNXImporter::parseOperatorSet()
}
else if (pair.first == "com.microsoft")
{
buildDispatchMap_COM_MICROSOFT(pair.second);
buildDispatchMap_COM_MICROSOFT();
}
else
{
@@ -2811,7 +2810,11 @@ void ONNXImporter::parseSoftMax(LayerParams& layerParams, const opencv_onnx::Nod
{
const std::string& layer_type = node_proto.op_type();
int axis;
if (onnx_opset != 0 && onnx_opset <= 11) {
if (onnx_opset_map.find(str_domain_ai_onnx) == onnx_opset_map.end()) {
CV_Error(Error::StsParseError , "ONNX/Softmax: opset for ai.onnx domain is not found");
}
const int opset_onnx_ai = onnx_opset_map[str_domain_ai_onnx];
if (opset_onnx_ai != 0 && opset_onnx_ai <= 11) {
axis = layerParams.get<int>("axis", 1);
} else {
axis = layerParams.get<int>("axis", -1);
@@ -3954,9 +3957,8 @@ void ONNXImporter::parseAttention(LayerParams& params, const opencv_onnx::NodePr
// Domain: ai.onnx (default)
// URL: https://github.com/onnx/onnx/blob/master/docs/Operators.md
void ONNXImporter::buildDispatchMap_ONNX_AI(int opset_version)
void ONNXImporter::buildDispatchMap_ONNX_AI()
{
CV_UNUSED(opset_version);
DispatchMap dispatch;
dispatch["ArgMax"] = dispatch["ArgMin"] = &ONNXImporter::parseArg;
@@ -4049,9 +4051,8 @@ void ONNXImporter::buildDispatchMap_ONNX_AI(int opset_version)
// Domain: com.microsoft
// URL: https://github.com/microsoft/onnxruntime/blob/master/docs/ContribOperators.md
void ONNXImporter::buildDispatchMap_COM_MICROSOFT(int opset_version)
void ONNXImporter::buildDispatchMap_COM_MICROSOFT()
{
CV_UNUSED(opset_version);
DispatchMap dispatch;
dispatch["QLinearAdd"] = dispatch["QLinearMul"] = &ONNXImporter::parseQEltwise;
+24 -32
View File
@@ -166,8 +166,8 @@ protected:
DomainDispatchMap domain_dispatch_map;
std::string getLayerTypeDomain(const opencv_onnx::NodeProto& node_proto);
const DispatchMap& getDispatchMap(const opencv_onnx::NodeProto& node_proto);
void buildDispatchMap_ONNX_AI(int opset_version);
void buildDispatchMap_COM_MICROSOFT(int opset_version);
void buildDispatchMap_ONNX_AI();
void buildDispatchMap_COM_MICROSOFT();
// Domain: 'ai.onnx' (default)
// URL: https://github.com/onnx/onnx/blob/master/docs/Operators.md
@@ -264,7 +264,6 @@ protected:
//void parseQSigmoid (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
//void parseQSoftmax (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
int onnx_opset; // OperatorSetIdProto for 'onnx' domain
std::map<std::string, int> onnx_opset_map; // map from OperatorSetIdProto
void parseOperatorSet();
@@ -282,7 +281,6 @@ protected:
};
ONNXImporter2::ONNXImporter2() :
onnx_opset(0),
useLegacyNames(getParamUseLegacyNames())
{
netimpl = net.getImpl();
@@ -577,33 +575,24 @@ void ONNXImporter2::parseOperatorSet()
const ::opencv_onnx::OperatorSetIdProto& opset_entry = model_proto.opset_import(i);
const std::string& domain = opset_entry.has_domain() ? opset_entry.domain() : std::string();
int version = opset_entry.has_version() ? opset_entry.version() : -1;
if (domain.empty() || domain == str_domain_ai_onnx)
{
// ONNX opset covered by specification: https://github.com/onnx/onnx/blob/master/docs/Operators.md
onnx_opset = std::max(onnx_opset, version);
onnx_opset_map[str_domain_ai_onnx] = onnx_opset;
}
const std::string domain_key = domain.empty() ? str_domain_ai_onnx : domain;
if (onnx_opset_map.find(domain_key) == onnx_opset_map.end())
onnx_opset_map[domain_key] = version;
else
onnx_opset_map[domain_key] = std::max(
onnx_opset_map[domain_key], version);
if (
domain_key != str_domain_ai_onnx &&
domain_key != str_domain_com_microsoft)
{
CV_LOG_DEBUG(NULL, "DNN/ONNX: using non-standard ONNX opset[" << i << "]: domain='" << domain << "' version=" << version);
onnx_opset_map[domain] = onnx_opset;
CV_LOG_INFO(NULL, "DNN/ONNX: found opset[" << i << "]: domain='" << domain_key << "' version=" << version);
}
}
buildDispatchMap_ONNX_AI();
buildDispatchMap_COM_MICROSOFT();
CV_LOG_INFO(NULL, "DNN/ONNX: ONNX opset version = " << onnx_opset);
buildDispatchMap_ONNX_AI(onnx_opset);
buildDispatchMap_COM_MICROSOFT(onnx_opset);
for (const auto& pair : onnx_opset_map)
{
if ((pair.first != str_domain_ai_onnx) && (pair.first != str_domain_com_microsoft))
CV_LOG_INFO(
NULL,
"DNN/ONNX: unknown domain='" << pair.first << "' version=" << pair.second << ". No dispatch map, you may need to register 'custom' layers."
);
}
}
/*static bool ifInt8Output(const String& layerType)
@@ -679,7 +668,7 @@ Net ONNXImporter2::parseModel()
netimpl->mainGraph = mainGraph;
netimpl->modelFormat = DNN_MODEL_ONNX;
netimpl->originalLayout = DATA_LAYOUT_NCHW;
netimpl->onnx_opset = onnx_opset;
// netimpl->onnx_opset = onnx_opset;
if (have_errors) {
std::stringstream sstrm;
@@ -1877,7 +1866,12 @@ void ONNXImporter2::parseSoftMax(LayerParams& layerParams, const opencv_onnx::No
{
const std::string& layer_type = node_proto.op_type();
int axis;
if (onnx_opset != 0 && onnx_opset <= 11) {
if (onnx_opset_map.find(str_domain_ai_onnx) == onnx_opset_map.end()) {
CV_Error(Error::StsParseError , "ONNX/Softmax: opset for ai.onnx domain is not found");
}
const int opset_onnx_ai = onnx_opset_map[str_domain_ai_onnx];
if (opset_onnx_ai != 0 && opset_onnx_ai <= 11) {
axis = layerParams.get<int>("axis", 1);
} else {
axis = layerParams.get<int>("axis", -1);
@@ -2619,9 +2613,8 @@ void ONNXImporter2::parseAttention(LayerParams& params, const opencv_onnx::NodeP
// Domain: ai.onnx (default)
// URL: https://github.com/onnx/onnx/blob/master/docs/Operators.md
void ONNXImporter2::buildDispatchMap_ONNX_AI(int opset_version)
void ONNXImporter2::buildDispatchMap_ONNX_AI()
{
CV_UNUSED(opset_version);
DispatchMap dispatch;
dispatch["ArgMax"] = dispatch["ArgMin"] = &ONNXImporter2::parseArgMinMax;
@@ -2738,9 +2731,8 @@ void ONNXImporter2::buildDispatchMap_ONNX_AI(int opset_version)
// Domain: com.microsoft
// URL: https://github.com/microsoft/onnxruntime/blob/master/docs/ContribOperators.md
void ONNXImporter2::buildDispatchMap_COM_MICROSOFT(int opset_version)
void ONNXImporter2::buildDispatchMap_COM_MICROSOFT()
{
CV_UNUSED(opset_version);
DispatchMap dispatch;
// BUG: https://github.com/opencv/opencv/issues/26310