- 椒盐噪声简介:椒(pepper)即表示图像中某像素处的值为0(黑色),盐(salt)即表示图像中某像素处的值为255(白色);
- 产生椒盐噪声的思路:
- 产生两个随机数(xPosition和yPosition),用来在图像中该坐标处添加椒盐点;
- 产生一个随机数,用来决定在1中的坐标点上添加椒点还是盐点;
- 注意事项:产生椒盐噪声的椒盐个数和椒盐颗粒的大小均需要通过参数设置,并且本程序是给灰度图片添加噪声。
代码如下:
int peppersalt(unsigned char* buffer, int w, int h, int count, int size)
{
int xPosition;
int yPosition;
int psNoise;
if (count == 0)
count = w*h;
if (size == 0)
size = 1;
while (count)
{
xPosition = rand() % (w - size + 1);//产生随机的要设置噪声的像素点x坐标
yPosition = rand() % (h - size + 1);//产生随机的要设置噪声的像素点y坐标
psNoise = rand() % 2;//随机设置该点作为盐点或椒点
if (psNoise)
{// 产生盐点
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
buffer[(yPosition+i)*w + xPosition+j] = 255;
}
}
}
else
{// 产生椒点
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
buffer[(yPosition+i)*w + xPosition+j] = 0;
}
}
}
count = count - 1;
}
return 0;
}
处理效果:
中值滤波去除椒盐噪声:
原理简介:
1:通过从 图像中的某个 采样窗口取出奇数个数据进行排序
2: 用排序后的中值取代要处理的数据即可
中值滤波的算法实现过程,重点是排序,最常用的冒泡排序
把滤波区间的数据从小到大进行排序,然后取中值,(如果是奇数个数据,那么中值就只有一个了,如果偶数个数据,中值有两个,可以对两个数据再求平均)
int GetMedianNum(int* buf, int num)
{
int i, j;// 循环变量
unsigned char bTemp;
// 用冒泡法对数组进行排序
for (j = 0; j < num - 1; j++)
{
for (i = 0; i < num - j - 1; i++)
{
if (buf[i] > buf[i + 1])
{
// 互换
bTemp = buf[i];
buf[i] = buf[i + 1];
buf[i + 1] = bTemp;
}
}
}
// 计算中值
if ((num & 1) > 0)
{
// 数组有奇数个元素,返回中间一个元素
bTemp = buf[((num + 1) / 2)-1];
}
else
{
// 数组有偶数个元素,返回中间两个元素平均值
bTemp = (buf[(num / 2)-1] + buf[(num / 2 + 1)-1]) / 2;
}
return bTemp;
}
int image_medianfilter(unsigned char* buffer, int w, int h, int size)
{
int rows2 = size / 2;
int cols2 = size / 2;
int index = 0;
int index2 = 0;
int total = size * size;
int* matrix = (int*)malloc(sizeof(int)*total);
unsigned char* tmp_buf = (unsigned char*)malloc(sizeof(unsigned char)*w*h);
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
int count = 0;
for (int row = -rows2; row <= rows2; row++)
{
int rowoffset = y + row;
if (rowoffset < 0 || rowoffset >= h) //边缘扩充用最近的像素值代替
{
rowoffset = y;
}
for (int col = -cols2; col <= cols2; col++)
{
int coloffset = col + x;
if (coloffset < 0 || coloffset >= w) //边缘扩充用最近的像素值代替
{
coloffset = x;
}
index2 = rowoffset * w + coloffset;
matrix[count] = buffer[index2];
count++;
}
}
tmp_buf[index++] = GetMedianNum(matrix, count);
}
}
memcpy(buffer, tmp_buf, sizeof(unsigned char)*w*h);
free(matrix);
free(tmp_buf);
return 0;
}
处理效果对比: