# 普通均值滤波

R是卷积核半径

image

1）设定一个均值区域，一般定义滤波半径R，半径越大越模糊

2）逐次移动坐标，求该区域内的所有像素的平均值

```//std mean filter
/**
* srcData：原图数据
* destData：存放处理结果的图片数据
* width：图片宽
* height：图片高度
* stride：图片一行的步幅(>= width)
*/

#define MIN2(a, b) ((a) < (b) ? (a) : (b))
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
#define CLIP3(x, a, b) MIN2(MAX2(a,x), b)

int MeanFilter(unsigned char *srcData, unsigned char* destData, int width, int height, int stride, int radius)
{
int ret = 0;
return ret;
int offset = stride - width * 4;

unsigned char* destData = (unsigned char*)malloc(sizeof(unsigned char) * height * stride);

int M = (radius * 2 + 1) * (radius * 2 + 1);
int sumr = 0, sumg = 0, sumb = 0;
for(int j = 0; j < height; j++)
{
for(int i = 0; i < width; i++)
{
sumr = sumg = sumb = 0;
{
{
// 注意图片的边界处，坐标会溢出，需要校正
int ny = CLIP3(j + n, 0, height - 1);
int nx = CLIP3(i + m, 0, width - 1);
int pos = nx * 4 + ny * stride;
sumb += srcData[pos];
sumg += srcData[pos + 1];
sumr += srcData[pos + 2];
}
}
destData[0] = sumb / M;
destData[1] = sumg / M;
destData[2] = sumr / M;
destData += 4;
}
destData += offset;
}

return ret;
};```

y轴移动原理相同。

```//Fast mean filter based histagram computation
int FastMeanFilter(unsigned char* srcData, unsigned char* dstData, int width, int height ,int stride, int radius)
{
int ret = 0;
return ret;
radius = (MIN2(width, height) / 2-0.5);

memset(dstData, 255, sizeof(unsigned char) * height * stride);
int unit = 4, t = 0, t1 = 0;
int i,j,k,len = width * height * unit;
int block = (radius << 1) + 1;
int winSize = block * block;
long sumB = 0, sumG = 0,sumR = 0;
unsigned char* pSrc = srcData;
int* temp = (int*)malloc(sizeof(int)* width * unit);
memset(temp,0,sizeof(int) * width * unit);
// 一次性求出第一行像素周边的和，存在temp中，
// 后面随着y值移动，不断更新temp值
// 设radius = 2, 求出 -2 -1 0 1 2 五行颜色的和，存储在temp中
{
for(j = 0; j< width; j++)
{
t = j * unit;
// 小于0在图片外面，没有值，对称映射到图片里面来取值
t1 = abs(k) * stride;
temp[t] += pSrc[t + t1];
temp[t + 1] += pSrc[t + 1 + t1];
temp[t + 2] += pSrc[t + 2 + t1];
}
}
// 开始从第一行扫描，沿y方向迭代
for (i = 0; i < height; i++)
{
sumB = sumG = sumR = 0;
// 求出坐标每一行第一个点的卷积
// -2 -1处的值不存在，取绝对值，映射成2 和 1出的值
{
// j < 0时，图片的左边没有值，映射到图片的右边来取值，这里也可以取(0,y)处的值，不一定要abs(j)
t = abs(j) * unit;
sumB += temp[t];
sumG += temp[t + 1];
sumR += temp[t + 2];
}
// 计算每一行的卷积平均值
for (j = 0; j < width; j++)
{
// 计算i行j列处的平均值
t = j * unit + i * stride;
dstData[t] = (sumB / winSize);
dstData[t + 1] = (sumG / winSize);
dstData[t + 2] = (sumR / winSize);

// sumRGB用完一次，往前推进一个像素，这个if是为了减少最后一次计算，最后一次不用算了
if (j < width - 1)
{
t = abs(j - radius) * unit;
t1 = (j + radius + 1) % width * unit;
sumB = sumB - temp[t] + temp[t1];
sumG = sumG - temp[t + 1] + temp[t1 + 1];
sumR = sumR - temp[t + 2] + temp[t1 + 2];
}
}

// 这个if是为了减少最后一次计算，减去卷积核
if (i < height - 1)
{
for (k = 0; k < width; k++)
{
t = k * unit + abs(i - radius) * stride;  // 卷积核第一行(注意abs绝对值，是应对边缘处的像素，映射到正值处的位置，增加容错)
t1 = k * unit + (i + radius + 1) % height * stride;  // 紧邻卷积核的下一行
temp[k * unit] = temp[k * unit] - pSrc[t] + pSrc[t1];
temp[k * unit + 1] = temp[k * unit + 1] - pSrc[t + 1] + pSrc[t1 + 1];
temp[k * unit + 2] = temp[k * unit + 2] - pSrc[t + 2] + pSrc[t1 + 2];
}
}
}
free(temp);
return ret;
};```

0 条评论

• ### 15.opengl高级-混合

纹理缓和的计算也不复杂，根据alpha通道值做叠加或减除融合，详细可参考opengl-混合

• ### 照片处理-阿宝色滤镜

阿宝色是一位摄影师名为阿宝(网名：aibao)，原名董立竑，由他在2008年左右所创的一种特别的色彩。这种色彩主要是，橘色的肤色和偏青色的背景色调为主，整体的视...

• ### 25.opengl高级光照-Gamma校正

简单理解：人对光强度的感知是非线性的。亮度的范围如果是[0,1]，0是黑色，1是纯白色，那么0.5应该代表的是中间灰色吗？NO!!人能感知到的中间灰度值是亮度为...

• ### 3(文件IO,不带缓冲的IO)

成功则返回文件描述符，失败则返回-1 第三个参数写成/*mode_t mode */ 表示这个参数仅在创建新文件时使用 Pathname表示要打开或者创...

• ### 什么是文件格式？

有了之前 4 篇对文件的操作工具之后，终于到了文件格式的介绍部分！本文介绍文件格式的定义，并实现一个自己的文件格式。这个文件格式十分简单，只用来说明原理。

• ### 北斗对时装置（NTP时钟服务器）助力政务云建设

以宣城“智慧城市”建设总体思路为指导，建设政务云计算中心，实现统一建设、统一管理、统一使用，为智慧城市和全市各部门的业务应用系统提供统一的机房空间、网络资源、存...

• ### 栅格化系统的原理以及实现

在一个有限的、固定的平面上，用水平线和垂直线（虚拟的线，“参考线”），将平面划分成有规律的一系列“格子”（虚拟的格子），并依托这些格子、或以格子的边线为基准线，...

• ### 3分钟理解响应式布局

总听别人说响应式布局，觉得是一个很高大上的东西，近日做的一个项目需要适配不同的屏幕尺寸，于是就简单研究了一下 Web响应式布局，其实原理很简单，下面就简单整理了...