目录
说明
检查这个Mat是否为Vector,用来确认传入的数据格式是否正确。
源码
int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const
{
return data && (depth() == _depth || _depth <= 0) &&
(isContinuous() || !_requireContinuous) &&
((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) ||
(cols == _elemChannels && channels() == 1))) ||
(dims == 3 && channels() == 1 && size.p[2] == _elemChannels && (size.p[0] == 1 || size.p[1] == 1) &&
(isContinuous() || step.p[1] == step.p[2]*size.p[2])))
? (int)(total()*channels()/_elemChannels) : -1;
}
分析
这个函数就一句话,用的是三目运算符:?
? 之前的所有条件都满足了才能返回矩阵中元素的个数,否则返回-1.
注意:一个元素可能有多个通道。
下面是OpenCV中关于此函数的说明,大家可以参考。
-1 if the requirement is not satisfied.
Otherwise, it returns the number of elements in the matrix.
Note that an element may have multiple channels.
@param elemChannels Number of channels or number of columns the matrix should have.
* For a 2-D matrix, when the matrix has only 1 column, then it should have
* elemChannels channels; When the matrix has only 1 channel,
* then it should have elemChannels columns.
* For a 3-D matrix, it should have only one channel. Furthermore,
* if the number of planes is not one, then the number of rows
* within every plane has to be 1; if the number of rows within
* every plane is not 1, then the number of planes has to be 1.
笔者翻译:elemChannels参数指通道数,或者该矩阵应该有多少列。
对于2-D矩阵,应该是1列*N channels 或者 N列 * 1 channel。
对于3-D矩阵,应该只有 1 channel。而且,如果平面的个数不是 1,每个平面内的行数必须是 1;
如果每个平面内的行数不是 1,平面的个数必须是 1。
看到这会有疑惑的朋友请看下面的代码。
举例
debug时看到Mat表示 n 通道 * c 列 * r 行。
用到的构造函数
Mat::Mat(int _rows, int _cols, int _type)
存储方法一:如果有16个二维点,表示为 2通道* 1 列*16行 ,那么代码中应该这样写。
std::vector<cv::Point2d> pts1;
for (int i = 0; i < 16; i++)
{
pts1.push_back(cv::Point2d(i, i + 1));
}
// 点集是 1 row * N cols, 二维点 channel = 2
cv::Mat ptsMat1 = cv::Mat(pts1); // 将vector转为Mat
// npoints的值是16,点的个数
int nPtsMat1 = ptsMat1.checkVector(2);
存储方法二:16个二维点也可以这种方式存储与Mat中 2通道*16列*1行。
cv::Mat ptsMat2 = cv::Mat(1, 16, CV_32FC2);
for (int i = 0; i < ptsMat2.cols; i++)
{
ptsMat2.at<Vec2f>(0, i)[0] = i;
ptsMat2.at<Vec2f>(0, i)[1] = i*2;
}
int nPtsMat2 = ptsMat2.checkVector(2);
存储方法三:1通道*2列* 16行
cv::Mat ptsMat3 = cv::Mat(16, 2, CV_32F);
for (int i = 0; i < ptsMat3.rows; i++)
{
for (int j = 0; j < ptsMat3.cols; j++)
{
ptsMat3.at<float>(i, j) = i*ptsMat3.cols+j;
}
}
int nPtsMat3 = ptsMat3.checkVector(2);
三维点原理相同,只是vector里面是cv::Point3d.,不赘述。
注意事项:channel或row的个数必须有一个是 1 . 具体参考翻译。
对于3-D矩阵,应该只有 1 channel。而且,如果平面的个数不是 1,每个平面内的行数必须是 1;
如果每个平面内的行数不是 1,平面的个数必须是 1。
完整代码
// 方法一:如果有16个二维点,表示为 2通道* 1 列*16行
std::vector<cv::Point2d> pts1;
for (int i = 0; i < 16; i++)
{
pts1.push_back(cv::Point2d(i, i + 1));
}
// 点集是 1 row * N cols, 二维点 channel = 2
cv::Mat ptsMat1 = cv::Mat(pts1); // 将vector转为Mat
// npoints的值是16,点的个数
int nPtsMat1 = ptsMat1.checkVector(2);
// 方法二:16个二维点也可以这种方式存储与Mat中 2通道*16列*1行。
cv::Mat ptsMat2 = cv::Mat(1, 16, CV_32FC2);
for (int i = 0; i < ptsMat2.cols; i++)
{
ptsMat2.at<Vec2f>(0, i)[0] = i;
ptsMat2.at<Vec2f>(0, i)[1] = i*2;
}
int nPtsMat2 = ptsMat2.checkVector(2);
// 方法三:1通道*2列* 16行
cv::Mat ptsMat3 = cv::Mat(16, 2, CV_32F);
for (int i = 0; i < ptsMat3.rows; i++)
{
for (int j = 0; j < ptsMat3.cols; j++)
{
ptsMat3.at<float>(i, j) = i*ptsMat3.cols+j;
}
}
int nPtsMat3 = ptsMat3.checkVector(2);
OpenCV官方示例
/**
* @brief It demonstrates the usage of cv::Mat::checkVector.
*/
#include <opencv2/core.hpp>
int main()
{
//! [example-2d]
cv::Mat mat(20, 1, CV_32FC2);
int n = mat.checkVector(2);
CV_Assert(n == 20); // mat has 20 elements
mat.create(20, 2, CV_32FC1);
n = mat.checkVector(1);
CV_Assert(n == -1); // mat is neither a column nor a row vector
n = mat.checkVector(2);
CV_Assert(n == 20); // the 2 columns are considered as 1 element 1个元素是2列
//! [example-2d]
mat.create(1, 5, CV_32FC1);
n = mat.checkVector(1);
CV_Assert(n == 5); // mat has 5 elements
n = mat.checkVector(5);
CV_Assert(n == 1); // the 5 columns are considered as 1 element
//! [example-3d]
int dims[] = {1, 3, 5}; // 1 plane, every plane has 3 rows and 5 columns
mat.create(3, dims, CV_32FC1); // for 3-d mat, it MUST have only 1 channel
n = mat.checkVector(5); // the 5 columns are considered as 1 element
CV_Assert(n == 3);
int dims2[] = {3, 1, 5}; // 3 planes, every plane has 1 row and 5 columns
mat.create(3, dims2, CV_32FC1);
n = mat.checkVector(5); // the 5 columns are considered as 1 element 1个元素是5列
CV_Assert(n == 3);
//! [example-3d]
return 0;
}