Skip to content

Fix issue 22015, let Clip layer support 1-3 inputs#22100

Merged
alalek merged 8 commits intoopencv:4.xfrom
WanliZhong:issue_22015
Jun 22, 2022
Merged

Fix issue 22015, let Clip layer support 1-3 inputs#22100
alalek merged 8 commits intoopencv:4.xfrom
WanliZhong:issue_22015

Conversation

@WanliZhong
Copy link
Copy Markdown
Member

@WanliZhong WanliZhong commented Jun 14, 2022

Merge with extra: opencv/opencv_extra#980

This PR will fix the issue #22015

The essence of the issue is that the Clip layer is supposed to accept 1-3 inputs, but the implementation here is based on ReLU6, which only supports attributes as parameters.

layerParams.type = "ReLU6";

Solution: When parsing the Clip layer, the min and max obtained from node_proto.input(), instead of from layerParams, are passed as parameters to the ReLU6. This allows the Clip layer to support 1-3 inputs.

Let layer Clip support 1-3 inputs.
@zihaomu zihaomu self-assigned this Jun 15, 2022
@zihaomu
Copy link
Copy Markdown
Member

zihaomu commented Jun 15, 2022

Thanks for the contribution @WanliZhong. As a short-term solution I think it's ok. In the long run, it cannot resolve the following Clip node.
Example Clip

WanliZhong and others added 2 commits June 15, 2022 13:18
@asmorkalov asmorkalov requested a review from rogday June 15, 2022 06:50
@WanliZhong
Copy link
Copy Markdown
Member Author

WanliZhong commented Jun 17, 2022

Yes, this is a temporary solution. I have added such a model to verify the availability of the clip node when min and max are constant inputs. This will solve the import problem of the image_classification_mobilenetv2_2022apr.onnx model.
M51Y(L5SM7MU470`~ZG}~I3

Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for contribution!

Please take a look on minor comments below.

layerParams.set("max_value", layerParams.get<float>("max", FLT_MAX));
float min_value = -FLT_MAX, max_value = FLT_MAX;
int input_size = node_proto.input_size();
CV_Assert(1 <= input_size && input_size <= 3);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CV_Check(input_size, 1 <= input_size && input_size <= 3, "")

is preferable (more clear message in case of problem)

Comment on lines 387 to 391
TEST_P(Test_ONNX_layers, Clip)
{
testONNXModels("clip", npy);
testONNXModels("clip_init_min_max");
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create separate test for each model (grouping them is not a good practice).

TEST_P(Test_ONNX_layers, Clip_init_min_max)
{
    testONNXModels("clip_init_min_max");
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I will update the code in the next commit.

…put_size to provide a clearer message in case of problem.
@WanliZhong
Copy link
Copy Markdown
Member Author

@alalek Hi, why doesn't the workflow run automatically after the first approval?

Copy link
Copy Markdown
Member

@fengyuentau fengyuentau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other looks good to me 👍

Copy link
Copy Markdown
Member

@rogday rogday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment on lines +1939 to +1953
if(input_size == 2)
{
if (constBlobs.find(node_proto.input(1)) != constBlobs.end())
min_value = getBlob(node_proto, 1).at<float>(0);
else
CV_Error(Error::StsNotImplemented, "Non-constant min values in Clip are not supported");
}

if(input_size == 3)
{
if (constBlobs.find(node_proto.input(1)) != constBlobs.end())
min_value = getBlob(node_proto, 1).at<float>(0);
if (constBlobs.find(node_proto.input(2)) != constBlobs.end())
max_value = getBlob(node_proto, 2).at<float>(0);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do something like:

    
    if(input_size >= 2)
    {
        if (constBlobs.find(node_proto.input(1)) != constBlobs.end())
            min_value = getBlob(node_proto, 1).at<float>(0);
        else
            CV_Error(Error::StsNotImplemented, "Non-constant min values in Clip are not supported");
    }

    if(input_size == 3)
    {
        if (constBlobs.find(node_proto.input(2)) != constBlobs.end())
            max_value = getBlob(node_proto, 2).at<float>(0);
        else
            CV_Error(Error::StsNotImplemented, "Non-constant max values in Clip are not supported");
    }

In order to print errors messages in both cases.

Copy link
Copy Markdown
Member Author

@WanliZhong WanliZhong Jun 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since min and max are optional, I don't think we should throw an error if only min or max is available when the clip is initialized.

This is what I thought would happen:
image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional parameters can either be with empty name or omitted to indicate that they aren't supplied. So, we could just add a check that the name isn't empty.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This is indeed a better implementation and I will change it in the next commit.

Copy link
Copy Markdown
Member

@rogday rogday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@alalek alalek merged commit a6ca48a into opencv:4.x Jun 22, 2022
@rogday
Copy link
Copy Markdown
Member

rogday commented Jun 22, 2022

@alalek, should this be backported to 4.x?

@alalek
Copy link
Copy Markdown
Member

alalek commented Jun 22, 2022

It is a feature, so no - if there is no such requirement.

@WanliZhong WanliZhong mentioned this pull request Mar 14, 2023
48 tasks
a-sajjad72 pushed a commit to a-sajjad72/opencv that referenced this pull request Mar 30, 2023
Fix issue 22015, let Clip layer support 1-3 inputs

* Fix issue 22015.
Let layer Clip support 1-3 inputs.

* Resolve other problems caused by modifications

* Update onnx_importer.cpp

added extra checks to min/max handling in Clip

* Add assertions to check the size of the input

* Add test for clip with min and max initializers

* Separate test for "clip_init_min_max". Change the check method for input_size to provide a clearer message in case of problem.

* Add tests for clip with min or max initializers

* Change the implementation of getting input

Co-authored-by: Vadim Pisarevsky <vadim.pisarevsky@gmail.com>
@WanliZhong WanliZhong deleted the issue_22015 branch May 16, 2023 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: dnn (onnx) ONNX suport issues in DNN module category: dnn feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenCV fails to import ONNX model

6 participants