mirror of
https://github.com/opencv/opencv.git
synced 2026-09-12 05:11:04 -05:00
Merge pull request #29621 from YangGuanyuhan/christylinux/fix-onnx-gather-cast
dnn: (bug fix )preserve Cast semantics after ONNX Gather
This commit is contained in:
@@ -1402,74 +1402,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class GatherCastSubgraph : public Subgraph
|
||||
{
|
||||
public:
|
||||
GatherCastSubgraph()
|
||||
{
|
||||
int input = addNodeToMatch("");
|
||||
int index = addNodeToMatch("Constant");
|
||||
gather = addNodeToMatch("Gather", input, index);
|
||||
cast = addNodeToMatch("Cast", gather);
|
||||
setFusedNode("Gather", input, index);
|
||||
}
|
||||
|
||||
virtual bool match(const Ptr<ImportGraphWrapper>& net, int nodeId,
|
||||
std::vector<int>& matchedNodesIds) CV_OVERRIDE
|
||||
{
|
||||
bool retVal = Subgraph::match(net, nodeId, matchedNodesIds);
|
||||
size_t matchedNodesNum = matchedNodesIds.size();
|
||||
// Now we check if merging can be made for these Gather and Cast nodes
|
||||
if (!retVal || matchedNodesNum < 2)
|
||||
return retVal;
|
||||
else {
|
||||
int nodeToMatch = matchedNodesIds[cast];
|
||||
const Ptr<ImportNodeWrapper> node = net->getNode(nodeToMatch);
|
||||
if (node->getType() == "Cast") {
|
||||
int inpNodeId = matchedNodesIds[gather];
|
||||
const Ptr<ImportNodeWrapper> inpNode = net->getNode(inpNodeId);
|
||||
if (inpNode->getType() == "Gather") {
|
||||
int numNodes = net->getNumNodes();
|
||||
std::string inpNodeName = node->getInputName(0);
|
||||
for (int i = 0; i < numNodes; ++i) {
|
||||
const Ptr<ImportNodeWrapper> node_to_check = net->getNode(i);
|
||||
int numInp = node_to_check->getNumInputs();
|
||||
for (int inp = 0; inp < numInp; ++inp) {
|
||||
if (i != nodeToMatch && inpNodeName == node_to_check->getInputName(inp)) {
|
||||
// Another node has the same input node, so it cannot be merged.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// extract axis from original Gather node
|
||||
axis = 0;
|
||||
opencv_onnx::NodeProto* origGatherNode =
|
||||
inpNode.dynamicCast<ONNXNodeWrapper>()->node;
|
||||
for (int i = 0; i < origGatherNode->attribute_size(); i++) {
|
||||
opencv_onnx::AttributeProto attr = origGatherNode->attribute(i);
|
||||
if (attr.name() == "axis")
|
||||
axis = attr.i();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
virtual void finalize(const Ptr<ImportGraphWrapper>& net,
|
||||
const Ptr<ImportNodeWrapper>& fusedNode,
|
||||
std::vector<Ptr<ImportNodeWrapper> >& /*inputs*/) CV_OVERRIDE
|
||||
{
|
||||
opencv_onnx::NodeProto* node = fusedNode.dynamicCast<ONNXNodeWrapper>()->node;
|
||||
opencv_onnx::AttributeProto* new_attr = node->add_attribute();
|
||||
new_attr->set_name("axis");
|
||||
new_attr->set_i(axis);
|
||||
}
|
||||
|
||||
private:
|
||||
int cast, gather, axis;
|
||||
};
|
||||
|
||||
/* Constant folding shape for Expand.
|
||||
|
||||
Before fusion:
|
||||
@@ -1629,19 +1561,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class MulCastSubgraph : public Subgraph
|
||||
{
|
||||
public:
|
||||
MulCastSubgraph()
|
||||
{
|
||||
int input = addNodeToMatch("");
|
||||
int scaleNode = addNodeToMatch("Constant");
|
||||
int mul = addNodeToMatch("Mul", input, scaleNode);
|
||||
addNodeToMatch("Cast", mul);
|
||||
setFusedNode("Mul", input, scaleNode);
|
||||
}
|
||||
};
|
||||
|
||||
class ExtractScalesSubgraph : public Subgraph
|
||||
{
|
||||
public:
|
||||
@@ -1922,8 +1841,6 @@ void simplifySubgraphs(opencv_onnx::GraphProto& net, const std::string& basePath
|
||||
subgraphs.push_back(makePtr<GeluSubGraph>());
|
||||
subgraphs.push_back(makePtr<GeluApproximationSubGraph>());
|
||||
subgraphs.push_back(makePtr<LayerNormSubGraph>());
|
||||
subgraphs.push_back(makePtr<GatherCastSubgraph>());
|
||||
subgraphs.push_back(makePtr<MulCastSubgraph>());
|
||||
subgraphs.push_back(makePtr<UpsampleSubgraph>());
|
||||
subgraphs.push_back(makePtr<ResizeSubgraph1>());
|
||||
subgraphs.push_back(makePtr<ResizeSubgraph2>());
|
||||
|
||||
@@ -2347,6 +2347,47 @@ TEST(Layer_Size, onnx_0d_scalar)
|
||||
EXPECT_EQ(outs[0].at<int64_t>(0), 1);
|
||||
}
|
||||
|
||||
TEST(Layer_GatherCast, preserves_float_cast)
|
||||
{
|
||||
const std::string modelname = findDataFile("dnn/onnx/models/gather_cast_float.onnx", true);
|
||||
Net net = readNetFromONNX(modelname, ENGINE_OPENCV);
|
||||
ASSERT_FALSE(net.empty());
|
||||
ASSERT_TRUE(net.getMainGraph());
|
||||
|
||||
int inputShape[] = {2, 3};
|
||||
Mat input(2, inputShape, CV_32F, Scalar(0));
|
||||
net.setInput(input, "input");
|
||||
|
||||
std::vector<Mat> outputs;
|
||||
net.forward(outputs, std::vector<String>{"output"});
|
||||
|
||||
ASSERT_EQ(outputs.size(), 1u);
|
||||
EXPECT_EQ(outputs[0].total(), (size_t)1);
|
||||
EXPECT_EQ(outputs[0].type(), CV_32F);
|
||||
EXPECT_FLOAT_EQ(outputs[0].ptr<float>()[0], 2.f);
|
||||
}
|
||||
|
||||
TEST(Layer_MulCast, preserves_float_cast)
|
||||
{
|
||||
const std::string modelname = findDataFile("dnn/onnx/models/mul_cast_float.onnx", true);
|
||||
Net net = readNetFromONNX(modelname, ENGINE_OPENCV);
|
||||
ASSERT_FALSE(net.empty());
|
||||
ASSERT_TRUE(net.getMainGraph());
|
||||
|
||||
int inputShape[] = {2, 3};
|
||||
Mat input(2, inputShape, CV_32F, Scalar(0));
|
||||
net.setInput(input, "input");
|
||||
|
||||
std::vector<Mat> outputs;
|
||||
net.forward(outputs, std::vector<String>{"output"});
|
||||
|
||||
ASSERT_EQ(outputs.size(), 1u);
|
||||
EXPECT_EQ(outputs[0].total(), (size_t)2);
|
||||
EXPECT_EQ(outputs[0].type(), CV_32F);
|
||||
EXPECT_FLOAT_EQ(outputs[0].ptr<float>()[0], 2.f);
|
||||
EXPECT_FLOAT_EQ(outputs[0].ptr<float>()[1], 2.f);
|
||||
}
|
||||
|
||||
TEST(ConvolutionWinograd, Accuracy)
|
||||
{
|
||||
Mat weights({2, 1, 3, 3}, CV_32F);
|
||||
|
||||
Reference in New Issue
Block a user