我想编写一个使用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>
该怎么办?
非常感谢。
答案 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
,请使用指针/迭代器(在constructor或std::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];