需要一种更快的方法将 cv::Mat 转换为一维向量形式

Posted

技术标签:

【中文标题】需要一种更快的方法将 cv::Mat 转换为一维向量形式【英文标题】:Need a faster way to convert a cv::Mat into 1 dimensional vector form 【发布时间】:2014-07-28 18:28:36 【问题描述】:

我有一个 for 循环,它接受一个 n x n 维度的 OpenCV Mat 对象,并返回一个 n^2 x 1 维度的 Mat 对象。它可以工作,但是当我对该方法进行计时时,它需要 1 到 2 毫秒。由于我调用此方法 3 或 400 万次,因此我的程序运行大约需要一个小时。我引用的一篇研究论文表明,作者能够生成一个具有相同功能的程序,该程序只需几分钟即可运行,而无需并行运行任何线程。在对每一段代码进行计时后,唯一需要 >1 ms 的部分是以下方法。

static Mat mat2vec(Mat mat)


Mat toReturn = Mat(mat.rows*mat.cols, 1, mat.type());
float* matPt;
float* retPt;
for (int i = 0; i < mat.rows; i++) //rows
    
        matPt = mat.ptr<float>(i);
        for (int j = 0; j < mat.row(i).cols; j++) //col
        
            retPt = toReturn.ptr<float>(i*mat.cols + j);
            retPt[0] = matPt[j];
        
    
return toReturn;

有什么方法可以提高此方法将 n x n 矩阵转换为 n^2 x 1 矩阵(或 cv::Mat 表示向量)的速度?

这解决了@berak 的大部分问题,它现在运行得更快了。但是在某些情况下,如下所示,垫子不是连续的。知道如何在连续垫子中获得投资回报率吗?

我的方法不是这样的:

static Mat mat2vec(Mat mat)

if ( ! mat.isContinuous() )
 
    mat = mat.clone();

return mat.reshape(1,2500);

问题发生在:

Mat patch = Mat(inputSource, Rect((inputPoint.x - (patchSize / 2)), (inputPoint.y -        (patchSize / 2)), patchSize, patchSize));
Mat puVec = mat2vec(patch);

【问题讨论】:

制作一个 ROI 的 clone() 将使它连续,尽管这又是一个昂贵的操作。 mat2vec(patch.clone()) 未测试,但我认为Mat patch = Mat(inputSource, Rect((inputPoint.x - (patchSize / 2)), (inputPoint.y - (patchSize / 2)), patchSize, patchSize)); 应该是Mat patch = inputSource(Rect((inputPoint.x - (patchSize / 2)), (inputPoint.y - (patchSize / 2)), patchSize, patchSize));,如果需要,最后带有 .clone() 【参考方案1】:

假设你的 Mat 中的数据是连续的,Mat::reshape() 获胜。

而且几乎是免费的。只有行/列得到调整,没有内存移动。即,mat = mat.reshape(1,1) 将创建一个一维浮点数组。

【讨论】:

【参考方案2】:

在 OpenCV 3.2 中看到这个,但现在函数是 mat.reshape(1)

【讨论】:

以上是关于需要一种更快的方法将 cv::Mat 转换为一维向量形式的主要内容,如果未能解决你的问题,请参考以下文章

将 Magick::Image 转换为 cv::Mat

如何将 cv::Mat 类型从 CV_16UC1 转换为 CV_8UC1

使用 OpenCV 在 C++ 中将 std::list 转换为 cv::Mat

如何从 cv::Mat 转换为 CvArr?

如何将从 C++ 发送的 cv::MAT 字节数组转换为 Java 中的位图?

将一行 cv::Mat 转换为 std::vector