Reputation: 518
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
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:
Mat
s or UMat
s depending on the input type.Mat
⟷ UMat
conversion.Disadvantage:
Mat
s and UMat
s.Upvotes: 1
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