1、什么是中值检测?
中值混合就是对一个滑动窗口中像素的灰度值进行排序,将窗口中心像素的原始灰度值替换为中值。果汁噪声抑制效果好,在抑制随机噪声的同时能有效保护边缘不模糊。
中值混合可以过滤尖峰。目的是我们对混合数据更感兴趣。混合数据保留了原始图像的趋势,同时不仅消除了尖峰对分析的影响。
以一维信号的中值混合为例。对于灰度序列 80、120、90、200、100、110、70,如果按照大小顺序排列,则结果为70、80、90、10O,110、120、200,中间位置灰度值为10O,则灰度序列的中位数为100。一维信号中位数混合实际上是将指定位置(通常是原始信号序列的中心位置)的信号值替换为中值。对于上面的序列,中位数混合的结果是将序列 80、120、90、200、100、替换为中位数 100 的中心位置值@>110、70 中的信号序列为 200,得到的检测序列为80、120、90、100、100、110、70。如果200是该序列中的噪声信号,则可以通过这种方式消除该噪声点。
二维中值检测算法是:对图像的像素矩阵,取一个以目标像素为中心的子矩阵窗口。对像素灰度进行排序,取中间值作为目标像素的新灰度值。比如在ooooxoooo的窗口中,x为目标像素,与周围的o组成一个3*3的矩阵Array,然后对这9个元素的灰度进行排序,取排序后的中间元素Array[4]为x 的新灰度值,这样就完成了像素 x 的中值检测,然后迭代检测其他需要的像素。
图像处理中中值混合的实现
1:通过从图像中的采样窗口中获取素数数据进行排序
2:将要处理的数据替换为排序后的中位数
中位数混合的算法实现过程,重点是排序,最常用的冒泡排序~~
将混合区间内的数据从小到大排序c语言实现图像处理,然后取中值,(如果是素数数据,则只有一个中值,如果有素数数据c语言实现图像处理,则有两个中值, 可以对这两个数据重新排序平均)
下面是一个用C语言实现中位数混合的函数:
unsigned char GetMedianNum(int * bArray, int iFilterLen) { int i,j;// 循环变量 unsigned char bTemp; // 用冒泡法对数组进行排序 for (j = 0; j < iFilterLen - 1; j ++) { for (i = 0; i bArray[i + 1]) { // 互换 bTemp = bArray[i]; bArray[i] = bArray[i + 1]; bArray[i + 1] = bTemp; } } } // 计算中值 if ((iFilterLen & 1) > 0) { // 数组有奇数个元素,返回中间一个元素 bTemp = bArray[(iFilterLen + 1) / 2]; } else { // 数组有偶数个元素,返回中间两个元素平均值 bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2; } return bTemp; }
注:bArray 是一个整形指针,我们传入的一般是一个数组,用来存储待排序的数据
iFilterLen 是滤波器的长度
用在图像处理中时,由于像素的取值范围是0~255,刚好是unsigned char 的范围,所以函数的返回值是unsigned char,如果我们要处理的数是float型,或其他类型,返回值也可以更改~~返回值是bTemp,也即是我们想得到的中值
下面是一个完整的C语言程序,用在图像处理中
/*************************************************************************
* 函数名称:
* MedianFilter()
* 参数:
* int iFilterH - 滤波器的高度
* int iFilterW - 滤波器的宽度
* int iFilterMX - 滤波器的中心元素X坐标
* int iFilterMY - 滤波器的中心元素Y坐标
* 说明:
* 该函数对DIB图像进行中值滤波。
************************************************************************/
#define iFilterW 1
#define iFilterH 1
#define iFilterMX 1
#define iFilterMY 1
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
unsigned char GetMedianNum(int * bArray, int iFilterLen);
void MedianFilter(unsigned char *pImg1,unsigned char *pImg,int nWidth,int nHeight)
{
unsigned char *lpSrc; // 指向源图像的指针
unsigned char *lpDst; // 指向要复制区域的指针
int aValue[iFilterH*iFilterW]; // 指向滤波器数组的指针
int i,j,k,l; // 循环变量
int lLineBytes; // 图像每行的字节数
lLineBytes = WIDTHBYTES(nWidth * 8);
for ( i=0;i<nWidth;i++,pImg++ )
(*pImg)=0;
// 开始中值滤波
// 行(除去边缘几行)
for(i = iFilterMY; i < nHeight - iFilterH + iFilterMY + 1; i++)
{
// 列(除去边缘几列)
for(j = iFilterMX; j < nWidth - iFilterW + iFilterMX + 1; j++)
{
// 指向新DIB第i行,第j个象素的指针
lpDst = pImg + lLineBytes * (nHeight - 1 - i) + j;
// 读取滤波器数组
for (k = 0; k < iFilterH; k++)
{
for (l = 0; l < iFilterW; l++)
{
// 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针
lpSrc = pImg1 + lLineBytes * (nHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l;
// 保存象素值
aValue[k * iFilterW + l] = *lpSrc;
}
}
// 获取中值
* lpDst = GetMedianNum(aValue, iFilterH * iFilterW);
}
}
}
unsigned char GetMedianNum(int * bArray, int iFilterLen)
{
int i,j; // 循环变量
unsigned char bTemp;
// 用冒泡法对数组进行排序
for (j = 0; j < iFilterLen - 1; j ++)
{
for (i = 0; i bArray[i + 1])
{
// 互换
bTemp = bArray[i];
bArray[i] = bArray[i + 1];
bArray[i + 1] = bTemp;
}
}
}
// 计算中值
if ((iFilterLen & 1) > 0)
{
// 数组有奇数个元素,返回中间一个元素
bTemp = bArray[(iFilterLen + 1) / 2];
}
else
{
// 数组有偶数个元素,返回中间两个元素平均值
bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
}
return bTemp;
}
发表评论