Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dnn: add more CANN operators to support SAM #23550

Closed
wants to merge 14 commits into from

Conversation

fengyuentau
Copy link
Member

@fengyuentau fengyuentau commented Apr 26, 2023

This PR is based on #23491. Need to merge #23491 first then rebase this PR.

To-do list:

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • 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
  • The PR is proposed to the proper branch
  • There is a reference to the original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

@fengyuentau fengyuentau added this to the 4.8.0 milestone Apr 27, 2023
@fengyuentau fengyuentau removed this from the 4.8.0 milestone May 31, 2023
@@ -20,11 +21,13 @@ class LayerNormLayerImpl CV_FINAL : public LayerNormLayer

// opencv attr
hasBias = params.get<bool>("hasBias", false);
is1D = params.get<bool>("is1D", false);
Copy link
Member

Choose a reason for hiding this comment

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

If I'm not mistaken, in case of 1D cv::Mat it has N rows and 1 column (Nx1). So with axis = 0 it should be correct. I think using such shortcut from MVN is enough:

if ( inpBlob.total() == newRows )
{
// MVN is applied to single values at an every row.
if (shift.empty())
{
outBlob.setTo(0);
}
else
{
for ( i = 0; i < newRows; i++ )
{
outMat.row(i).setTo(((float*)shift.data)[i]);
}
}
return;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

@dkurt, in 4.x there is no support for 1D. In 5.x I have added support for 1D and 0D matrices. 1D matrix of N elements may be interpreted (if you ignore Mat::dims) as 1xN 2D matrix, i.e. it's a single-row matrix, not single-column

Copy link
Member

Choose a reason for hiding this comment

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

My point is that instead of extra is1D flag there is a check that let skip layer compute because output values will be all zeros.

Copy link
Member Author

Choose a reason for hiding this comment

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

The 1d flag is introduced for other backends to avoid incorrect shape inference. Let me try to bypass this...

Lets say axis=-1 and the shape of scale mat is still 2d; that stands for a 1d scale and bias tensor.

@fengyuentau fengyuentau added the category:dnn_cann CANN backend related issues in DNN module label Sep 13, 2023
@fengyuentau fengyuentau mentioned this pull request Oct 9, 2023
12 tasks
@fengyuentau fengyuentau added this to the 4.10.0 milestone Nov 10, 2023
@fengyuentau
Copy link
Member Author

This PR is too out-of-date. Created a new PR #24756 in place of this one.

@LaurentBerger
Copy link
Contributor

LaurentBerger commented Dec 23, 2023

What's about Mod layer?

class MyModLayer : public cv::dnn::Layer
{
protected:
    Mat divisor;
public:
    MyModLayer(const cv::dnn::LayerParams& params);
    static cv::Ptr<cv::dnn::Layer> create(cv::dnn::LayerParams& params)
    {
        return cv::Ptr<cv::dnn::Layer>(new MyModLayer(params));
    }
    virtual bool getMemoryShapes(const std::vector<MatShape >& inputs,
        const int requiredOutputs,
        std::vector<MatShape >& outputs,
        std::vector<MatShape>& internals) const CV_OVERRIDE
    {
        outputs.assign(1, inputs[0]);
        return true;
    }
    virtual void forward(cv::InputArrayOfArrays inputs_arr,
        cv::OutputArrayOfArrays outputs_arr,
        cv::OutputArrayOfArrays internals)
    {
        std::vector<cv::Mat> inputs, outputs, internal;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);
        internals.getMatVector(internal);
        Mat blob;
        if ((inputs.size() == 2 && inputs[1].total() == 1 ) || (inputs.size() == 1 && divisor.total()==1))
        {
            int valDivisor;
            if (inputs.size() == 2)
                valDivisor = inputs[1].at<int>(0);
            else
                valDivisor = divisor.at<int>(0);
            inputs[0].copyTo(blob);
            int x = 2;
            switch (blob.depth()) {
            case CV_8U:
                blob.forEach<uchar>([&](uchar elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_8S:
                blob.forEach<char>([&](char elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_16U:
                blob.forEach<ushort>([&](ushort elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_16S:
                blob.forEach<short>([&](short elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_32S:
                blob.forEach<int>([&](int elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_32F:
                blob.forEach<float>([&](float elem, const int* p) { elem = int(elem) % valDivisor; });
                break;
            default:
                CV_Error(-1, "Unimplemented type");
            }
        }
        else
            CV_Error(-1, "Cannot manage mod layer with more than one divisor");
        blob.copyTo(outputs[0]);
    }
    virtual void finalize(cv::InputArrayOfArrays inputs,
        cv::OutputArrayOfArrays outputs)
    {}

};

@fengyuentau
Copy link
Member Author

What's about Mod layer?

class MyModLayer : public cv::dnn::Layer
{
protected:
    Mat divisor;
public:
    MyModLayer(const cv::dnn::LayerParams& params);
    static cv::Ptr<cv::dnn::Layer> create(cv::dnn::LayerParams& params)
    {
        return cv::Ptr<cv::dnn::Layer>(new MyModLayer(params));
    }
    virtual bool getMemoryShapes(const std::vector<MatShape >& inputs,
        const int requiredOutputs,
        std::vector<MatShape >& outputs,
        std::vector<MatShape>& internals) const CV_OVERRIDE
    {
        outputs.assign(1, inputs[0]);
        return true;
    }
    virtual void forward(cv::InputArrayOfArrays inputs_arr,
        cv::OutputArrayOfArrays outputs_arr,
        cv::OutputArrayOfArrays internals)
    {
        std::vector<cv::Mat> inputs, outputs, internal;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);
        internals.getMatVector(internal);
        Mat blob;
        if ((inputs.size() == 2 && inputs[1].total() == 1 ) || (inputs.size() == 1 && divisor.total()==1))
        {
            int valDivisor;
            if (inputs.size() == 2)
                valDivisor = inputs[1].at<int>(0);
            else
                valDivisor = divisor.at<int>(0);
            inputs[0].copyTo(blob);
            int x = 2;
            switch (blob.depth()) {
            case CV_8U:
                blob.forEach<uchar>([&](uchar elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_8S:
                blob.forEach<char>([&](char elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_16U:
                blob.forEach<ushort>([&](ushort elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_16S:
                blob.forEach<short>([&](short elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_32S:
                blob.forEach<int>([&](int elem, const int* p) { elem = elem % valDivisor; });
                break;
            case CV_32F:
                blob.forEach<float>([&](float elem, const int* p) { elem = int(elem) % valDivisor; });
                break;
            default:
                CV_Error(-1, "Unimplemented type");
            }
        }
        else
            CV_Error(-1, "Cannot manage mod layer with more than one divisor");
        blob.copyTo(outputs[0]);
    }
    virtual void finalize(cv::InputArrayOfArrays inputs,
        cv::OutputArrayOfArrays outputs)
    {}

};

Sure, let me do it in a new PR.

@opencv-alalek opencv-alalek removed this from the 4.10.0 milestone Dec 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category:dnn_cann CANN backend related issues in DNN module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants