传递opencv inputarray并将其用作std :: vector

时间:2014-09-09 16:51:04

标签: c++ opencv vector

我想编写一个使用cv :: InputArray作为参数的自定义函数。 在函数中,我理解我可以使用cv :: InputArray :: getMat来获取输入cv :: Mat的头。

我在将std :: vector传递给cv :: InputArray时遇到了一些困惑。

1.如果我将std :: vector传递给函数,我还能在函数中获取std :: vector吗?例如:

void foo(cv::InputArray _input)
{
    std::vector<cv::Point2f> input = _input.getVector() // getVector function doesn't exist
}

std::vector<cv::Point2f> a;
foo(a);

2.如果我将std :: vector传递给函数并使用getMat在函数中获取cv :: Mat,那么mat将如何显示?

Poly在std::vector<char>的情况下做了明确的解释。如果我想在函数中获得std::vector<cv::Point2f>该怎么办?

非常感谢。

2 个答案:

答案 0 :(得分:3)

当您将向量传递给带InputArray的函数时,您隐式调用转换构造函数InputArray::InputArray(vector)。 (转换构造函数在这里解释:https://stackoverflow.com/a/15077788/928387

在此构造函数中,向量的指针简单地分配给InputArray中的obj成员变量。如果您使用OpenCV 3.0,则InputArray具有getObj()方法,因此您可以通过以下方式获取向量:

// Only works on OpenCV 3.0 or above
const std::vector<Point2f>& input = *(const std::vector<Point2f>*)_input.getObj();

如果您使用OpenCV 2.X,则可以使用InputArray::getMat()。它返回具有指向数据的指针的Mat对象。所以你也可以采取以下方式。

// Should Work on any OpenCV version
cv::Mat mat = _input.getMat();
Point2f *data = (Point2f *)mat.data;
int length = mat.total();
std::vector<Point2f> input;
input.assign(data, data + length);

关于第二个问题,如果在带有N元素的InputArray对象上调用InputArray::getMat(),则返回(N * 1)矩阵。

答案 1 :(得分:1)

请注意InputArray::getObj()返回创建它的对象。因此,如果_input是使用std::vector创建的,则有效!这可以通过InputArray::isVector()进行检查。

否则,必须创建一个新的std::vector对象。不幸的是,没有办法告诉std::vector使用现有数据。我认为使用你自己的allocator时甚至都不可能。如果您仍需要std::vector,请使用指针/迭代器(在constructorstd::vector::assign()中)来创建带有数据副本的新对象。您可以直接从_input通过InputArray::total()获取尺寸。

矢量

根据之前的观察,我结合了Poly提出的尝试。

std::vector<Point2f> *input;
if (_input.isVector()) {
    input = static_cast<std::vector<Point2f>*>(_input.getObj());
} else {
    size_t length = _input.total();
    Point2f* data = reinterpret_cast<Point2f*>(_input.getMat().data);
    input = new std::vector<Point2f>(data, data + length);
}

模板

要重用其他类型的代码,我建议使用模板。

template<class T>
std::vector<T>& getVec(InputArray _input) {
    std::vector<T> *input;
    if (_input.isVector()) {
        input = static_cast<std::vector<T>*>(_input.getObj());
    } else {
        size_t length = _input.total();
        T* data = reinterpret_cast<T*>(_input.getMat().data);
        input = new std::vector<T>(data, data + length);
    }
    return *input;
}

此外,您应该通过InputArray::type()检查类型是否兼容。

阵列

如果您只想轻松编制索引,当然可以使用标准的C风格数组(注意,C ++风格std::array也需要复制数据)。

Point2f* data = reinterpret_cast<Point2f*>(_input.getMat().data);

然后您可以通过

访问数据
Point2f p = data[5];