mirror of
https://github.com/opencv/opencv.git
synced 2025-07-25 22:57:53 +08:00
Merge pull request #20478 from rogday:onnx_refactor_master
This commit is contained in:
commit
610e3dccb7
@ -14,6 +14,7 @@ Mutex& getInitializationMutex();
|
||||
void initializeLayerFactory();
|
||||
|
||||
namespace detail {
|
||||
#define CALL_MEMBER_FN(object, ptrToMemFn) ((object).*(ptrToMemFn))
|
||||
|
||||
class NotImplemented : public Layer
|
||||
{
|
||||
|
@ -66,7 +66,7 @@ class ONNXImporter
|
||||
public:
|
||||
|
||||
ONNXImporter(Net& net, const char *onnxFile)
|
||||
: dstNet(net), utilNet()
|
||||
: dstNet(net), utilNet(), dispatch(buildDispatchMap())
|
||||
{
|
||||
hasDynamicShapes = false;
|
||||
CV_Assert(onnxFile);
|
||||
@ -87,7 +87,7 @@ public:
|
||||
}
|
||||
|
||||
ONNXImporter(Net& net, const char* buffer, size_t sizeBuffer)
|
||||
: dstNet(net), utilNet()
|
||||
: dstNet(net), utilNet(), dispatch(buildDispatchMap())
|
||||
{
|
||||
hasDynamicShapes = false;
|
||||
CV_LOG_DEBUG(NULL, "DNN/ONNX: processing in-memory ONNX model (" << sizeBuffer << " bytes)");
|
||||
@ -129,6 +129,57 @@ protected:
|
||||
typedef std::map<std::string, LayerInfo>::iterator IterLayerId_t;
|
||||
|
||||
void handleNode(const opencv_onnx::NodeProto& node_proto);
|
||||
|
||||
private:
|
||||
typedef void (ONNXImporter::*ONNXImporterNodeParser)(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
typedef std::map<std::string, ONNXImporterNodeParser> DispatchMap;
|
||||
|
||||
void parseMaxPool (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseAveragePool (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseReduce (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseSlice (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseSplit (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseBias (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parsePow (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseMax (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseNeg (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseConstant (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseLSTM (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseImageScaler (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseClip (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseLeakyRelu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseRelu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseElu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseTanh (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parsePRelu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseLRN (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseInstanceNormalization(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseBatchNormalization (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseGemm (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseMatMul (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseMul (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseConv (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseConvTranspose (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseTranspose (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseSqueeze (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseFlatten (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseUnsqueeze (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseExpand (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseReshape (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parsePad (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseShape (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseCast (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseConstantFill (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseGather (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseConcat (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseResize (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseUpsample (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseSoftMax (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseDetectionOutput (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseCustom (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
|
||||
const DispatchMap dispatch;
|
||||
static const DispatchMap buildDispatchMap();
|
||||
};
|
||||
|
||||
inline void replaceLayerParam(LayerParams& layerParams, const String& oldKey, const String& newKey)
|
||||
@ -585,13 +636,11 @@ const std::set<String>& ONNXImporter::getSupportedTypes()
|
||||
return layerTypes;
|
||||
}
|
||||
|
||||
void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_; // TODO FIXIT
|
||||
|
||||
CV_Assert(node_proto.output_size() >= 1);
|
||||
std::string name = node_proto.output(0);
|
||||
std::string layer_type = node_proto.op_type();
|
||||
const std::string& layer_type = node_proto.op_type();
|
||||
CV_LOG_DEBUG(NULL, "DNN/ONNX: processing node with " << node_proto.input_size() << " inputs and " << node_proto.output_size() << " outputs: "
|
||||
<< cv::format("[%s]:(%s)", layer_type.c_str(), name.c_str())
|
||||
);
|
||||
@ -605,22 +654,86 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
layerParams.type = layer_type;
|
||||
layerParams.set("has_dynamic_shapes", hasDynamicShapes);
|
||||
|
||||
if (layer_type == "MaxPool")
|
||||
DispatchMap::const_iterator iter = dispatch.find(layer_type);
|
||||
if (iter != dispatch.end())
|
||||
{
|
||||
CALL_MEMBER_FN(*this, iter->second)(layerParams, node_proto);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseCustom(layerParams, node_proto);
|
||||
}
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
{
|
||||
if (DNN_DIAGNOSTICS_RUN)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "DNN/ONNX: Potential problem during processing node with " << node_proto.input_size() << " inputs and " << node_proto.output_size() << " outputs: "
|
||||
<< cv::format("[%s]:(%s)", layer_type.c_str(), name.c_str()) << "\n" << e.msg
|
||||
);
|
||||
auto registeredLayers = getLayerFactoryImpl();
|
||||
if (registeredLayers.find(layerParams.type) != registeredLayers.end())
|
||||
{
|
||||
try
|
||||
{
|
||||
Ptr<Layer> layer = LayerFactory::createLayerInstance(layerParams.type, layerParams);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "DNN/ONNX: Layer of type " << layerParams.type << "(" << layer_type << ") cannot be created with parameters " << layerParams << ". Error: " << e.what()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "DNN/ONNX: ERROR during processing node with " << node_proto.input_size() << " inputs and " << node_proto.output_size() << " outputs: "
|
||||
<< cv::format("[%s]:(%s)", layer_type.c_str(), name.c_str())
|
||||
);
|
||||
}
|
||||
for (int i = 0; i < node_proto.input_size(); i++)
|
||||
{
|
||||
CV_LOG_INFO(NULL, " Input[" << i << "] = '" << node_proto.input(i) << "'");
|
||||
}
|
||||
for (int i = 0; i < node_proto.output_size(); i++)
|
||||
{
|
||||
CV_LOG_INFO(NULL, " Output[" << i << "] = '" << node_proto.output(i) << "'");
|
||||
}
|
||||
if (DNN_DIAGNOSTICS_RUN)
|
||||
{
|
||||
for (int i = 0; i < node_proto.output_size(); ++i)
|
||||
{
|
||||
layer_id.insert(std::make_pair(node_proto.output(i), LayerInfo(0, i)));
|
||||
outShapes[node_proto.output(i)] = outShapes[node_proto.input(0)];
|
||||
}
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsError, cv::format("Node [%s]:(%s) parse error: %s", layer_type.c_str(), name.c_str(), e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void ONNXImporter::parseMaxPool(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "Pooling";
|
||||
layerParams.set("pool", "MAX");
|
||||
layerParams.set("ceil_mode", layerParams.has("pad_mode"));
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "AveragePool")
|
||||
|
||||
void ONNXImporter::parseAveragePool(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "Pooling";
|
||||
layerParams.set("pool", "AVE");
|
||||
layerParams.set("ceil_mode", layerParams.has("pad_mode"));
|
||||
layerParams.set("ave_pool_padded_area", framework_name == "pytorch");
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "GlobalAveragePool" || layer_type == "GlobalMaxPool" ||
|
||||
layer_type == "ReduceMean" || layer_type == "ReduceSum" || layer_type == "ReduceMax")
|
||||
|
||||
void ONNXImporter::parseReduce(LayerParams &layerParams, const opencv_onnx::NodeProto &node_proto_)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_;
|
||||
const std::string& layer_type = node_proto.op_type();
|
||||
|
||||
CV_Assert(node_proto.input_size() == 1);
|
||||
layerParams.type = "Pooling";
|
||||
String pool;
|
||||
@ -772,8 +885,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
node_proto.set_input(0, node_proto.output(0));
|
||||
node_proto.set_output(0, layerParams.name);
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Slice")
|
||||
|
||||
void ONNXImporter::parseSlice(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
int axis = 0;
|
||||
std::vector<int> begin;
|
||||
@ -881,8 +996,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
addConstant(layerParams.name, sliced[0]);
|
||||
return;
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Split")
|
||||
|
||||
void ONNXImporter::parseSplit(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
if (layerParams.has("split"))
|
||||
{
|
||||
@ -902,9 +1019,13 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
layerParams.set("num_split", node_proto.output_size());
|
||||
}
|
||||
layerParams.type = "Slice";
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Add" || layer_type == "Sum" || layer_type == "Sub")
|
||||
|
||||
void ONNXImporter::parseBias(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_;
|
||||
const std::string& layer_type = node_proto.op_type();
|
||||
bool isSub = layer_type == "Sub";
|
||||
CV_CheckEQ(node_proto.input_size(), 2, "");
|
||||
bool is_const_0 = layer_id.find(node_proto.input(0)) == layer_id.end();
|
||||
@ -1007,8 +1128,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
layerParams.type = "Scale";
|
||||
layerParams.set("bias_term", true);
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Pow")
|
||||
|
||||
void ONNXImporter::parsePow(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
if (layer_id.find(node_proto.input(1)) != layer_id.end())
|
||||
CV_Error(Error::StsNotImplemented, "Unsupported Pow op with variable power");
|
||||
@ -1020,26 +1143,33 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
blob.convertTo(blob, CV_32F);
|
||||
layerParams.type = "Power";
|
||||
layerParams.set("power", blob.ptr<float>()[0]);
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Max")
|
||||
|
||||
void ONNXImporter::parseMax(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "Eltwise";
|
||||
layerParams.set("operation", "max");
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Neg")
|
||||
|
||||
void ONNXImporter::parseNeg(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "Power";
|
||||
layerParams.set("scale", -1);
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Constant")
|
||||
|
||||
void ONNXImporter::parseConstant(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
CV_Assert(node_proto.input_size() == 0);
|
||||
CV_Assert(layerParams.blobs.size() == 1);
|
||||
addConstant(layerParams.name, layerParams.blobs[0]);
|
||||
return;
|
||||
}
|
||||
else if (layer_type == "LSTM")
|
||||
|
||||
void ONNXImporter::parseLSTM(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_;
|
||||
LayerParams lstmParams = layerParams;
|
||||
lstmParams.name += "/lstm";
|
||||
|
||||
@ -1106,8 +1236,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
layerParams.set("dim", DictValue::arrayInt(&lstmShape[0], lstmShape.size()));
|
||||
node_proto.set_input(0, lstmParams.name); // redirect input to LSTM
|
||||
node_proto.set_output(0, layerParams.name); // keep origin LSTM's name
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "ImageScaler")
|
||||
|
||||
void ONNXImporter::parseImageScaler(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
const float scale = layerParams.has("scale") ? layerParams.get<float>("scale") : 1.0f;
|
||||
layerParams.erase("scale");
|
||||
@ -1130,42 +1262,58 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
layerParams.set("scale", scale);
|
||||
layerParams.type = "Power";
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Clip")
|
||||
|
||||
void ONNXImporter::parseClip(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "ReLU6";
|
||||
replaceLayerParam(layerParams, "min", "min_value");
|
||||
replaceLayerParam(layerParams, "max", "max_value");
|
||||
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "LeakyRelu")
|
||||
|
||||
void ONNXImporter::parseLeakyRelu(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "ReLU";
|
||||
replaceLayerParam(layerParams, "alpha", "negative_slope");
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Relu")
|
||||
|
||||
void ONNXImporter::parseRelu(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "ReLU";
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Elu")
|
||||
|
||||
void ONNXImporter::parseElu(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "ELU";
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Tanh")
|
||||
|
||||
void ONNXImporter::parseTanh(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "TanH";
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "PRelu")
|
||||
|
||||
void ONNXImporter::parsePRelu(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "PReLU";
|
||||
layerParams.blobs.push_back(getBlob(node_proto, 1));
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "LRN")
|
||||
|
||||
void ONNXImporter::parseLRN(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
replaceLayerParam(layerParams, "size", "local_size");
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "InstanceNormalization")
|
||||
|
||||
void ONNXImporter::parseInstanceNormalization(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_;
|
||||
if (node_proto.input_size() != 3)
|
||||
CV_Error(Error::StsNotImplemented,
|
||||
"Expected input, scale, bias");
|
||||
@ -1207,8 +1355,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
//Replace Batch Norm's input to MVN
|
||||
node_proto.set_input(0, mvnParams.name);
|
||||
layerParams.type = "BatchNorm";
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "BatchNormalization")
|
||||
|
||||
void ONNXImporter::parseBatchNormalization(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
if (node_proto.input_size() != 5)
|
||||
CV_Error(Error::StsNotImplemented,
|
||||
@ -1237,8 +1387,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
} else {
|
||||
layerParams.set("has_bias", false);
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Gemm")
|
||||
|
||||
void ONNXImporter::parseGemm(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
CV_Assert(node_proto.input_size() >= 2);
|
||||
layerParams.type = "InnerProduct";
|
||||
@ -1270,8 +1422,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
|
||||
layerParams.set("num_output", layerParams.blobs[0].size[ind_num_out]);
|
||||
layerParams.set("bias_term", node_proto.input_size() == 3);
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "MatMul")
|
||||
|
||||
void ONNXImporter::parseMatMul(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
CV_Assert(node_proto.input_size() == 2);
|
||||
layerParams.type = "InnerProduct";
|
||||
@ -1290,9 +1444,13 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
secondInpDims = outShapes[node_proto.input(1)].size();
|
||||
}
|
||||
layerParams.set("axis", firstInpDims - secondInpDims + 1);
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Mul" || layer_type == "Div")
|
||||
|
||||
void ONNXImporter::parseMul(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_;
|
||||
const std::string& layer_type = node_proto.op_type();
|
||||
CV_Assert(node_proto.input_size() == 2);
|
||||
|
||||
bool isDiv = layer_type == "Div";
|
||||
@ -1417,9 +1575,12 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
}
|
||||
layerParams.type = "Scale";
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Conv")
|
||||
|
||||
void ONNXImporter::parseConv(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_;
|
||||
CV_Assert(node_proto.input_size() >= 2);
|
||||
layerParams.type = "Convolution";
|
||||
for (int j = 1; j < node_proto.input_size(); j++) {
|
||||
@ -1469,8 +1630,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
node_proto.set_input(0, padLp.name);
|
||||
}
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "ConvTranspose")
|
||||
|
||||
void ONNXImporter::parseConvTranspose(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
CV_Assert(node_proto.input_size() >= 2);
|
||||
layerParams.type = "Deconvolution";
|
||||
@ -1512,8 +1675,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
{
|
||||
replaceLayerParam(layerParams, "output_padding", "adj");
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Transpose")
|
||||
|
||||
void ONNXImporter::parseTranspose(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "Permute";
|
||||
replaceLayerParam(layerParams, "perm", "order");
|
||||
@ -1527,8 +1692,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
addConstant(layerParams.name, transposed[0]);
|
||||
return;
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Squeeze")
|
||||
|
||||
void ONNXImporter::parseSqueeze(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
CV_Assert_N(node_proto.input_size() == 1, layerParams.has("axes"));
|
||||
DictValue axes_dict = layerParams.get("axes");
|
||||
@ -1577,8 +1744,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
addConstant(layerParams.name, out);
|
||||
return;
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Flatten")
|
||||
|
||||
void ONNXImporter::parseFlatten(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
CV_CheckEQ(node_proto.input_size(), 1, "");
|
||||
if (constBlobs.find(node_proto.input(0)) != constBlobs.end())
|
||||
@ -1592,8 +1761,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
addConstant(layerParams.name, output);
|
||||
return;
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Unsqueeze")
|
||||
|
||||
void ONNXImporter::parseUnsqueeze(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
CV_Assert(node_proto.input_size() == 1);
|
||||
DictValue axes = layerParams.get("axes");
|
||||
@ -1640,9 +1811,12 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
layerParams.set("dynamic_axes", DictValue::arrayInt(dynamicAxes.data(), dynamicAxes.size()));
|
||||
layerParams.set("input_indices", DictValue::arrayInt(inputIndices.data(), inputIndices.size()));
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Expand")
|
||||
|
||||
void ONNXImporter::parseExpand(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_;
|
||||
CV_CheckEQ(node_proto.input_size(), 2, "");
|
||||
const std::string& input0 = node_proto.input(0);
|
||||
const std::string& input1 = node_proto.input(1);
|
||||
@ -1764,8 +1938,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsNotImplemented, "Unsupported Expand op");
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Reshape")
|
||||
|
||||
void ONNXImporter::parseReshape(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
CV_Assert(node_proto.input_size() == 2 || layerParams.has("shape"));
|
||||
|
||||
@ -1798,8 +1974,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
}
|
||||
replaceLayerParam(layerParams, "shape", "dim");
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Pad")
|
||||
|
||||
void ONNXImporter::parsePad(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "Padding";
|
||||
replaceLayerParam(layerParams, "mode", "type");
|
||||
@ -1817,8 +1995,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
layerParams.set("value", value.ptr<float>()[0]);
|
||||
}
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Shape")
|
||||
|
||||
void ONNXImporter::parseShape(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
CV_Assert(node_proto.input_size() == 1);
|
||||
IterShape_t shapeIt = outShapes.find(node_proto.input(0));
|
||||
@ -1831,9 +2011,9 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
shapeMat.dims = 1;
|
||||
|
||||
addConstant(layerParams.name, shapeMat);
|
||||
return;
|
||||
}
|
||||
else if (layer_type == "Cast")
|
||||
|
||||
void ONNXImporter::parseCast(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
if (constBlobs.find(node_proto.input(0)) != constBlobs.end())
|
||||
{
|
||||
@ -1859,8 +2039,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
}
|
||||
else
|
||||
layerParams.type = "Identity";
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "ConstantOfShape" || layer_type == "ConstantFill")
|
||||
|
||||
void ONNXImporter::parseConstantFill(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
int depth = CV_32F;
|
||||
float fill_value;
|
||||
@ -1880,10 +2062,11 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
CV_CheckGT(inpShape[i], 0, "");
|
||||
Mat tensor(inpShape.size(), &inpShape[0], depth, Scalar(fill_value));
|
||||
addConstant(layerParams.name, tensor);
|
||||
return;
|
||||
}
|
||||
else if (layer_type == "Gather")
|
||||
|
||||
void ONNXImporter::parseGather(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_;
|
||||
CV_Assert(node_proto.input_size() == 2);
|
||||
Mat indexMat = getBlob(node_proto, 1);
|
||||
CV_Assert_N(indexMat.type() == CV_32S, indexMat.total() == 1);
|
||||
@ -1958,8 +2141,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
layerParams = sliceLp;
|
||||
}
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Concat")
|
||||
|
||||
void ONNXImporter::parseConcat(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
bool hasVariableInps = false;
|
||||
for (int i = 0; i < node_proto.input_size(); ++i)
|
||||
@ -2018,8 +2203,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
}
|
||||
}
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Resize")
|
||||
|
||||
void ONNXImporter::parseResize(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
for (int i = 1; i < node_proto.input_size(); i++)
|
||||
CV_Assert(layer_id.find(node_proto.input(i)) == layer_id.end());
|
||||
@ -2065,8 +2252,10 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
}
|
||||
}
|
||||
replaceLayerParam(layerParams, "mode", "interpolation");
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "Upsample")
|
||||
|
||||
void ONNXImporter::parseUpsample(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
//fused from Resize Subgraph
|
||||
if (layerParams.has("coordinate_transformation_mode"))
|
||||
@ -2112,14 +2301,20 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
}
|
||||
}
|
||||
replaceLayerParam(layerParams, "mode", "interpolation");
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "SoftMax" || layer_type == "LogSoftmax")
|
||||
|
||||
void ONNXImporter::parseSoftMax(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
const std::string& layer_type = node_proto.op_type();
|
||||
layerParams.type = "Softmax";
|
||||
layerParams.set("log_softmax", layer_type == "LogSoftmax");
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else if (layer_type == "DetectionOutput")
|
||||
|
||||
void ONNXImporter::parseDetectionOutput(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
||||
{
|
||||
opencv_onnx::NodeProto node_proto = node_proto_;
|
||||
CV_CheckEQ(node_proto.input_size(), 3, "");
|
||||
if (constBlobs.find(node_proto.input(2)) != constBlobs.end())
|
||||
{
|
||||
@ -2136,62 +2331,68 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
|
||||
node_proto.set_input(2, constParams.name);
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
else
|
||||
|
||||
void ONNXImporter::parseCustom(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
for (int j = 0; j < node_proto.input_size(); j++) {
|
||||
if (layer_id.find(node_proto.input(j)) == layer_id.end())
|
||||
layerParams.blobs.push_back(getBlob(node_proto, j));
|
||||
}
|
||||
}
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
|
||||
const ONNXImporter::DispatchMap ONNXImporter::buildDispatchMap()
|
||||
{
|
||||
if (DNN_DIAGNOSTICS_RUN)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "DNN/ONNX: Potential problem during processing node with " << node_proto.input_size() << " inputs and " << node_proto.output_size() << " outputs: "
|
||||
<< cv::format("[%s]:(%s)", layer_type.c_str(), name.c_str()) << "\n" << e.msg
|
||||
);
|
||||
auto registeredLayers = getLayerFactoryImpl();
|
||||
if (registeredLayers.find(layerParams.type) != registeredLayers.end())
|
||||
{
|
||||
try
|
||||
{
|
||||
Ptr<Layer> layer = LayerFactory::createLayerInstance(layerParams.type, layerParams);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "DNN/ONNX: Layer of type " << layerParams.type << "(" << layer_type << ") cannot be created with parameters " << layerParams << ". Error: " << e.what()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "DNN/ONNX: ERROR during processing node with " << node_proto.input_size() << " inputs and " << node_proto.output_size() << " outputs: "
|
||||
<< cv::format("[%s]:(%s)", layer_type.c_str(), name.c_str())
|
||||
);
|
||||
}
|
||||
for (int i = 0; i < node_proto.input_size(); i++)
|
||||
{
|
||||
CV_LOG_INFO(NULL, " Input[" << i << "] = '" << node_proto.input(i) << "'");
|
||||
}
|
||||
for (int i = 0; i < node_proto.output_size(); i++)
|
||||
{
|
||||
CV_LOG_INFO(NULL, " Output[" << i << "] = '" << node_proto.output(i) << "'");
|
||||
}
|
||||
if (DNN_DIAGNOSTICS_RUN)
|
||||
{
|
||||
for (int i = 0; i < node_proto.output_size(); ++i)
|
||||
{
|
||||
layer_id.insert(std::make_pair(node_proto.output(i), LayerInfo(0, i)));
|
||||
outShapes[node_proto.output(i)] = outShapes[node_proto.input(0)];
|
||||
}
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsError, cv::format("Node [%s]:(%s) parse error: %s", layer_type.c_str(), name.c_str(), e.what()));
|
||||
}
|
||||
DispatchMap dispatch;
|
||||
|
||||
dispatch["MaxPool"] = &ONNXImporter::parseMaxPool;
|
||||
dispatch["AveragePool"] = &ONNXImporter::parseAveragePool;
|
||||
dispatch["GlobalAveragePool"] = dispatch["GlobalMaxPool"] = dispatch["ReduceMean"] = dispatch["ReduceSum"] =
|
||||
dispatch["ReduceMax"] = &ONNXImporter::parseReduce;
|
||||
dispatch["Slice"] = &ONNXImporter::parseSlice;
|
||||
dispatch["Split"] = &ONNXImporter::parseSplit;
|
||||
dispatch["Add"] = dispatch["Sum"] = dispatch["Sub"] = &ONNXImporter::parseBias;
|
||||
dispatch["Pow"] = &ONNXImporter::parsePow;
|
||||
dispatch["Max"] = &ONNXImporter::parseMax;
|
||||
dispatch["Neg"] = &ONNXImporter::parseNeg;
|
||||
dispatch["Constant"] = &ONNXImporter::parseConstant;
|
||||
dispatch["LSTM"] = &ONNXImporter::parseLSTM;
|
||||
dispatch["ImageScaler"] = &ONNXImporter::parseImageScaler;
|
||||
dispatch["Clip"] = &ONNXImporter::parseClip;
|
||||
dispatch["LeakyRelu"] = &ONNXImporter::parseLeakyRelu;
|
||||
dispatch["Relu"] = &ONNXImporter::parseRelu;
|
||||
dispatch["Elu"] = &ONNXImporter::parseElu;
|
||||
dispatch["Tanh"] = &ONNXImporter::parseTanh;
|
||||
dispatch["PRelu"] = &ONNXImporter::parsePRelu;
|
||||
dispatch["LRN"] = &ONNXImporter::parseLRN;
|
||||
dispatch["InstanceNormalization"] = &ONNXImporter::parseInstanceNormalization;
|
||||
dispatch["BatchNormalization"] = &ONNXImporter::parseBatchNormalization;
|
||||
dispatch["Gemm"] = &ONNXImporter::parseGemm;
|
||||
dispatch["MatMul"] = &ONNXImporter::parseMatMul;
|
||||
dispatch["Mul"] = dispatch["Div"] = &ONNXImporter::parseMul;
|
||||
dispatch["Conv"] = &ONNXImporter::parseConv;
|
||||
dispatch["ConvTranspose"] = &ONNXImporter::parseConvTranspose;
|
||||
dispatch["Transpose"] = &ONNXImporter::parseTranspose;
|
||||
dispatch["Squeeze"] = &ONNXImporter::parseSqueeze;
|
||||
dispatch["Flatten"] = &ONNXImporter::parseFlatten;
|
||||
dispatch["Unsqueeze"] = &ONNXImporter::parseUnsqueeze;
|
||||
dispatch["Expand"] = &ONNXImporter::parseExpand;
|
||||
dispatch["Reshape"] = &ONNXImporter::parseReshape;
|
||||
dispatch["Pad"] = &ONNXImporter::parsePad;
|
||||
dispatch["Shape"] = &ONNXImporter::parseShape;
|
||||
dispatch["Cast"] = &ONNXImporter::parseCast;
|
||||
dispatch["ConstantFill"] = dispatch["ConstantOfShape"] = &ONNXImporter::parseConstantFill;
|
||||
dispatch["Gather"] = &ONNXImporter::parseGather;
|
||||
dispatch["Concat"] = &ONNXImporter::parseConcat;
|
||||
dispatch["Resize"] = &ONNXImporter::parseResize;
|
||||
dispatch["Upsample"] = &ONNXImporter::parseUpsample;
|
||||
dispatch["SoftMax"] = dispatch["LogSoftmax"] = &ONNXImporter::parseSoftMax;
|
||||
dispatch["DetectionOutput"] = &ONNXImporter::parseDetectionOutput;
|
||||
dispatch["Custom"] = &ONNXImporter::parseCustom;
|
||||
|
||||
return dispatch;
|
||||
}
|
||||
|
||||
Net readNetFromONNX(const String& onnxFile)
|
||||
|
@ -2894,7 +2894,7 @@ void TFImporter::parseNode(const tensorflow::NodeDef& layer)
|
||||
DispatchMap::const_iterator iter = dispatch.find(type);
|
||||
if (iter != dispatch.end())
|
||||
{
|
||||
((*this).*(iter->second))(net, layer, layerParams);
|
||||
CALL_MEMBER_FN(*this, iter->second)(net, layer, layerParams);
|
||||
}
|
||||
else if (!DNN_DIAGNOSTICS_RUN || !layerHandler->handleMissing(layer))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user