数字图像处理,自适应中值滤波的C++实现

自适应中值滤波的原理

     自适应中值滤波的思想是根据噪声密度改变滤波窗口的大小,同时对噪声点和信号点采取不同的处理方法。对噪声点进行中值滤波,对信号点保持其灰度值不变。

       设为fij为点(i,j)的灰度值,Sij为当前工作窗口,fmin,fmax和fmed分别为Sij中的灰度最小值、灰度最大值和灰度中值,令maxize为预设的允许最大窗口。自适应中值滤波的步骤如下:

1)若 fmin< fmed <fmax,则转至第2步;否则增大窗口的尺寸。若的尺寸小于的尺寸,则重复第1步;否则输出。

2)若 fmin< fij <fmax,则输出fij;否则输出fmed

可以看出,算法中噪声的检测和认定时以 fmin fmax为基准的,如果 fmin< fmed <fmax,表明fmed 不是噪声,

接着根据fmin< fij <fmax判断fij 是否为噪声,当fmedfij 都不是脉冲噪声时,优先输出fij

引入自适应中值滤波算法主要有3 个目的: 

一是去除脉冲噪声;

二是平滑其他非脉冲噪声;

三是减少诸如物体边界细化或粗化等失真。

自适应中值滤波的流程图如下图所示。



参考代码:

/自适应中值滤波/
int adp_media_filter(unsigned char* inbuffer,int width,int height,int maxwinsize,unsigned char* outbuffer)
{
	int pos = (maxwinsize - 1) / 2;
	memcpy(outbuffer,inbuffer,width*height);       
	for (int m = pos; m < height - pos; m++)//当前中心位置(m,n)
	{
		for (int n = pos; n < width - pos; n++)
		{
			int curwinsize = 3;     //设置初始滤波窗口大小
			while (curwinsize <= maxwinsize)
			{
				int curpos = (curwinsize - 1) / 2;
				int winpos = 0;
				int lens = curwinsize*curwinsize;
				int* windows = new int[lens];
				for (int i = -curpos; i < curpos + 1; i++)
					for (int j = -curpos; j < curpos + 1; j++)
						windows[winpos++] = inbuffer[(m + i)*width + n + j];
				
				sort(windows, lens);
				int fmin = windows[0];
				int fmax = windows[lens - 1];
				int fmed = windows[(lens - 1) / 2];
				int A1 = fmed - fmin;
				int A2 = fmed - fmax;
				if (A1 > 0 && A2 < 0)//第一层噪声检测,fmed是不是噪声
				{
					//满足fmin< fmed < fmax,表明fmed不是噪声
					int B1 = inbuffer[m*width + n] - fmin;//当前窗口中心值inbuffer[m*width + n]
					int B2 = inbuffer[m*width + n] - fmax;
					//满足fmin< fmn < fmax,表明fmn不是噪声
					if (B1 > 0 && B2 < 0)//第二层检测,fmn是不是噪声
						outbuffer[m*width + n] = inbuffer[m*width + n];//fmn和fmed都不是噪声优先输出当前窗口中心值
					else
						outbuffer[m*width + n] = fmed;//fmn是噪声,输出中间值重新估计该点
					delete[] windows;
					windows = NULL;
					break;
				}
				curwinsize += 2;
				delete[] windows;
				windows = NULL;
			}
		}
	}
	//对边界进行处理,与中值滤波一样
	for (int k = 0;k < pos;k++)
		for (int l =pos;l < width-pos;l++)
			outbuffer[k*width+l] = outbuffer[pos*width+l];
	for(int a=height-pos;a < height;a++)
		for(int b=pos;b < width-pos;b++)
			outbuffer[a*width+b] = outbuffer[(height-pos-1)*width+b];
	for(int c = 0;c < pos;c++)
		for(int d=0;d < height;d++)
			outbuffer[d*width+c] = outbuffer[d*width+pos];
	for (int e = width-pos;e < width;e++)
		for(int f = 0;f < height;f++)
			outbuffer[f*width+e] = outbuffer[f*width+width-pos-1];

	return 0;	
}


实验结果:

以下所有结果均为C++处理。
1,对原图像进行处理的结果(左为原图)
可以发现,自适应中值滤波对图像边缘的保护相当好


2,对乘性噪声图像进行处理的结果(左为噪声图)

注意该噪声为matlab中的乘性噪声,可以发现对乘性噪声的处理效果相当差。



3,对椒盐噪声图像进行处理的结果(左为噪声图)

注意该噪声为matlab中的椒盐噪声,可以发现对椒盐噪声的处理效果优秀。



最后在此处收录一份别人写的matlab程序:

function f = adpmedian(g, Smax)
%ADPMEDIAN Perform adaptive median filtering.
%   F = ADPMEDIAN(G, SMAX) performs adaptive median filtering of
%   image G.  The median filter starts at size 3-by-3 and iterates up
%   to size SMAX-by-SMAX. SMAX must be an odd integer greater than 1.

%   Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins
%   Digital Image Processing Using MATLAB, Prentice-Hall, 2004
%   $Revision: 1.5 $  $Date: 2003/11/21 14:19:05 $

% SMAX must be an odd, positive integer greater than 1.
if (Smax <= 1) | (Smax/2 == round(Smax/2)) | (Smax ~= round(Smax))
   error('SMAX must be an odd integer > 1.')
end
[M, N] = size(g);

% Initial setup.
f = g;
f(:) = 0;
alreadyProcessed = false(size(g));

% Begin filtering.
for k = 3:2:Smax
   zmin = ordfilt2(g, 1, ones(k, k), 'symmetric');
   zmax = ordfilt2(g, k * k, ones(k, k), 'symmetric');
   zmed = medfilt2(g, [k k], 'symmetric');
   
   processUsingLevelB = (zmed > zmin) & (zmax > zmed) & ...
       ~alreadyProcessed; 
   zB = (g > zmin) & (zmax > g);
   outputZxy  = processUsingLevelB & zB;
   outputZmed = processUsingLevelB & ~zB;
   f(outputZxy) = g(outputZxy);
   f(outputZmed) = zmed(outputZmed);
   
   alreadyProcessed = alreadyProcessed | processUsingLevelB;
   if all(alreadyProcessed(:))
      break;
   end
end

% Output zmed for any remaining unprocessed pixels. Note that this
% zmed was computed using a window of size Smax-by-Smax, which is
% the final value of k in the loop.
f(~alreadyProcessed) = zmed(~alreadyProcessed);




参考资源:

【1】自适应中值滤波算法在图像处理中的应用,刘 颖,陈谨女,长安大学电子与控制工程工程学院
【2】一种改进的自适应中值滤波方法,卫保国,西北工业大学电子信息学院,2008

  • 5
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个使用C语言编写的自适应中值滤波程序: ```c #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 256 void adaptive_median_filter(int** image, int** result, int width, int height, int window_size, int max_window_size); void main() { int i, j; int** image; int** result; int width, height; int window_size, max_window_size; // 读取图像 FILE* fp; fp = fopen("lena.raw", "rb"); if (fp == NULL) { printf("Could not open file\n"); exit(0); } width = height = MAX_SIZE; image = (int**)malloc(height * sizeof(int*)); result = (int**)malloc(height * sizeof(int*)); for (i = 0; i < height; i++) { image[i] = (int*)malloc(width * sizeof(int)); result[i] = (int*)malloc(width * sizeof(int)); fread(image[i], sizeof(int), width, fp); } fclose(fp); // 执行自适应中值滤波 window_size = 3; max_window_size = 7; adaptive_median_filter(image, result, width, height, window_size, max_window_size); // 保存图像 fp = fopen("lena_filtered.raw", "wb"); for (i = 0; i < height; i++) { fwrite(result[i], sizeof(int), width, fp); } fclose(fp); // 释放内存 for (i = 0; i < height; i++) { free(image[i]); free(result[i]); } free(image); free(result); } void adaptive_median_filter(int** image, int** result, int width, int height, int window_size, int max_window_size) { int i, j, k, l, m, n, p; int med, zmin, zmax, zmed, zxy; int window[MAX_SIZE * MAX_SIZE]; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { // 获取当前窗口大小 int size = window_size; while (size <= max_window_size) { // 构造窗口 int cx = j - size / 2; int cy = i - size / 2; int count = 0; for (k = 0; k < size; k++) { for (l = 0; l < size; l++) { if (cx + l >= 0 && cx + l < width && cy + k >= 0 && cy + k < height) { window[count++] = image[cy + k][cx + l]; } } } // 求中值和最小最大值 med = window[count / 2]; zmin = window[0]; zmax = window[count - 1]; zmed = 0; for (k = 0; k < count; k++) { if (window[k] > zmin && window[k] < zmax) { zmed = window[k]; break; } } // 判断当前像素是否为脉冲噪声 if (zmed > zmin && zmed < zmax) { zxy = image[i][j]; if (zxy > zmin && zxy < zmax) { result[i][j] = zxy; } else { result[i][j] = zmed; } break; } // 将窗口扩大一格 size += 2; } // 如果窗口大小已经达到最大值,直接取中值 if (size > max_window_size) { result[i][j] = med; } } } } ``` 该程序读取一幅灰度图像(文件名为lena.raw),并执行自适应中值滤波,将滤波结果保存为lena_filtered.raw。程序中的窗口大小从3开始逐渐扩大,直到达到最大值为止。如果当前像素被判断为脉冲噪声,则直接使用原始像素值或中值进行替换。如果窗口大小已经达到最大值,直接使用中值进行替换。 注意,这里假设图像的像素值为整数类型,如果是浮点数类型需要做一些修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值