我正在尝试制作快速图像阈值功能。目前我所做的是:
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()
功能很慢。如何更快地设置输出,或者换句话说如何将从输入到输出的指针关联起来?
答案 0 :(得分:1)
您正在考虑at
,因为C ++标准库会为几个容器记录它,执行范围检查并在超出范围时抛出,但这不是标准库,而是OpenCV。
根据cv::Mat::at文档:
模板方法返回对指定数组元素的引用。 为了获得更高的性能,索引范围检查仅在调试配置中执行。
因此您可能没有考虑范围检查。
比较源代码中的cv::Mat::at
和cv::Mat::ptr
,我们可以看到它们几乎相同。
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
,这些差距是从一行到另一行,你是指向一行,所以你不需要处理矩阵间隙。