传递 opencv inputarray 并将其用作 std::vector
Posted
技术标签:
【中文标题】传递 opencv inputarray 并将其用作 std::vector【英文标题】:Pass opencv inputarray and use it as std::vector 【发布时间】:2014-09-09 16:51:03 【问题描述】:我想编写一个使用 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 会是什么样子?
对于std::vector<char>
的情况,保利做了明确的解释。如果我想在函数中得到std::vector<cv::Point2f>
,有什么建议吗?
非常感谢。
【问题讨论】:
【参考方案1】:当您将向量传递给采用InputArray
的函数时,您会隐式调用转换构造函数InputArray::InputArray(vector)
。 (这里解释了转换构造函数:https://***.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) 矩阵。
【讨论】:
您好,感谢您的回答。我尝试了两种方法,但都没有奏效。对于第一种方式,InputArray 没有 getObj() 方法,所以我假设您的意思是 getMat()。这给了我编译错误,例如:无法从 'cv::Mat' 转换为 'const std::vector<_ty> *'。对于第二种方法,我想恢复cv::Point2f的向量,但是结果不正确。 似乎只有 OpenCV 3.0 有 getObj() 方法。我更新了我的原始答案以包含版本描述并使用 Point2f。我使用 OpenCV 2.4.8 在我的机器上成功恢复了 vector请注意,InputArray::getObj()
返回创建它的对象。因此,如果 _input
是使用 std::vector
创建的,则投射 only 有效!这可以通过InputArray::isVector()
进行检查。
否则,必须创建一个新的std::vector
对象。不幸的是,没有办法告诉std::vector
使用现有数据。我认为使用您自己的allocator 时甚至不可能。如果您仍然想要std::vector
,请使用指针/迭代器(在constructor 或std::vector::assign()
中)创建带有数据副本的新对象。您可以通过InputArray::total()
直接从_input
获取大小。
矢量
基于之前的观察,我结合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];
【讨论】:
以上是关于传递 opencv inputarray 并将其用作 std::vector的主要内容,如果未能解决你的问题,请参考以下文章
为啥 OPENCV 中有这么多函数使用 InputArray 和 OutputArray 作为函数参数?
将 Qt QByteArray 转换为 OpenCV cv::InputArray