Gianni
Gianni

Reputation: 518

Writing template functions accepting inputs of type cv::Mat or cv::UMat

What is the simplest and cleanest way to write a function accepting input arguments of type Mat or UMat?

Should I use InputArray, use templates or is there a better alternative? I am currenlty having functions with identical implementation written for both Mat and UMat.

The function should take full advantage of the UMat abstraction over OpenCL, and running roughly as fast as if it was written just for UMats, and without the overhead of having to copy UMats to Mats.

An example of function which I could want to define for both Mat and UMat is the following (please do not propose refactoring to remove local Mat/UMat variables, this is just an example)

using namespace cv;    

void foo(const Mat & in1, const Mat & in2, Mat & out)
{
    Mat aux1;
    Mat aux2;
    exp(in1, aux1);
    exp(in2, aux2);
    add(aux1, aux2, out);
    return;
}

void foo(const UMat & in1, const UMat & in2, UMat & out)
{
    UMat aux1;
    UMat aux2;
    exp(in1, aux1);
    exp(in2, aux2);
    add(aux1, aux2, out);
    return;
}

Upvotes: 2

Views: 888

Answers (2)

angelo-peronio
angelo-peronio

Reputation: 379

I used a template:

using namespace cv;    

// MatType is either cv::Mat or cv::UMat.
template<typename MatType>
void foo(const MatType& in1, const MatType& in2, MatType& out)
{
    MatType aux1;
    MatType aux2;
    exp(in1, aux1);
    exp(in2, aux2);
    add(aux1, aux2, out);
    return;
}

Advantages:

  • It is easy to declare local Mats or UMats depending on the input type.
  • No MatUMat conversion.

Disadvantage:

  • All matrix arguments must be of the same type, it is not possible to mix Mats and UMats.

Upvotes: 1

Kinght 金
Kinght 金

Reputation: 18331

Suggested by @Miki and @Gianni, we can choose InpputArray and OutputArray for the general template types of Mat, Mat_<T>, Matx<T, m, n>, std::vector<T>, std::vector<std::vector<T> >, std::vector<Mat>, std::vector<Mat_<T> >, UMat, std::vector<UMat> or double.

void func(InputArray _src1, InputArray _src2, OutputArray _dst)
{
    Mat src1 = _src1.getMat(), src2 = _src2.getMat();
    CV_Assert( src1.type() == src2.type() && src1.size() == src2.size());
    Mat aux1 = Mat(src1.size(), src1.type());
    Mat aux2 = Mat(src1.size(), src1.type());
    cv::exp(src1, aux1);
    cv::exp(src2, aux2);

    _dst.create(src1.size(), src1.type());
    Mat dst = _dst.getMat();
    cv::add(aux1, aux2, dst);
}

Now you can test it with Mat or UMat or even std::vector

int test(){
    std::vector<float> vec1 = {1,2,3};
    std::vector<float> vec2 = {3,2,1};
    std::vector<float> dst;

    func(vec1, vec2, dst);
    // now dst is [22.8038, 14.7781, 22.8038]

}

Upvotes: 2

Related Questions