【问题标题】:Opencv Mat vector assignment to a row of a matrix, fastest way?Opencv Mat向量分配给矩阵的一行,最快的方法?
【发布时间】:2014-09-23 09:14:27
【问题描述】:

在循环中将向量分配给矩阵行的最快方法是什么?我想用向量沿其行填充 数据矩阵。这些向量在循环中计算。这个循环一直持续到 data matrix 的所有条目都被这些向量填充。

目前我正在使用cv::Mat::at<>() 方法来访问矩阵的元素并用向量填充它们,但是,这个过程似乎很慢。我尝试过使用cv::Mat::X.row(index) = data_vector 的另一种方法,它工作得很快,但是用一些我无法理解的垃圾值填充我的矩阵X,为什么。

我读到存在另一种使用指针的方法(最快的方法),但是,我无法理解。有人可以解释如何使用它们或其他不同的方法吗?

这是我的代码的一部分:

#define OFFSET 2

cv::Mat im = cv::imread("001.png", CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat X = cv::Mat((im.rows - 2*OFFSET)*(im.cols - 2*OFFSET), 25, CV_64FC1); // Holds the training data. Data contains image patches
cv::Mat patch = cv::Mat(5, 5, im.type()); // Holds a cropped image patch
typedef cv::Vec<float, 25> Vec25f;

int ind = 0;
for (int row = 0; row < (im.rows - 2*OFFSET); row++){
    for (int col = 0; col < (im.cols - 2*OFFSET); col++){

    cv::Mat temp_patch = im(cv::Rect(col, row, 5, 5)); // crop an image patch (5x5) at each pixel
    patch = temp_patch.clone(); // Needs to do this because temp_patch is not continuous in memory 
    patch.convertTo(patch, CV_64FC1);

    Vec25f data_vector = patch.reshape(0, 1); // make it row vector (1X25).
    for (int i = 0; i < 25; i++) 
    {
        X.at<float>(ind, i) = data_vector[i]; // Currently I am using this way (quite slow).
    }

    //X_train.row(ind) = patch.reshape(0, 1); // Tried this but it assigns some garbage values to the data matrix!
    ind += 1;
    }
}

【问题讨论】:

  • 如果你真的想访问单个 ROW,它总是连续的 afaik。

标签: c++ opencv matrix


【解决方案1】:

要做到这一点,你可以做常规的 opencv 方式:-

ImageMat.row(RowIndex) = RowMat.clone();

RowMat.copyTo(ImageMat.row(RowIndex));

尚未测试正确性或速度。

【讨论】:

    【解决方案2】:

    只需对代码进行几处编辑

    double * xBuffer = X.ptr<double>(0);
    for (int row = 0; row < (im.rows - 2*OFFSET); row++){
        for (int col = 0; col < (im.cols - 2*OFFSET); col++){
    
        cv::Mat temp_patch = im(cv::Rect(col, row, 5, 5)); // crop an image patch (5x5) at each pixel
        patch = temp_patch.clone(); // Needs to do this because temp_patch is not continuous in memory 
        patch.convertTo(patch, CV_64FC1);
        memcpy(xBuffer, patch.data, 25*sizeof(double));
        xBuffer += 25;
        }
    }
    

    另外,您似乎没有在 patch 中进行任何计算,只是提取灰度值,因此您可以创建与 im 相同类型的 X,并在最后将其转换为 double。这样,您可以 memcpy 补丁的每一行,内存中的地址 beeing `unsigned char* buffer = im.ptr(row) + col

    【讨论】:

    • 有些事情要提一下:patch.convertTo(patch,...) 总是会在每次循环运行时重新分配内存。在循环之前创建另一个 Mat: cv::Mat convertedPatch; 并重用它,不会重新分配内存。如果直接使用temp_patch.convertTo(patch,...)(或convertedPatch),则不需要Clone - 不是100%确定它是否仍然连续。
    【解决方案3】:

    根据docs

    如果你需要处理一整行矩阵,最有效的方法是先获取指向该行的指针,然后使用纯C运算符[]:

    // compute sum of positive matrix elements
    // (assuming that M is double-precision matrix)
    double sum=0;
    for(int i = 0; i < M.rows; i++)
    {
        const double* Mi = M.ptr<double>(i);
        for(int j = 0; j < M.cols; j++)
            sum += std::max(Mi[j], 0.);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      • 1970-01-01
      • 2012-02-12
      • 1970-01-01
      • 2015-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多