如何通过OpenCV Mat和GpuMat上的元素处理有效地完成?

时间:2017-08-01 11:40:59

标签: c++ opencv image-processing

我正在使用OpenCV C ++进行图像处理。我想在Mat和GpuMat 按元素进行一些快速处理。

例如,我必须将复合函数应用于Mat或GpuMat的每个元素。目前,我通过循环访问Mat的每个元素,如下所示:

// C++ Example 1: a and b are Mat
for (int i = 0; i < 512; i++) {
    for (int j = 0; j < 512; j++) {
        double sPixel = s.at<double>(512 * i + j);
        if (sPixel >= 0 && sPixel <= 1) {
            a.at<double>(512 * i + j) = double(1);
        } else if (sPixel > 1) {
            b.at<double>(512 * i + j) = double(1);
        }
    }
}

// C++ Example 2: f, x are Mat
for (int i = 0; i < 512; i++) {
    for (int j = 0; j < 512; j++) {
        f.at<double>(512 * i + j) = (1 / (2 * sigma)) * (1 + cos(pi * x.at<double>(512 * i + j) / sigma));
    }
}

但是,我认为这种方法很慢,因为Mat的元素之间没有实际的关系,如果按元素计算并行完成则会更好。

另一方面,我无法访问GpuMat的元素。如果Mat和GpuMat之间经常有downloadupload数据,那么它将非常慢并且不存在使用GPU的优势。

所以我的问题是:

  1. Mat和GpuMat上的元素处理有哪些改进方法? 特别是OpenCV本身提供的那些。
  2. GpuMat上的元素处理怎么做?

1 个答案:

答案 0 :(得分:2)

  1. 您只需使用内置的openCV函数来执行每个元素的操作。例如。你有重载矩阵运算符,用于加法,减去矩阵或矩阵和标量,元素乘法,除法,绝对差,三角函数,幂,根等函数。它们通常与标准库数学函数同名。只需搜索文档。要比较第一个示例中的矩阵元素,请使用matrix expressions

  2. 这与第1点非常相同。您必须检查openCV提供的功能,并将操作划分为可能使用这些功能执行的步骤。例如。这是这些函数的很好的列表:

  3. http://docs.opencv.org/2.4/modules/gpu/doc/per_element_operations.html

    http://docs.opencv.org/trunk/d8/d34/group__cudaarithm__elem.html

    如果上述功能对您来说不够,请避免使用at()方法访问像素,因为这非常无效,在迭代所有像素时不建议这样做。请改用ptr()函数来访问整行。

    以下是如何使用上述技术转换计算的示例:

    //first example
    b = (s > 1);
    a = (s >= 0).mul(s <= 1);
    
    //second example
    f = (1 / (2*sigma)) * ((1 + cos_mat) / sigma);
    

    openCV中没有每个元素cos()函数,但是如果你想要性能,你可以将余弦实现为泰勒序列,它将等于每个元素的乘法和减法/加法的几个,并获得这样cos_mat矩阵。你可以在这里找到一个例子:

    http://answers.opencv.org/question/55602/sine-or-cosine-of-every-element-in-mat-c/