Skip to content

dnn: add more CANN operators to support SAM#23550

Closed
fengyuentau wants to merge 14 commits intoopencv:4.xfrom
fengyuentau:cann_sam
Closed

dnn: add more CANN operators to support SAM#23550
fengyuentau wants to merge 14 commits intoopencv:4.xfrom
fengyuentau:cann_sam

Conversation

@fengyuentau
Copy link
Copy Markdown
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

// opencv attr
hasBias = params.get<bool>("hasBias", false);
is1D = params.get<bool>("is1D", false);
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.

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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Member Author

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

@LaurentBerger
Copy link
Copy Markdown
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
Copy Markdown
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
@fengyuentau fengyuentau deleted the cann_sam branch June 25, 2025 10:48
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