我的程序中有以下代码功能
template <typename _Tp>
void lbp::OLBP_(const Mat& src, Mat& dst) {
assert(src.rows > 3);
dst = Mat::zeros(src.rows-2, src.cols-2, CV_8UC1);
_Tp
*row_m1,
*row = (_Tp*)src.ptr<_Tp>(0),
*row_p1 = (_Tp*)src.ptr<_Tp>(1);
for(int i=1; i<src.rows-1; i++) {
unsigned char *dst_row = dst.ptr<unsigned char>(i-1);
row_m1 = row;
row = row_p1;
row_p1 = (_Tp*)src.ptr<_Tp>(i+1);
for(int j=1;j<src.cols-1;j++) {
_Tp center = row[j];
unsigned char code = 0;
code |= (row_m1 [j-1] > center) << 7;
code |= (row_m1 [j] > center) << 6;
code |= (row_m1 [j+1] > center) << 5;
code |= (row [j+1] > center) << 4;
code |= (row_p1 [j+1] > center) << 3;
code |= (row_p1 [j] > center) << 2;
code |= (row_p1 [j-1] > center) << 1;
code |= (row [j-1] > center) << 0;
dst_row[j-1] = code;
}
}
}
基本上它的作用是,src
中的每个像素都会在dst
中生成代码。该“代码”是二进制数,其中8位中的每一位对应于8个像素的邻居中的每一个,如果邻居大于中心的像素,则为1
,否则为0
。 (参见维基百科中的Local Binary Patterns)
代码工作正常,并且会被调用很多次。运行一个分析器我发现大部分执行时间花在这个特定的函数上,特别是在我访问像素值的行上:
//The code is templated but it should compile to something similar to this
unsigned char *pointer = src.ptr<unsigned char>(row); // THIS CONSUMES MOST OF THE TIME!
pointer[column]; // get the actual pixel value
像素的访问方式还有改进的余地吗? 我对这样的场景特别感兴趣,其中函数需要随机访问图像而不是连续的情况。
答案 0 :(得分:1)
事实上,是。将数据写入Mat::ptr
图像时,您可以避免调用dst
:
...
for(int i=1; i<src.rows-1; i++) {
unsigned char *dst_row = dst.ptr<unsigned char>(i-1); << THIS CAN BE AVOIDED
...
您可以在创建数据缓冲区之后简单地初始化指向数据缓冲区的指针,然后在不调用dst
的情况下填充它,即:
ptr
如果dst = Mat::zeros(src.rows-2, src.cols-2, CV_8UC1);
unsigned char *dst_data = dst.data;
int pix_ctr = 0;
// .. and then, inside the `for` loop, after calculating the LBP code.
dst_data[pix_ctr++] = code;
中存储的数据连续,则可以 (在这种情况下,您知道它,因为您刚刚通过调用{{}来初始化它1}})。您可以致电dst
来查看。
(事实上,如果Mat::zeros
中的输入数据是连续的,你可以摆脱循环中的{strong>全部 dst.isContinuous()
。在这种情况下,推进你的像素指针没有Mat::ptr
使用图片尺寸。)