时间复杂度比较高的版本,每个像素点做(hor_radius * 2 + 1) * (ver_radius * 2 + 1) 次加法和1次除法
void MeanFilter(uint8* img, int width, int height, int pitch,
int hor_radius, int ver_radius) // filter size
{
uint8* temp = new uint8[height * pitch];
memcpy(temp, img, sizeof(uint8) * height * pitch);
int n = (hor_radius * 2 + 1) * (ver_radius * 2 + 1);
for(int ver = ver_radius; ver < height - ver_radius; ++ver) {
for(int hor = hor_radius; hor < width - hor_radius; ++hor) {
int sum = 0;
for(int row = ver - ver_radius; row <= ver + ver_radius; ++row) {
for(int col = hor - hor_radius; col <= hor + hor_radius; ++col) {
sum += temp[row * pitch + col];
}
}
img[ver * pitch + hor] = sum / n;
}
}
delete [] temp;
}
无论滤波器的尺寸多大,平均每个像素点只做4次加减法,1次除法
void FastMeanFilter(uint8* img, int width, int height, int pitch,
int hor_radius, int ver_radius) // filter size
{
uint8* temp = new uint8[(height + 1) * pitch];
memset(temp, 0, pitch);
uint8* srcp = temp + pitch;
memcpy(srcp, img, sizeof(uint8) * height * pitch);
int* buf = new int[width+1];
memset((void*)buf, 0, sizeof(int) * (width + 1) );
int* bufp = buf + 1;
int filter_width = hor_radius * 2 + 1;
int filter_height = ver_radius * 2 + 1;
int n = filter_width * filter_height;
uint8* dstp = img + ver_radius * pitch + hor_radius;
int inc = pitch - width;
int offset = filter_height * pitch;
// 计算图像最上面的filter_height-1行中,每一列的像素值之和
int ver, hor;
for(ver = 0; ver < filter_height - 1; ++ver) {
for(hor = 0; hor < width; ++hor) {
*bufp += *srcp++;
bufp++;
}
srcp += inc;
}
for(; ver < height; ++ver) {
int blk_sum = 0;
bufp = buf + 1;
for(hor = 0; hor < filter_width - 1; ++hor) {
*bufp += *srcp - *(srcp - offset);
blk_sum += *bufp;
++srcp;
++bufp;
}
for(; hor < width; ++hor) {
// 加上最下行的像素值,减去最上行的像素值,得到列像素值的和
*bufp += *srcp - *(srcp - offset);
// 加上最右边列的像素值和,减去最左边列的像素值和,得到块的和
blk_sum += *bufp - *(bufp - filter_width);
*dstp++ = blk_sum / n;
++srcp;
++bufp;
}
srcp += inc;
dstp += inc + filter_width - 1;
}
delete [] buf;
delete [] temp;
}