使用C ++中的指针加速对数组的访问

时间:2015-05-14 21:12:30

标签: c++ pointers opencv

我正在尝试制作快速图像阈值功能。目前我所做的是:

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()功能很慢。如何更快地设置输出,或者换句话说如何将从输入到输出的指针关联起来?

1 个答案:

答案 0 :(得分:1)

您正在考虑at,因为C ++标准库会为几个容器记录它,执行范围检查并在超出范围时抛出,但这不是标准库,而是OpenCV。

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

  

模板方法返回对指定数组元素的引用。 为了获得更高的性能,索引范围检查仅在调试配置中执行

因此您可能没有考虑范围检查。

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

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

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

虽然cv::Mat::at<>(row, column)和以下一样贵:

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,这些差距是从一行到另一行,你是指向一行,所以你不需要处理矩阵间隙。