OpenCV checkVector()函数说明与C++代码举例

目录

说明

源码

分析

举例

完整代码

OpenCV官方示例


说明

检查这个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;
}
发布了86 篇原创文章 · 获赞 88 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/yl_best/article/details/104540709
今日推荐