From 2c675820203f21b047252fc3c2f8b2ad5dfdc072 Mon Sep 17 00:00:00 2001 From: Abhishek Gola Date: Fri, 3 Jul 2026 17:49:10 +0530 Subject: [PATCH] slope fix --- modules/dnn/include/opencv2/dnn/all_layers.hpp | 2 ++ modules/dnn/src/graph_const_args.cpp | 5 +++++ modules/dnn/src/layers/elementwise_layers.cpp | 15 +++++++++++++++ modules/dnn/src/onnx/onnx_importer2.cpp | 14 +++++++++++--- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/modules/dnn/include/opencv2/dnn/all_layers.hpp b/modules/dnn/include/opencv2/dnn/all_layers.hpp index bce0b862de..686bccda2d 100644 --- a/modules/dnn/include/opencv2/dnn/all_layers.hpp +++ b/modules/dnn/include/opencv2/dnn/all_layers.hpp @@ -1123,6 +1123,8 @@ CV__DNN_INLINE_NS_BEGIN { public: static Ptr create(const LayerParams& params); + // Set the per-channel slope when it arrives as a second input, not a blob. + virtual void setSlope(const Mat& /*slope*/) {} }; class CV_EXPORTS ELULayer : public ActivationLayer diff --git a/modules/dnn/src/graph_const_args.cpp b/modules/dnn/src/graph_const_args.cpp index 7cb449d440..706bd67538 100644 --- a/modules/dnn/src/graph_const_args.cpp +++ b/modules/dnn/src/graph_const_args.cpp @@ -68,6 +68,7 @@ struct ConstArgs Conv2Layer* conv = dynamic_cast(layer_ptr); ConvTranspose2Layer* deconv = dynamic_cast(layer_ptr); BatchNorm2Layer* bn = dynamic_cast(layer_ptr); + ChannelsPReLULayer* prelu = dynamic_cast(layer_ptr); //ActivationLayer* activ = dynamic_cast(layer_ptr); if (tail_const) { @@ -88,6 +89,10 @@ struct ConstArgs } else if (bn && bn->freezeScaleBias()) { // batch norm with constant parameters unuse_tail = true; + } else if (prelu && ninputs == 2) { + prelu->setSlope(netimpl->__tensors__[inputs[1].idx]); + prelu->inputs.resize(1); + unuse_tail = true; }/* else if (activ && dynamic_cast(activ)) { // [TODO] ... unuse_tail = true; diff --git a/modules/dnn/src/layers/elementwise_layers.cpp b/modules/dnn/src/layers/elementwise_layers.cpp index 5405d938d2..269b3fe96a 100644 --- a/modules/dnn/src/layers/elementwise_layers.cpp +++ b/modules/dnn/src/layers/elementwise_layers.cpp @@ -3742,6 +3742,14 @@ class ChannelsPReLUImpl CV_FINAL : public ElementWiseLayer public: using ElementWiseLayer::ElementWiseLayer; + void setSlope(const Mat& slope) CV_OVERRIDE + { + slope.reshape(1, (int)slope.total()).convertTo(func.scale, CV_32F); +#ifdef HAVE_OPENCL + func.scale_umat.release(); +#endif + } + void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE @@ -3849,6 +3857,13 @@ private: Ptr ChannelsPReLULayer::create(const LayerParams& params) { + if (params.blobs.empty()) + { + // Slope comes as a second input; constArgs() fills the scale in later. + Ptr l(new ChannelsPReLUImpl(ChannelsPReLUFunctor())); + l->setParamsFrom(params); + return l; + } CV_Assert(params.blobs.size() == 1); Mat scale = params.blobs[0]; float slope = *scale.ptr(); diff --git a/modules/dnn/src/onnx/onnx_importer2.cpp b/modules/dnn/src/onnx/onnx_importer2.cpp index 1eb9c7b154..961d207538 100644 --- a/modules/dnn/src/onnx/onnx_importer2.cpp +++ b/modules/dnn/src/onnx/onnx_importer2.cpp @@ -1458,9 +1458,17 @@ void ONNXImporter2::parsePRelu(LayerParams& layerParams, const opencv_onnx::Node { layerParams.type = "PReLU"; CV_Assert(node_inputs.size() == 2); - CV_Assert(net.isConstArg(node_inputs[1])); - layerParams.blobs.push_back(net.argTensor(node_inputs[1])); - addLayer(layerParams, node_proto, 1); + if (net.isConstArg(node_inputs[1])) + { + layerParams.blobs.push_back(net.argTensor(node_inputs[1])); + addLayer(layerParams, node_proto, 1); + } + else + { + // Slope produced by a foldable subgraph (e.g. Reshape of an initializer): + // keep it as a second input for constFold()/constArgs() to resolve. + addLayer(layerParams, node_proto); + } } void ONNXImporter2::parseLpNormalization(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)