自动将一种c ++类型转换为另一种

时间:2018-01-17 01:28:22

标签: c++ opencv type-conversion

我正在尝试在自定义类和OpenCV之间进行转换。

Converting constructors允许我们声明一个没有explicit关键字的类,并从备用数据类型构造。

例如,我们可以声明两个类:

class Foo
{
public:
    std::vector<int32_t> data;

    Foo(int k) : data(k) {}
};

class FooProxy : public cv::Mat
{
public:
    FooProxy(const Foo & foo) :  cv::Mat(foo.data.size(), 1, CV_32SC1, (void*)foo.data.data()) {}
};

然后我们可以通过设置它来创建FooProxy,然后使用我们想要的任何OpenCV函数:

Foo myFoo(3);
myFoo.data = { 1,2,3 };

FooProxy fp = myFoo;
fp.setTo(1);
float myNorm = cv::norm(fp);

std::cout <<  "myFoo: " << myFoo.data.at(0) << ", " << myFoo.data.at(1) << ", " << myFoo.data.at(2) << "\n";
std::cout << "fp: " << fp.at<int32_t>(0) << ", " << fp.at<int32_t>(1) << ", " << fp.at<int32_t>(2) << "\n";
std::cout << "The Norm is: " << myNorm << "\n";

带输出:

myFoo: 1, 1, 1
fp: 1, 1, 1
The Norm is: 1.73205

但是,我更愿意写:

float myNorm = cv::norm(myFoo);

并让c ++自动转换myFoo。这可能吗?

这有效:

 float myNorm2 = cv::norm(FooProxy(myFoo));

但不是更简单的版本。

2 个答案:

答案 0 :(得分:3)

您可以创建conversion operator

class Foo
{
  ...

  operator cv::Mat()
  {
    return cv::Mat(data.size(), 1, CV_32SC1, (void*)data.data());
  }
};

修改 cv::norm有以下重载(请注意没有cv::Mat):

cv::norm(const Matx< _Tp, m, n > &M)
cv::norm(const Matx< _Tp, m, n > &M, int normType)
cv::norm(InputArray src1, int normType=NORM_L2, InputArray mask=noArray()) // this is the one we want
cv::norm(InputArray src1, InputArray src2, int normType=NORM_L2, InputArray mask=noArray())
cv::norm(const SparseMat &src, int normType)

cv::InputArray可以从cv::Mat构建,但是您只允许隐式地进行1次用户定义的转换。因此,如果您希望cv::InputArrayFoo一起使用,您实际上需要cv::norm的转换运算符。

答案 1 :(得分:2)

然后你应该在 namespace cv 中定义一个函数,如下所示:

namespace cv{
float norm(const Foo& foo){
    return cv::norm(FooProxy(foo));
}
}

现在你可以致电:

float res =  cv::norm(myFoo);

代码:

//! 2018.01.17 09:42:16 CST

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

class Foo
{
    public:
        std::vector<int32_t> data;

        Foo(int k) : data(k) {}
};

class FooProxy : public cv::Mat
{
    public:
        FooProxy(const Foo & foo) :  cv::Mat(foo.data.size(), 1, CV_32SC1, (void*)foo.data.data()) {}
};

namespace cv {
float norm(const Foo& foo) {
    return cv::norm(FooProxy(foo));
}
}

int main() {
    Foo myFoo(3);
    myFoo.data = { 1,2,3 };

    FooProxy fp = myFoo;
    fp.setTo(1);
    float myNorm = cv::norm(fp);

    std::cout <<  "myFoo: " << myFoo.data.at(0) << ", " << myFoo.data.at(1) << ", " << myFoo.data.at(2) << "\n";
    std::cout << "fp: " << fp.at<int32_t>(0) << ", " << fp.at<int32_t>(1) << ", " << fp.at<int32_t>(2) << "\n";
    std::cout << "The Norm is: " << myNorm << "\n";


    float myNorm2 = cv::norm(FooProxy(myFoo));
    std::cout << "The Norm2 is:"<<myNorm2<<endl;

    float myNorm3 = cv::norm(myFoo);
    std::cout << "The Norm3 is:"<<myNorm2<<endl;
}

结果:

myFoo: 1, 1, 1
fp: 1, 1, 1
The Norm is: 1.73205
The Norm2 is:1.73205
The Norm3 is:1.73205