在c++中加速对带有指针的数组的访问

Speeding up access to a array with pointers in C++

本文关键字:指针 数组 访问 c++ 加速      更新时间:2023-10-16

我正在尝试快速图像阈值函数。目前我做的是:

void threshold(const cv::Mat &input, cv::Mat &output, uchar threshold) {
    int rows = input.rows;
    int cols = input.cols;
    // cv::Mat for result
    output.create(rows, cols, CV_8U);        
    if(input.isContinuous()) { //we have to make sure that we are dealing with a continues memory chunk
        const uchar* p;
        for (int r = 0; r < rows; ++r) {
            p = input.ptr<uchar>(r);
            for (int c = 0; c < cols; ++c) {
                if(p[c] >= threshold)
                    //how to access output faster??
                    output.at<uchar>(r,c) = 255;
                else
                    output.at<uchar>(r,c) = 0;
            }
        }
    }
}

我知道at()函数相当慢。我怎样才能更快地设置输出,或者换句话说,如何将我从输入到输出得到的指针联系起来?

您认为at作为c++标准库为几个容器文档,执行范围检查并抛出越界,但这不是标准库,而是OpenCV。

根据cv::Mat::at文档:

模板方法返回对指定数组元素的引用。为了提高性能,索引范围检查只在Debug配置中执行。

所以你可能会想,没有范围检查

比较源代码中的cv::Mat::atcv::Mat::ptr,我们可以看到它们几乎相同。

所以cv::Mat::ptr<>(row)和

一样昂贵
return (_Tp*)(data + step.p[0] * y);

而cv::Mat::at<>(行,列)和:

一样昂贵
return ((_Tp*)(data + step.p[0] * i0))[i1];

您可能希望直接使用cv::Mat::ptr,而不是每列调用cv::Mat::at,以避免进一步重复data + step.p[0] * i0操作,自己执行[i1]

你可以这样做:

/* output.create and stuff */
const uchar* p, o;
for (int r = 0; r < rows; ++r) {
    p = input.ptr<uchar>(r);
    o = output.ptr<uchar>(r); // <-----
    for (int c = 0; c < cols; ++c) {
        if(p[c] >= threshold)
           o[c] = 255;
          else
            o[c] = 0;
    }
}

作为旁注,你不应该也不应该检查cv::Mat::isContinuous在这里,差距是从一行到另一行,你正在采取指针到单行,所以你不需要处理矩阵差距。