Repository: opencv/opencv
File: modules/dnn/src/layers/nonmaxsuppression_layer.cpp (C++)

Code before:
    }

    bool supportBackend(int backendId) CV_OVERRIDE {
        return backendId == DNN_BACKEND_OPENCV;
    }

    virtual bool dynamicOutputShapes() const CV_OVERRIDE { return true; }

    bool getMemoryShapes(const std::vector<MatShape>& inputs, const int, std::vector<MatShape>& outputs, std::vector<MatShape>&) const CV_OVERRIDE {
        CV_Assert(inputs.size() >= 2);
        const MatShape& boxes = inputs[0];
        const MatShape& scores = inputs[1];
        CV_Assert(boxes.size() == 3 && boxes[2] == 4);
        CV_Assert(scores.size() == 3 && boxes[0] == scores[0] && boxes[1] == scores[2]);

        outputs.assign(1, MatShape({1, 3}));
        return false;
    }

    void getTypes(const std::vector<MatType>&, const int requiredOutputs, const int requiredInternals,
                   std::vector<MatType>& outputs, std::vector<MatType>& internals) const CV_OVERRIDE {
        outputs.assign(requiredOutputs, MatType(CV_64S));
    }

    void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE {
        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);

        const Mat& boxesBlob  = inputs[0];
        const Mat& scoresBlob = inputs[1];

        const int B = boxesBlob.size[0];
        const int N = boxesBlob.size[1];
        const int C = scoresBlob.size[1];

        int maxOut = defaultMaxOut;
        if (inputs.size() >= 3 && !inputs[2].empty())
        {
            CV_Assert(inputs[2].channels() == 1 && inputs[2].total() == 1);
            inputs[2].convertTo(Mat(1, 1, CV_32S, &maxOut), CV_32S);
        }
        float iouThr = defaultIouThr;
        if (inputs.size() >= 4 && !inputs[3].empty())
        {
            CV_Assert(inputs[3].channels() == 1 && inputs[3].total() == 1);
            inputs[3].convertTo(Mat(1, 1, CV_32F, &iouThr), CV_32F);
        }
        float scoreThr = defaultScoreThr;
        if (inputs.size() >= 5 && !inputs[4].empty())
        {

Review comment (suggestion):
1) move processing logic to a separate method, like 'run()'
2) handle inputs_arr.kind (or outputs_arr.kind) == STD_VECTOR_MAT and STD_VECTOR_UMAT, just like in Unique and other layers.

Code after:
    }

    bool supportBackend(int backendId) CV_OVERRIDE {
        return backendId == DNN_BACKEND_OPENCV;
    }

    virtual bool dynamicOutputShapes() const CV_OVERRIDE { return true; }

    bool getMemoryShapes(const std::vector<MatShape>& inputs, const int, std::vector<MatShape>& outputs, std::vector<MatShape>&) const CV_OVERRIDE {
        CV_Assert(inputs.size() >= 2);
        const MatShape& boxes = inputs[0];
        const MatShape& scores = inputs[1];
        CV_Assert(boxes.size() == 3 && boxes[2] == 4);
        CV_Assert(scores.size() == 3 && boxes[0] == scores[0] && boxes[1] == scores[2]);

        outputs.assign(1, MatShape({1, 3}));
        return false;
    }

    void getTypes(const std::vector<MatType>&, const int requiredOutputs, const int requiredInternals,
                   std::vector<MatType>& outputs, std::vector<MatType>& internals) const CV_OVERRIDE {
        outputs.assign(requiredOutputs, MatType(CV_64S));
    }

    void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE {
        std::vector<Mat> inputs, outputs;

        Mat boxesBlob, scoresBlob;
        int maxOut = defaultMaxOut;
        float iouThr = defaultIouThr;
        float scoreThr = defaultScoreThr;

        auto inKind = inputs_arr.kind();
        if (inKind == _InputArray::STD_VECTOR_UMAT) {
            std::vector<UMat> uinputs;
            inputs_arr.getUMatVector(uinputs);
            CV_Assert(uinputs.size() >= 2);
            boxesBlob = uinputs[0].getMat(ACCESS_READ);
            scoresBlob = uinputs[1].getMat(ACCESS_READ);
            if (uinputs.size() >= 3 && !uinputs[2].empty()) {
                Mat tmp = uinputs[2].getMat(ACCESS_READ);
                CV_Assert(tmp.channels() == 1 && tmp.total() == 1);
                maxOut = tensorToScalar<int>(tmp);
            }
            if (uinputs.size() >= 4 && !uinputs[3].empty()) {
                Mat tmp = uinputs[3].getMat(ACCESS_READ);
                CV_Assert(tmp.channels() == 1 && tmp.total() == 1);
                iouThr = tensorToScalar<float>(tmp);
            }
            if (uinputs.size() >= 5 && !uinputs[4].empty()) {
                Mat tmp = uinputs[4].getMat(ACCESS_READ);