图像增强-中值滤波
中值滤波是一种典型的非线性滤波技术。它在一定条件下可以克服线性滤波器如最小均方滤波,均值滤波等带来的图像细节模糊,而且对滤波脉冲干扰及图像扫描噪声非常有效。
传统的中值滤波一般采用含有奇数个点的滑动窗口,用窗口中各点灰度值的中值来替代指定点的灰度值。对于奇数个元素,中值为大小排序后中间的数值;对于偶数个元素,中值为排序后中间两个元素灰度值的平均值。
中值滤波是一种典型的低通滤波器,主要用来抑制脉冲噪声,它能彻底滤除尖波干扰噪声,同时又具有能较好地保护目标图像边缘的特点。
标准一维中值滤波器的定义为:
yk = med{ xK-N, xk-N+1, ... ,xk, ... ,xK+N }
式中,med表示取中值操作。中值滤波的滤波方法是对滑动滤波窗口(2N+1)内的像素做大小排序,滤波结果的输出像素值规定为该序列的中值。
二维中值滤波的窗口形状和尺寸设计对滤波的效果影响较大,不同的图像内容和不同的应用要求,往往采用不同的形状和尺寸。常用的二维中值滤波窗口有线状,方形,圆形,十字形及圆环形等,窗口尺寸一般选为3。当然也可以采用其他尺寸,主要视具体情况而定。
1.中值的计算关键在于对滑动窗口内的像素进行排序,排序算法的选择是影响中值滤波算法的重要因素。传统的排序算法是基于冒泡排序法,若窗口中的像素为m,则每个窗口排序需要m(m-2)/2次像素的比较操作,时间复杂度为O(m2)。此外常规的滤波算法每移动一次窗口就要进行一次排序。当一幅图像的大小为NXN时,则整个计算需要O(m2N2)时间,当窗口较大时,计算量很大,较费时。
2.为了提高中值滤波的实现速度,针对3X3中值滤波,介绍一种快速的并行中值滤波方法。下图为3X3窗口内像素排列
首先对窗口内的每一列分别计算最大值,中值和最小值,这样就得到了3组数据
最大值组:Max0 = max[P0,P3,P6],Max1 = max[P1,P4,P7],Max2 = max[P2,P5,P8]
中值组: Med0 = med[P0,P3,P6],Med1 = med[P1,P4,P7], Med2 = med[P2,P5,P8]
最小值组:Min0 = Min[P0,P3,P6],Min1 = Min[P1,P4,P7],Min2 = max[P2,P5,P8]
由此可以看到,最大值组中的最大值与最小值组中的最小值一定是9个元素中的最大值和最小值,不可能为中值,剩下7个;中值组中的最大值至少大于5个像素,中值组中的最小值至少小于5个像素,不可能为中值,剩下5个;最大值组中的中值至少大于5个元素,最小值组中的中值至少小于5个元素,不可能为中值,最后剩下3个要比较的元素,即
最大值组中的最小值Maxmin,中值组中的中值Medmed,最小值组中的最大值MinMax;找出这三个值中的中值为9个元素的中值。
算法实现:
/********************************************************************** * * 函数名称: * MedFilter(int FilterH, int FilterW, int FilterCX, int FilterCY) * * 参数: * int FilterH 模板的高度 * int FilterW 模板的宽度 * int FilterCX 模板的中心元素X坐标 ( < FilterW - 1) * int FilterCY 模板的中心元素Y坐标 ( < FilterH - 1) * * 返回值: * void * * 说明: * 中值滤波的算法 * **********************************************************************/ void CImgEnhance::MedianFilter(int FilterH, int FilterW, int FilterCX, int FilterCY) { unsigned char* pSrc; unsigned char* pDst; int i,j,k,l; unsigned char* value; //指向滤波器数组的指针 if(m_pImgDataOut != NULL) { delete []m_pImgDataOut; m_pImgDataOut = NULL; } //计算图像每行的字节数 int lineByte = (m_imgWidth * m_nBitCount / 8 + 3) / 4 * 4; if(m_nBitCount != 8) { AfxMessageBox("只能处理8位灰度图像!"); return ; } //分配内存,以保存新图像 m_nBitCountOut = m_nBitCount; int lineByteOut = (m_imgWidth * m_nBitCountOut / 8 + 3) / 4 * 4; if (!m_pImgDataOut) { //为处理后的图像分配内存空间 m_pImgDataOut = new unsigned char[lineByteOut * m_imgHeight]; } int pixelByte = m_nBitCountOut / 8; for(i = 0; i < m_imgHeight; i++){ for(j = 0; j < m_imgWidth * pixelByte; j++) *(m_pImgDataOut + i * lineByteOut +j) = *(m_pImgData + i * lineByteOut + j); } //暂时分配内存,以保存滤波器数组 value = new unsigned char[FilterH * FilterW]; for (i = FilterCY; i < m_imgHeight - FilterH ; i++)//+ FilterCY + 1 { for (j = FilterCX; j < m_imgWidth - FilterW ; j++)//+ FilterCX + 1 { pDst = m_pImgDataOut + lineByte * (m_imgHeight - 1 - i) + j; for (k = 0; k < FilterH; k++) { for (l = 0; l < FilterW; l++) { pSrc = m_pImgData + lineByte * (m_imgHeight - l - i + FilterCY - k) + j - FilterCX + l; value[k * FilterW + l] = *pSrc; } } *pDst = FindMedianValue(value,FilterW * FilterH); } } }
posted on 2012-07-21 12:18 NotValid 阅读(22962) 评论(1) 编辑 收藏 举报