我正在尝试快速图像阈值函数。目前我做的是:
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::at
和cv::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
在这里,差距是从一行到另一行,你正在采取指针到单行,所以你不需要处理矩阵差距。