OpenCV 的“calcCovarMatrix”函数中“const Mat* samples”参数的工作原理?
Posted
技术标签:
【中文标题】OpenCV 的“calcCovarMatrix”函数中“const Mat* samples”参数的工作原理?【英文标题】:Workings of ``const Mat* samples`` param in OpenCV's ``calcCovarMatrix`` function? 【发布时间】:2019-03-28 22:40:20 【问题描述】:我正在尝试计算 OpenCV 中多个矩阵的协方差矩阵,并看到了 calcCovarMatrix
的 2 个版本。我很好奇,想使用以const Mat* samples, int nsamples
作为前 2 个参数的重载版本。
问题:samples
参数是什么?它是指向 Mats 向量的第一项的指针吗?为什么它本身不是向量?传递什么/参数如何工作?
P.S.:我不想使用该函数的其他重载版本!我想了解我询问的版本中使用的实际代码。
【问题讨论】:
那你为什么不检查source code呢? 我有点不清楚你的问题是否正确,但我尝试:想象一下你有一个函数需要std::vector<SomeThing>
(当然,最好是const std::vector<SomeThing>&
)。现在,假设您有一个 SomeThings
的常量静态数组,您想输入它 - 如果没有副本,这是不可能的,因为副本可能既昂贵又不必要。现在,想象一下相反的情况:一个将const SomeThing*
与size_t
结合在一起的函数。是的,它看起来很丑而且很 C 风格,但是:你可以按地址输入数组,它的长度会增加一点 sizeof
魔法。
...您也可以使用std::vector::data()
和std::vector::size()
输入std::vector
。 (这适用于除bool
之外的所有类型,但这是另一回事。)因此,丑陋的C 风格函数实际上更灵活。顺便提一句。如果有疑问,只需创建第二个函数(作为内联函数),它接受 std::vector
并使用 data()
和 size()
调用另一个函数。 (如果我遇到你的问题,我会很乐意用一个最小的实际例子来回答这个问题。);-)
@Miki ,因为源代码只显示正在做什么,而不是为什么它是这样的(即没有解释为什么它不是std::vector
)。
@Scheff 所以是为了灵活性?感谢您的解释!如果您做出回答,我会很乐意接受您的回答:)
【参考方案1】:
我确信 OpenCV 的作者更喜欢 const Mat*
、int
对参数而不是 std::vector
,因为这样更灵活。
想象一个必须处理一系列特定对象的函数。
在 C++ 中,可以使用std::vector
存储一系列对象。但是,如果这些对象的系列是静态常量,即可以在编译时定义怎么办?该对象的普通旧 C 数组也可以完成这项工作。
可以处理这样一系列对象的函数可以接受const std::vector&
。如果应用于 C 数组,则必须构建一个临时向量实例。 C++ 代码相对简单,但它会让人感到恶心,因为必须将数组内容复制到临时的 std::vector
实例中才能将其传递给函数。
相反的情况:函数接受一个指向起始对象的指针和一个计数(就像在 C 中通常一样)。这样的函数可以应用于 C 数组以及 std::vector
,因为 std::vector
提供了一个 data()
方法,该方法提供了一个指向其第一个元素的 const 指针和一个 size()
方法。此外,向量元素可以像 C 数组一样连续存储。
所以,我的简单例子:
#include <cassert>
#include <cmath>
#include <iostream>
#include <vector>
// Pi (from Windows 7 calculator)
const float Pi = 3.1415926535897932384626433832795;
struct Point
float x, y;
;
std::ostream& operator<<(std::ostream &out, const Point &point)
return out << '(' << point.x << ", " << point.y << ')';
Point average(const Point *points, size_t size)
assert(size > 0);
Point sum = points[0];
for (size_t i = 1; i < size; ++i)
sum.x += points[i].x; sum.y += points[i].y;
return sum.x / (unsigned)size, sum.y / (unsigned)size ;
static const Point square[] =
-0.5f, -0.5f ,
+0.5f, -0.5f ,
+0.5f, +0.5f ,
-0.5f, +0.5f
;
static const size_t sizeSquare = sizeof square / sizeof *square;
int main()
// process points of a static const square (using average() with an array)
std::cout << "CoG of " << sizeSquare << " points of square: "
<< average(square, sizeSquare) << '\n';
// build a tesselated circle
std::vector<Point> circle;
const unsigned n = 16;
for (unsigned i = 0; i < n; ++i)
const float angle = i * 2 * Pi / n;
circle.push_back( std::sin(angle), std::cos(angle) );
// process points of that circle (using average() with a vector)
std::cout << "CoG of " << circle.size() << " points of circle: "
<< average(circle.data(), circle.size()) << '\n';
// done
return 0;
输出:
CoG of 4 points of square: (0, 0)
CoG of 16 points of circle: (-5.58794e-09, 4.47035e-08)
Live Demo on coliru
为方便起见,可以为std::vector
添加以下替代定义:
static inline Point average(const std::vector<Point> &points)
return average(points.data(), points.size());
一个通用的解决方案将提供一个替代方案,其中包含两个可应用于任何容器的迭代器。 (C++ 标准库中有很多这方面的例子。)
我只能假设 OpenCV 作者专注于性能而不是灵活性(但这只是我个人的猜测)。
【讨论】:
以上是关于OpenCV 的“calcCovarMatrix”函数中“const Mat* samples”参数的工作原理?的主要内容,如果未能解决你的问题,请参考以下文章
opencv学习之路(38)Mat像素统计基础——均值,标准差,协方差