如何将vector <mat>转换为vector <float>?

时间:2017-07-17 04:54:53

标签: c++ opencv

假设我有vector<Mat>名为regionFeaMatregionFeaMat.size() == 81。换句话说,regionFeaMat有81个相等大小的矩阵,regionFeaMat[0].rows==256regionFeaMat[0].cols==1。我想将reginFeaMat转换为vector<float> reginFeaVec。我尝试使用以下代码,但结果出错:

vector<float> regionFeaVec;
regionFeaVec.assign((float*)regionFeaMat[0].datastart, (float*)regionFeaMat[80].dataend);

1 个答案:

答案 0 :(得分:1)

你似乎做了一些错误的假设。

std::vector会将其元素连续存储在内存中,但cv::Mat是一个包含指向其内部缓冲区的指针的标头,因此只有vector<Mat>中的指针是连续存储的,而不是Mat数据本身。因此,位于(float*)regionFeaMat[0].dataend(float*)regionFeaMat[80].datastart之间的内存是一些随机垃圾 - 如果它确实包含其他Mat的数据,那就是纯粹的运气。

由于上述原因,您不能将矢量分配给任何其他矢量,您必须分别插入每个垫子。尝试这样的事情:

// prevent vector reallocation after each Mat insertion:
regionFeaVec.reserve(regionFeaMat.size()*regionFeaMat[0].cols*regionFeaMat[0].rows);
for (int i = 0; i < regionFeaMat.size(); ++i)
{
    if (regionFeaMat[i].isContinuous())
        regionFeaVec.insert(
                           regionFeaVec.end(), 
                           (float*)regionFeaMat[i].datastart, 
                           (float*)regionFeaMat[i].dataend
                           );
    else
    {
        for (int j = 0; j < regionFeaMat[i].rows; ++j)
        {
                const float* row = regionFeaMat[i].ptr<float>(j);
                regionFeaVec.insert(regionFeaVec.end(), row, row + regionFeaMat[i].cols);
        }
    }
}

请注意,我正在检查特定的Mat对象是否是连续的,因为根据OpenCV docs,在某些情况下,每行可能在末尾包含间隙,在这种情况下,我们必须通过以下方式读取矩阵行:行。

这段代码可以简化,因为如果矩阵是连续的,我们可以按照上面引用的文档将其视为一维向量:

// prevent vector reallocation after each Mat insertion:
regionFeaVec.reserve(regionFeaMat.size()*regionFeaMat[0].cols*regionFeaMat[0].rows);
for (int i = 0; i < regionFeaMat.size(); ++i)
{
    cv::Size size = regionFeaMat[i].size();
    if (regionFeaMat[i].isContinuous())
    {
        size.width *= size.height;
        size.height = 1;
    }
    for (int j = 0; j < size.height; ++j)
    {
        const float* row = regionFeaMat[i].ptr<float>(j);
        regionFeaVec.insert(regionFeaVec.end(), row, row + size.width);
    }
}

如果要在更一般的情况下阻止向量重新分配,还必须更改计算传递给reserve()的元素数量的方法。我使用的方法假设所有Mat对象只有两个对所有对象都相同的维度,因为这就是你描述问题的方式。

另外,如果您要将其分配给vector<float>,请确保regionFeaMat的元素类型为CV_32F