为什么在使用OpenCV进行矩阵缩放时,星形(*)运算符比指针访问乘法快?

时间:2019-04-08 21:45:35

标签: performance opencv matrix

我正在尝试学习如何以最优化的方式操作OpenCV矩阵值。我尝试以四种不同方式缩放存储在OpenCV矩阵中的大图像。

1)使用星形*运算符

2)使用at函数和for循环

3)使用指针访问和for循环

4)使用查找表

该实验的四舍五入结果如下

*运算符------- 3 ms

at功能------- 12 ms

指针访问---- 9 ms

查找表-------- 1 ms

现在很明显为什么查找表是最快的。但是我并不总是能够使用它们。对于无法使用查找表的情况,我需要了解OpenCV如何使用*运算符实现缩放,以便可以在其他矩阵值操作中将该方法用作参考。

如果有人能告诉我*操作背后的情况使它比指针访问方法更快,我将不胜感激?

请找到以下代码以供参考。

谢谢

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <chrono>

typedef std::chrono::system_clock Timer;
typedef std::chrono::duration<double> Duration;

using std::cout;
using std::endl;
using std::vector;

double profile(Timer::time_point start, Timer::time_point end) {
    Duration span = end - start;
    return span.count() * 1000;
}

int main() {

    cv::Mat image = cv::imread("../data/large.jpg", 0);
    float sc = 1;

    while (true) {

        //=================== first method ====================
        Timer::time_point s1 = Timer::now();
        cv::Mat mine = image * sc;
        Timer::time_point s2 = Timer::now();

        //=================== second method ====================
        cv::Mat yours(image.size(), image.type());
        Timer::time_point s3 = Timer::now();
        for (int i = 0; i < image.rows; i++) {
            for (int j = 0; j < image.cols; j++) {
                yours.at<uchar>(i, j) = image.at<uchar>(i, j) * sc;
            }
        }
        Timer::time_point s4 = Timer::now();

        //=================== third method ====================
        if (!image.isContinuous()) {
            std::cerr << "ERROR: image matrix isn't stored as a 1D array" << endl;
            exit(-1);
        }
        Timer::time_point s5 = Timer::now();
        cv::Mat result(image.size(), image.type());
        for (int i = 0; i < image.rows; i++) {
            for (int j = 0; j < image.cols; j++) {
                result.data[i * image.cols + j] = image.data[i * image.cols + j] * sc;
            }
        }
        Timer::time_point s6 = Timer::now();

        //=================== fourth method ====================
        Timer::time_point s7 = Timer::now();
        cv::Mat lookupTable(1, 256, image.type());
        for (int i = 0; i < 256; i++)
            lookupTable.data[i] = i * sc;
        cv::Mat his;
        cv::LUT(image, lookupTable, his);
        Timer::time_point s8 = Timer::now();


        cout << "first = " << profile(s1, s2) << endl;
        cout << "second = " << profile(s3, s4) << endl;
        cout << "third = " << profile(s5, s6) << endl;
        cout << "fourth = " << profile(s7, s8) << endl;
        cout << "=============== " << endl;

    }

    return 0;
}

1 个答案:

答案 0 :(得分:0)

操作员*()使用parallel_for!因此它将比单线程函数更快。您可以在行循环之前编写#pragma omp parallel并比较结果。或者,您可以使用image.forEach-它也是并行且快速的。

cv :: LUT:https://github.com/opencv/opencv/blob/master/modules/core/src/lut.cpp#L359

此函数具有一组实现:opencl,openvx,ipp和带有parallel_for的简单实现。我认为在您的情况下,使用的是ipp_lut,这是Intel非常优化的处理器版本。而且速度很快!