mirror of
https://github.com/opencv/opencv.git
synced 2025-06-13 04:52:53 +08:00
Merge pull request #20605 from rogday:split_slice_shenanigans
Add Normalize subgraph, fix Slice, Mul and Expand * Add Normalize subgraph, support for starts<0 and axis<0 in Slice, Mul broadcasting in the middle and fix Expand's unsqueeze * remove todos * remove range-based for loop * address review comments * change >> to > > in template * fix indexation * fix expand that does nothing
This commit is contained in:
parent
1e0d290f2e
commit
4807cd8a6e
@ -58,6 +58,31 @@ namespace cv
|
|||||||
namespace dnn
|
namespace dnn
|
||||||
{
|
{
|
||||||
|
|
||||||
|
void sliceRangesFromShape(const MatShape& inpShape, int& axis, std::vector<std::vector<cv::Range> >& sliceRanges)
|
||||||
|
{
|
||||||
|
CV_Assert(inpShape.size() > 0);
|
||||||
|
bool axisNeg = (axis < 0);
|
||||||
|
axis = (axis + static_cast<int>(inpShape.size())) % inpShape.size();
|
||||||
|
int n = inpShape[axis];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sliceRanges.size(); ++i){
|
||||||
|
std::vector<Range>& ranges = sliceRanges[i];
|
||||||
|
if (axisNeg)
|
||||||
|
{
|
||||||
|
ranges.insert(ranges.begin(), axis, Range::all());
|
||||||
|
}
|
||||||
|
Range& range = ranges.back();
|
||||||
|
|
||||||
|
if (range.start >= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_Assert(n != 0);
|
||||||
|
range.start = (n + range.start) % n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SliceLayerImpl : public SliceLayer
|
class SliceLayerImpl : public SliceLayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -69,20 +94,22 @@ public:
|
|||||||
num_split = params.get<int>("num_split", 0);
|
num_split = params.get<int>("num_split", 0);
|
||||||
hasDynamicShapes = params.get<bool>("has_dynamic_shapes", false);
|
hasDynamicShapes = params.get<bool>("has_dynamic_shapes", false);
|
||||||
shapesInitialized = !hasDynamicShapes;
|
shapesInitialized = !hasDynamicShapes;
|
||||||
|
|
||||||
if (params.has("slice_point"))
|
if (params.has("slice_point"))
|
||||||
{
|
{
|
||||||
CV_Assert(!params.has("begin") && !params.has("size") && !params.has("end"));
|
CV_Assert(!params.has("begin") && !params.has("size") && !params.has("end"));
|
||||||
const DictValue &indicesValue = params.get("slice_point");
|
const DictValue &indicesValue = params.get("slice_point");
|
||||||
|
int size = axis > 0 ? axis + 1 : 1;
|
||||||
sliceRanges.resize(indicesValue.size() + 1,
|
sliceRanges.resize(indicesValue.size() + 1,
|
||||||
std::vector<Range>(axis + 1, Range::all()));
|
std::vector<Range>(size, Range::all()));
|
||||||
int prevSlice = 0;
|
int prevSlice = 0;
|
||||||
for (int i = 0; i < indicesValue.size(); ++i)
|
for (int i = 0; i < indicesValue.size(); ++i)
|
||||||
{
|
{
|
||||||
sliceRanges[i][axis].start = prevSlice;
|
sliceRanges[i][size - 1].start = prevSlice;
|
||||||
sliceRanges[i][axis].end = indicesValue.get<int>(i);
|
sliceRanges[i][size - 1].end = indicesValue.get<int>(i);
|
||||||
prevSlice = sliceRanges[i][axis].end;
|
prevSlice = sliceRanges[i][size - 1].end;
|
||||||
}
|
}
|
||||||
sliceRanges.back()[axis].start = prevSlice;
|
sliceRanges.back()[size - 1].start = prevSlice;
|
||||||
}
|
}
|
||||||
else if (params.has("begin"))
|
else if (params.has("begin"))
|
||||||
{
|
{
|
||||||
@ -97,7 +124,6 @@ public:
|
|||||||
{
|
{
|
||||||
int start = begins.get<int>(i);
|
int start = begins.get<int>(i);
|
||||||
int sizeOrEnd = sizesOrEnds.get<int>(i); // It may be negative to reverse indexation.
|
int sizeOrEnd = sizesOrEnds.get<int>(i); // It may be negative to reverse indexation.
|
||||||
CV_Assert(start >= 0);
|
|
||||||
|
|
||||||
sliceRanges[0][i].start = start;
|
sliceRanges[0][i].start = start;
|
||||||
if (params.has("size"))
|
if (params.has("size"))
|
||||||
@ -154,16 +180,20 @@ public:
|
|||||||
CV_Assert(inputs.size() == 1);
|
CV_Assert(inputs.size() == 1);
|
||||||
MatShape inpShape = inputs[0];
|
MatShape inpShape = inputs[0];
|
||||||
|
|
||||||
if (!sliceRanges.empty())
|
int axis_rw = axis;
|
||||||
|
std::vector<std::vector<cv::Range> > sliceRanges_rw = sliceRanges;
|
||||||
|
sliceRangesFromShape(inpShape, axis_rw, sliceRanges_rw);
|
||||||
|
|
||||||
|
if (!sliceRanges_rw.empty())
|
||||||
{
|
{
|
||||||
outputs.resize(sliceRanges.size(), inpShape);
|
outputs.resize(sliceRanges_rw.size(), inpShape);
|
||||||
for (int i = 0; i < outputs.size(); ++i)
|
for (int i = 0; i < outputs.size(); ++i)
|
||||||
{
|
{
|
||||||
CV_Assert(sliceRanges[i].size() <= inpShape.size());
|
CV_Assert(sliceRanges_rw[i].size() <= inpShape.size());
|
||||||
for (int j = 0; j < sliceRanges[i].size(); ++j)
|
for (int j = 0; j < sliceRanges_rw[i].size(); ++j)
|
||||||
{
|
{
|
||||||
if (shapesInitialized || inpShape[j] > 0)
|
if (shapesInitialized || inpShape[j] > 0)
|
||||||
outputs[i][j] = normalize_axis_range(sliceRanges[i][j], inpShape[j]).size();
|
outputs[i][j] = normalize_axis_range(sliceRanges_rw[i][j], inpShape[j]).size();
|
||||||
|
|
||||||
if (!sliceSteps.empty() && (i < sliceSteps.size()) && (j < sliceSteps[i].size()) && (sliceSteps[i][j] > 1))
|
if (!sliceSteps.empty() && (i < sliceSteps.size()) && (j < sliceSteps[i].size()) && (sliceSteps[i][j] > 1))
|
||||||
outputs[i][j] = (outputs[i][j] + sliceSteps[i][j] - 1) / sliceSteps[i][j];
|
outputs[i][j] = (outputs[i][j] + sliceSteps[i][j] - 1) / sliceSteps[i][j];
|
||||||
@ -172,10 +202,10 @@ public:
|
|||||||
}
|
}
|
||||||
else // Divide input blob on equal parts by axis.
|
else // Divide input blob on equal parts by axis.
|
||||||
{
|
{
|
||||||
CV_Assert(0 <= axis && axis < inpShape.size());
|
CV_Assert(0 <= axis_rw && axis_rw < inpShape.size());
|
||||||
int splits = num_split ? num_split : requiredOutputs;
|
int splits = num_split ? num_split : requiredOutputs;
|
||||||
CV_Assert(splits > 0 && inpShape[axis] % splits == 0);
|
CV_Assert(splits > 0 && inpShape[axis_rw] % splits == 0);
|
||||||
inpShape[axis] /= splits;
|
inpShape[axis_rw] /= splits;
|
||||||
outputs.resize(splits, inpShape);
|
outputs.resize(splits, inpShape);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -200,6 +230,7 @@ public:
|
|||||||
CV_Assert(inputs.size() == 1);
|
CV_Assert(inputs.size() == 1);
|
||||||
const MatSize& inpShape = inputs[0].size;
|
const MatSize& inpShape = inputs[0].size;
|
||||||
|
|
||||||
|
sliceRangesFromShape(shape(inputs[0]), axis, sliceRanges);
|
||||||
finalSliceRanges = sliceRanges;
|
finalSliceRanges = sliceRanges;
|
||||||
|
|
||||||
if (sliceRanges.empty())
|
if (sliceRanges.empty())
|
||||||
|
@ -231,6 +231,27 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NormalizeSubgraph2_2 : public NormalizeSubgraphBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NormalizeSubgraph2_2()
|
||||||
|
{
|
||||||
|
int input = addNodeToMatch("");
|
||||||
|
int norm = addNodeToMatch("ReduceL2", input);
|
||||||
|
|
||||||
|
int min = addNodeToMatch("");
|
||||||
|
int max = addNodeToMatch("");
|
||||||
|
int clip = addNodeToMatch("Clip", norm, min, max);
|
||||||
|
|
||||||
|
int shape = addNodeToMatch("");
|
||||||
|
int expand = addNodeToMatch("Expand", clip, shape);
|
||||||
|
|
||||||
|
addNodeToMatch("Div", input, expand);
|
||||||
|
|
||||||
|
setFusedNode("Normalize", input);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class NormalizeSubgraph3 : public NormalizeSubgraphBase
|
class NormalizeSubgraph3 : public NormalizeSubgraphBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -555,6 +576,7 @@ void simplifySubgraphs(opencv_onnx::GraphProto& net)
|
|||||||
subgraphs.push_back(makePtr<SoftMaxSubgraph>());
|
subgraphs.push_back(makePtr<SoftMaxSubgraph>());
|
||||||
subgraphs.push_back(makePtr<NormalizeSubgraph1>());
|
subgraphs.push_back(makePtr<NormalizeSubgraph1>());
|
||||||
subgraphs.push_back(makePtr<NormalizeSubgraph2>());
|
subgraphs.push_back(makePtr<NormalizeSubgraph2>());
|
||||||
|
subgraphs.push_back(makePtr<NormalizeSubgraph2_2>());
|
||||||
subgraphs.push_back(makePtr<NormalizeSubgraph3>());
|
subgraphs.push_back(makePtr<NormalizeSubgraph3>());
|
||||||
subgraphs.push_back(makePtr<BatchNormalizationSubgraph1>());
|
subgraphs.push_back(makePtr<BatchNormalizationSubgraph1>());
|
||||||
subgraphs.push_back(makePtr<BatchNormalizationSubgraph2>());
|
subgraphs.push_back(makePtr<BatchNormalizationSubgraph2>());
|
||||||
|
@ -59,6 +59,8 @@ class ONNXImporter
|
|||||||
void addLayer(LayerParams& layerParams,
|
void addLayer(LayerParams& layerParams,
|
||||||
const opencv_onnx::NodeProto& node_proto);
|
const opencv_onnx::NodeProto& node_proto);
|
||||||
|
|
||||||
|
void expandMid(const std::string& prefix, opencv_onnx::NodeProto& node_proto,
|
||||||
|
const std::string& input, size_t n);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ONNXImporter(Net& net, const char *onnxFile)
|
ONNXImporter(Net& net, const char *onnxFile)
|
||||||
@ -427,6 +429,37 @@ void ONNXImporter::addLayer(LayerParams& layerParams,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Make N copies of input layer and set them as input to node_proto.
|
||||||
|
* @param prefix prefix of new layers' names
|
||||||
|
* @param node_proto node which will contain all copies as inputs
|
||||||
|
* @param input name of the node to copy
|
||||||
|
* @param n number of copies
|
||||||
|
*/
|
||||||
|
void ONNXImporter::expandMid(const std::string& prefix, opencv_onnx::NodeProto& node_proto,
|
||||||
|
const std::string& input, size_t n)
|
||||||
|
{
|
||||||
|
std::vector<std::string> input_names;
|
||||||
|
input_names.reserve(n);
|
||||||
|
for (size_t j = 0; j < n; j++)
|
||||||
|
{
|
||||||
|
LayerParams copyLP;
|
||||||
|
copyLP.name = format("%s/copy_%d", prefix.c_str(), j);
|
||||||
|
copyLP.type = "Identity";
|
||||||
|
CV_Assert((layer_id.find(copyLP.name) == layer_id.end()) &&
|
||||||
|
"Couldn't copy the node: generated name already exists in the graph.");
|
||||||
|
input_names.push_back(copyLP.name);
|
||||||
|
|
||||||
|
node_proto.set_input(0, input);
|
||||||
|
node_proto.set_output(0, copyLP.name);
|
||||||
|
addLayer(copyLP, node_proto);
|
||||||
|
}
|
||||||
|
node_proto.clear_input();
|
||||||
|
for (size_t i = 0; i < input_names.size(); i++)
|
||||||
|
{
|
||||||
|
node_proto.add_input(input_names[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ONNXImporter::addConstant(const std::string& name, const Mat& blob)
|
void ONNXImporter::addConstant(const std::string& name, const Mat& blob)
|
||||||
{
|
{
|
||||||
constBlobs.insert(std::make_pair(name, blob));
|
constBlobs.insert(std::make_pair(name, blob));
|
||||||
@ -1288,6 +1321,37 @@ void ONNXImporter::parseMatMul(LayerParams& layerParams, const opencv_onnx::Node
|
|||||||
addLayer(layerParams, node_proto);
|
addLayer(layerParams, node_proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void findBroadAxis(const MatShape& broadShape, const MatShape& outShape, size_t& axis, int& broadAxis)
|
||||||
|
{
|
||||||
|
const size_t diff = outShape.size() - broadShape.size();
|
||||||
|
|
||||||
|
// find the first non-one element of the broadcasting shape
|
||||||
|
axis = 0;
|
||||||
|
for (; axis < broadShape.size() && broadShape[axis] == 1; ++axis) {}
|
||||||
|
|
||||||
|
// find the last non-one element of the broadcasting shape
|
||||||
|
size_t endAxis = broadShape.size();
|
||||||
|
for (; endAxis > axis && broadShape[endAxis - 1] == 1; --endAxis) {}
|
||||||
|
|
||||||
|
// find one between axis and endAxis - as it needs to be broadcasted,
|
||||||
|
// dimensions from the left of axis and from the right of endAxis will be handled by Scale layer
|
||||||
|
broadAxis = -1;
|
||||||
|
for (size_t i = axis; i < endAxis; ++i)
|
||||||
|
{
|
||||||
|
size_t outAxis = i + diff;
|
||||||
|
if (outShape[outAxis] == broadShape[i])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure we need to broadcast only 1 dimension in the middle
|
||||||
|
CV_Assert(broadShape[i] == 1 && broadAxis == -1);
|
||||||
|
broadAxis = static_cast<int>(outAxis);
|
||||||
|
}
|
||||||
|
|
||||||
|
axis += diff;
|
||||||
|
}
|
||||||
|
|
||||||
// "Mul" "Div"
|
// "Mul" "Div"
|
||||||
void ONNXImporter::parseMul(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
void ONNXImporter::parseMul(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
|
||||||
{
|
{
|
||||||
@ -1410,13 +1474,31 @@ void ONNXImporter::parseMul(LayerParams& layerParams, const opencv_onnx::NodePro
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MatShape& broadShape = outShapes[node_proto.input(1)];
|
const MatShape& broadShape = outShapes[node_proto.input(1)];
|
||||||
const size_t outShapeSize = outShapes[node_proto.input(0)].size();
|
const MatShape& outShape = outShapes[node_proto.input(0)];
|
||||||
const size_t diff = outShapeSize - broadShape.size();
|
|
||||||
|
|
||||||
size_t axis;
|
size_t axis = 0;
|
||||||
for (axis = diff; axis < broadShape.size() && broadShape[axis - diff] == 1; ++axis) {}
|
int broadAxis = -1;
|
||||||
|
findBroadAxis(broadShape, outShape, axis, broadAxis);
|
||||||
|
|
||||||
CV_Assert(axis != outShapeSize);
|
// if there is a one dimension in the middle that should be broadcasted, broadcast it
|
||||||
|
if (broadAxis != -1)
|
||||||
|
{
|
||||||
|
opencv_onnx::NodeProto concat_node_proto = node_proto;
|
||||||
|
const std::string& input1 = concat_node_proto.input(1);
|
||||||
|
|
||||||
|
expandMid(layerParams.name, concat_node_proto, input1, outShape[broadAxis]);
|
||||||
|
|
||||||
|
LayerParams concatLP;
|
||||||
|
concatLP.name = layerParams.name + "/concat";
|
||||||
|
concatLP.set("axis", broadAxis);
|
||||||
|
concatLP.type = "Concat";
|
||||||
|
concat_node_proto.set_output(0, concatLP.name);
|
||||||
|
|
||||||
|
addLayer(concatLP, concat_node_proto);
|
||||||
|
node_proto.set_input(1, concatLP.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_Assert(axis != outShape.size());
|
||||||
layerParams.set("axis", static_cast<int>(axis));
|
layerParams.set("axis", static_cast<int>(axis));
|
||||||
layerParams.type = "Scale";
|
layerParams.type = "Scale";
|
||||||
}
|
}
|
||||||
@ -1685,12 +1767,11 @@ void ONNXImporter::parseExpand(LayerParams& layerParams, const opencv_onnx::Node
|
|||||||
// Unsqueeze and repeat along new axis
|
// Unsqueeze and repeat along new axis
|
||||||
if (targetShape.size() == inpShape.size() + 1)
|
if (targetShape.size() == inpShape.size() + 1)
|
||||||
{
|
{
|
||||||
|
inpShape.insert(inpShape.begin(), targetShape.size() - inpShape.size(), 1);
|
||||||
for (int i = 0; i < targetShape.size(); i++)
|
for (int i = 0; i < targetShape.size(); i++)
|
||||||
{
|
{
|
||||||
if (targetShape[i] == -1 && i < inpShape.size())
|
if (abs(targetShape[i]) == 1)
|
||||||
targetShape[i] = inpShape[i];
|
targetShape[i] = inpShape[i];
|
||||||
else if (i < inpShape.size() && targetShape[i] != inpShape[i])
|
|
||||||
inpShape.insert(inpShape.begin() + i, 1);
|
|
||||||
}
|
}
|
||||||
if (haveVariables)
|
if (haveVariables)
|
||||||
{
|
{
|
||||||
@ -1710,14 +1791,19 @@ void ONNXImporter::parseExpand(LayerParams& layerParams, const opencv_onnx::Node
|
|||||||
CV_CheckEQ(inpShape.size(), targetShape.size(), "Unsupported Expand op with different dims");
|
CV_CheckEQ(inpShape.size(), targetShape.size(), "Unsupported Expand op with different dims");
|
||||||
|
|
||||||
std::vector<int> broadcast_axes;
|
std::vector<int> broadcast_axes;
|
||||||
|
// shapes aren't right-aligned here because targetShape.size() == inpShape.size()
|
||||||
for (int i = 0; i < targetShape.size(); i++)
|
for (int i = 0; i < targetShape.size(); i++)
|
||||||
{
|
{
|
||||||
if (targetShape[i] != inpShape[i])
|
if (targetShape[i] != inpShape[i])
|
||||||
{
|
{
|
||||||
if (inpShape[i] == 1)
|
if (inpShape[i] == 1)
|
||||||
|
{
|
||||||
broadcast_axes.push_back(i);
|
broadcast_axes.push_back(i);
|
||||||
else
|
}
|
||||||
|
else if (targetShape[i] != 1)
|
||||||
|
{
|
||||||
CV_Error(Error::StsError, format("Could not be broadcast by axis: %d", i));
|
CV_Error(Error::StsError, format("Could not be broadcast by axis: %d", i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1756,31 +1842,16 @@ void ONNXImporter::parseExpand(LayerParams& layerParams, const opencv_onnx::Node
|
|||||||
}
|
}
|
||||||
else if (broadcast_axes.size() == 1 && broadcast_axes[0] <= 1)
|
else if (broadcast_axes.size() == 1 && broadcast_axes[0] <= 1)
|
||||||
{
|
{
|
||||||
String base_name = layerParams.name + "/copy_";
|
expandMid(layerParams.name, node_proto, srcName, targetShape[broadcast_axes[0]]);
|
||||||
std::vector<std::string> input_names;
|
|
||||||
for (int j = 0; j < targetShape[broadcast_axes[0]]; j++)
|
|
||||||
{
|
|
||||||
std::ostringstream ss;
|
|
||||||
ss << j;
|
|
||||||
LayerParams copyLP;
|
|
||||||
copyLP.name = base_name + ss.str();
|
|
||||||
copyLP.type = "Identity";
|
|
||||||
CV_Assert(layer_id.find(copyLP.name) == layer_id.end());
|
|
||||||
input_names.push_back(copyLP.name);
|
|
||||||
|
|
||||||
node_proto.set_input(0, srcName);
|
|
||||||
node_proto.set_output(0, copyLP.name);
|
|
||||||
addLayer(copyLP, node_proto);
|
|
||||||
}
|
|
||||||
node_proto.clear_input();
|
|
||||||
for (int i = 0; i < input_names.size(); i++)
|
|
||||||
{
|
|
||||||
node_proto.add_input(input_names[i]);
|
|
||||||
}
|
|
||||||
layerParams.set("axis", broadcast_axes[0]);
|
layerParams.set("axis", broadcast_axes[0]);
|
||||||
layerParams.type = "Concat";
|
layerParams.type = "Concat";
|
||||||
node_proto.set_output(0, layerParams.name);
|
node_proto.set_output(0, layerParams.name);
|
||||||
}
|
}
|
||||||
|
else if (broadcast_axes.empty())
|
||||||
|
{
|
||||||
|
layerParams.type = "Identity";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
CV_Error(Error::StsNotImplemented, "Unsupported Expand op");
|
CV_Error(Error::StsNotImplemented, "Unsupported Expand op");
|
||||||
addLayer(layerParams, node_proto);
|
addLayer(layerParams, node_proto);
|
||||||
|
@ -285,6 +285,7 @@ TEST_P(Test_ONNX_layers, Scale)
|
|||||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||||
testONNXModels("scale");
|
testONNXModels("scale");
|
||||||
testONNXModels("scale_broadcast", npy, 0, 0, false, true, 3);
|
testONNXModels("scale_broadcast", npy, 0, 0, false, true, 3);
|
||||||
|
testONNXModels("scale_broadcast_mid", npy, 0, 0, false, true, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(Test_ONNX_layers, ReduceMean3D)
|
TEST_P(Test_ONNX_layers, ReduceMean3D)
|
||||||
@ -471,6 +472,8 @@ TEST_P(Test_ONNX_layers, MatMulAdd)
|
|||||||
|
|
||||||
TEST_P(Test_ONNX_layers, Expand)
|
TEST_P(Test_ONNX_layers, Expand)
|
||||||
{
|
{
|
||||||
|
testONNXModels("expand");
|
||||||
|
testONNXModels("expand_identity");
|
||||||
testONNXModels("expand_batch");
|
testONNXModels("expand_batch");
|
||||||
testONNXModels("expand_channels");
|
testONNXModels("expand_channels");
|
||||||
testONNXModels("expand_neg_batch");
|
testONNXModels("expand_neg_batch");
|
||||||
@ -611,6 +614,7 @@ TEST_P(Test_ONNX_layers, ReduceL2)
|
|||||||
testONNXModels("reduceL2");
|
testONNXModels("reduceL2");
|
||||||
testONNXModels("reduceL2_subgraph");
|
testONNXModels("reduceL2_subgraph");
|
||||||
testONNXModels("reduceL2_subgraph_2");
|
testONNXModels("reduceL2_subgraph_2");
|
||||||
|
testONNXModels("reduceL2_subgraph2_2");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(Test_ONNX_layers, Split)
|
TEST_P(Test_ONNX_layers, Split)
|
||||||
@ -624,6 +628,7 @@ TEST_P(Test_ONNX_layers, Split)
|
|||||||
testONNXModels("split_3");
|
testONNXModels("split_3");
|
||||||
testONNXModels("split_4");
|
testONNXModels("split_4");
|
||||||
testONNXModels("split_sizes");
|
testONNXModels("split_sizes");
|
||||||
|
testONNXModels("split_neg_axis");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(Test_ONNX_layers, Slice)
|
TEST_P(Test_ONNX_layers, Slice)
|
||||||
@ -632,6 +637,7 @@ TEST_P(Test_ONNX_layers, Slice)
|
|||||||
testONNXModels("slice", npy, 0, 0, false, false);
|
testONNXModels("slice", npy, 0, 0, false, false);
|
||||||
#else
|
#else
|
||||||
testONNXModels("slice");
|
testONNXModels("slice");
|
||||||
|
testONNXModels("slice_neg_starts");
|
||||||
testONNXModels("slice_opset_11");
|
testONNXModels("slice_opset_11");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user