mirror of
https://github.com/opencv/opencv.git
synced 2025-07-31 01:47:12 +08:00
Merge pull request #25492 from alexlyulkov:al/range-fixed-5.x
Fixed ONNX Range layer to support any input type #25492 Fixed ONNX Range layer to support any input type Extra PR: https://github.com/opencv/opencv_extra/pull/1173 Fixes #25363 ### 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:
parent
bbe86e6dea
commit
72ad06bcf3
@ -2997,6 +2997,34 @@ void ONNXImporter::parseDepthToSpace(LayerParams& layerParams, const opencv_onnx
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Mat runRangeLayer(const Mat& startMat, const Mat& limitMat, const Mat& deltaMat)
|
||||
{
|
||||
T start = startMat.at<T>(0);
|
||||
T limit = limitMat.at<T>(0);
|
||||
T delta = deltaMat.at<T>(0);
|
||||
|
||||
int numberOfElements;
|
||||
if (startMat.depth() == CV_32S || startMat.depth() == CV_64S) {
|
||||
if (delta > 0)
|
||||
numberOfElements = (limit - start + delta - 1) / delta;
|
||||
else
|
||||
numberOfElements = (start - limit - delta - 1) / -delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
numberOfElements = std::ceil((limit - start) / delta);
|
||||
}
|
||||
numberOfElements = std::max(numberOfElements, 0);
|
||||
|
||||
Mat r(std::vector<int>{numberOfElements}, startMat.type());
|
||||
for (int i = 0; i < numberOfElements; i++)
|
||||
{
|
||||
r.at<T>(i) = start + (i * delta);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// Currently we only support range with all constant inputs
|
||||
void ONNXImporter::parseRange(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
@ -3011,25 +3039,27 @@ void ONNXImporter::parseRange(LayerParams& layerParams, const opencv_onnx::NodeP
|
||||
// only supports the case which all inputs are constant
|
||||
CV_Assert(const_id.size() == 3);
|
||||
|
||||
Mat startMat = getIntBlob(node_proto, 0);
|
||||
CV_Assert(startMat.type() == CV_32SC1);
|
||||
int start = startMat.at<int>(0);
|
||||
Mat startMat = getBlob(node_proto, 0);
|
||||
Mat limitMat = getBlob(node_proto, 1);
|
||||
Mat deltaMat = getBlob(node_proto, 2);
|
||||
|
||||
Mat limitMat = getIntBlob(node_proto, 1);
|
||||
CV_Assert(limitMat.type() == CV_32SC1);
|
||||
int limit = limitMat.at<int>(0);
|
||||
|
||||
Mat deltaMat = getIntBlob(node_proto, 2);
|
||||
CV_Assert(deltaMat.type() == CV_32SC1);
|
||||
int delta = deltaMat.at<int>(0);
|
||||
|
||||
int number_of_elements = std::max(int(std::ceil((limit - start) / delta)), 0);
|
||||
Mat r(number_of_elements, 1, CV_32SC1);
|
||||
for (int i = 0; i < number_of_elements; i++)
|
||||
Mat result;
|
||||
switch (startMat.depth())
|
||||
{
|
||||
r.at<int>(i) = start + (i * delta);
|
||||
}
|
||||
addConstant(node_proto.output(0), r);
|
||||
case CV_32F:
|
||||
result = runRangeLayer<float>(startMat, limitMat, deltaMat);
|
||||
break;
|
||||
case CV_32S:
|
||||
result = runRangeLayer<int32_t>(startMat, limitMat, deltaMat);
|
||||
break;
|
||||
case CV_64S:
|
||||
result = runRangeLayer<int64_t>(startMat, limitMat, deltaMat);
|
||||
break;
|
||||
default:
|
||||
CV_Error(cv::Error::BadDepth, "Unsupported type.");
|
||||
};
|
||||
|
||||
addConstant(node_proto.output(0), result);
|
||||
constBlobsExtraInfo.insert(std::make_pair(node_proto.output(0), TensorInfo(1)));
|
||||
}
|
||||
|
||||
|
@ -807,14 +807,26 @@ TEST_P(Test_ONNX_layers, CumSumExclusiveInplace)
|
||||
testONNXModels("cumsum_exclusive_inplace");
|
||||
}
|
||||
|
||||
// Issue: https://github.com/opencv/opencv/issues/25363
|
||||
// The issue was addressed in 4.x, but the solution does not fit 5.x design
|
||||
TEST_P(Test_ONNX_layers, DISABLED_Range)
|
||||
TEST_P(Test_ONNX_layers, RangeFloat)
|
||||
{
|
||||
testONNXModels("range_float");
|
||||
testONNXModels("range_float_negative");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, RangeInt32)
|
||||
{
|
||||
testONNXModels("range_int32");
|
||||
testONNXModels("range_int32_negative");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, RangeInt64)
|
||||
{
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // OpenVINO uses int32 precision for int64 operations
|
||||
testONNXModels("range_int64");
|
||||
testONNXModels("range_int64_negative");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, Eltwise3D)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
|
||||
|
Loading…
Reference in New Issue
Block a user