中值滤波器.docx
《中值滤波器.docx》由会员分享,可在线阅读,更多相关《中值滤波器.docx(13页珍藏版)》请在冰豆网上搜索。
中值滤波器
中值滤波器.txt让人想念而死,是谋杀的至高境界,就连法医也鉴定不出死因。
。
。
。
。
。
帽泡排序法的汇编实现。
。
movcx,count;CX←数组元素个数
deccx;元素个数减1为外循环次数
outlp:
movdx,cx;DX←内循环次数
movbx,offsetarray
inlp:
moval,[bx];取前一个元素
cmpal,[bx+1];与后一个元素比较
jnanext
xchgal,[bx+1];否则,进行交换
mov[bx],al
next:
incbx;下一对元素
decdx
jnzinlp;内循环尾
loopoutlp;外循环尾
2、中值滤波
中值滤汉是对某一参数连续输入N次(一般N取奇数),从中选择一个中间值作为本次采样值,若变量变化比较缓慢,采用此方法效果比较好,但对快速变化过程的参数,如流量、自然伽玛等,则不宜采用。
中值滤波的C程序函数如下:
floatmiddle_filter(floatmiddle_value[],intcount)
{
floatsample_value,data;
inti,j;
for(i=1;ifor(j=count-1;j>=i,--j){
if(middle_value[j-1]=middle_value[j]{
data=middle_value[j-1];
middle_value[j-1]=middle_value[j]
middle_value[j]=data;
}
}
sample_value=middle_value(count-1)/2];
return(sample_value);
}
函数假设对某一参数连续采样3次,若多次采样,可对该函数稍作修改即可。
3次采样值存储在数组middle_value[3],其中Sample-value表示有效采样值,count表示连续采样次数。
FILTER3:
MOVR2,#04H
SRT:
MOVA,R2
MOVR3,A
MOVR0,#SAMP
LOOP:
MOVA,@R0
INCR0
MOVR1,A
CLRC
SUBBA,@R0
MOVA,R1
JCDONE
MOVA,@R0
DECR0
XCHA,@R0
INCR0
MOV@R0,A
DONE:
DJNZR3,LOOP
DJNZR2.,SORT
INCR0
MOVA,@R0
RET
SAMPEQU30H
用汇编实现冒泡排序的函数
;参数说明:
_lpData是待排序的数组首地址,_dwCount是待排序的个数,_dwOption设为0则由小到大排序
;如果是非0值,则是由大到小排序.
;返回值:
已排序数据放回原数组中.
;作者:
ONEPROBLEM
;=================================================
_BubblingSortproc_lpData,_dwCount,_dwOption
local@dwCount
pushad
movedi,1
.whileedi<_dwCount
movesi,_lpData
moveax,_dwCount
mov@dwCount,eax
sub@dwCount,edi
movebx,1
.whileebx<=@dwCount
moveax,[esi]
.ifeax<[esi+4]&&_dwOption==0
jmpnext
.elseifeax>[esi+4]&&_dwOption==0
jmpcontinue
.elseifeax<[esi+4]&&_dwOption!
=0
jmpcontinue
.elseifeax>[esi+4]&&_dwOption!
=0
jmpnext
.endif
continue:
moveax,[esi]
movedx,[esi+4]
mov[esi],edx
mov[esi+4],eax
next:
addesi,4
incebx
.endw
incedi
.endw
popad
ret
_BubblingSortendp
DSEGSEGMENT
nequ10
BUFFERDB9,11,2,7,21,13,2,0,14,3
DSEGENDS
CSEGSEGMENT
assumecs:
CSEG,ds:
DSEG
MAINPROCFAR;主程序入口
movax,dseg
movds,ax
movcx,n
deccx
loop1:
movdi,cx
movbx,0
loop2:
moval,buffer[bx]
cmpal,buffer[bx+1]
jgecontinue
xchgal,buffer[bx+1]
movbuffer[bx],al
continue:
addbx,1
looploop2
movcx,di
looploop1
movah,1;按任意键退出
int21h
movax,4c00h;程序结束,返回到操作系统系统
int21h
MAINENDP
CSEGENDS
ENDMAIN
中值滤波原理
中值滤波是一种非线性平滑法,它对一个滑动窗口内的像素灰度值排序,并用其中值代替窗口中心像素的灰度值.对脉冲干扰及椒盐噪声具有良好的抑制作用,并且在抑制随机噪声的同时能有效保护边缘少受模糊.二维中值滤波的窗口形状有多种,如线状、方形、十字形、圆形、菱形等.不同形状的窗口产生不同的滤波效果.通过研究,不少文献认为十字中值滤波的效果优于方形的中值滤波,而且十字中值滤波也有不同的形式以形成不同的滤波特性,其数据可从方形数据获得.最常使用的十字中值滤波是对五个相邻像素进行排序,以确定中心点的数值.
I=[17181711
11151111
11555117
11555181
81151111
81151151
11151111
17181711
];
[MN]=size(I);
I1=zeros(M,N);
fori=2:
M-1
forj=2:
N-1
temp=I(i-1:
i+1,j-1:
j+1);
temp=sort(temp);
temp=sort(temp');
I1(i,j)=temp(2,2);
end
end
imshow(I,[]);
figure,imshow(I1,[]);
中值滤波器属于非线性空间滤波器,用于除去图像中的椒盐噪声。
中值滤波器只适用于灰度RGB图像(对于YUV图像,应该只需要对Y进行处理),一个有趣现象:
对于彩色RGB图像进行中值滤波,得到的输出接近于灰色图像。
中值滤波的算法核心就是找出中间值。
对于一个3x3的块,只需要找的这样一个值:
1)有4个比它小;2)有4个比它大。
而不需要进行泡沫排序。
对于图像的边界,一般有两种处理方法:
边界扩展和不处理。
为了跟具有普遍性,此IP不考虑边界问题。
中值滤波器的主要开销在于linebuffer,通常linebuffer需要存储图像的一行像素。
对于3x3块的滤波,就需要两个linebuffer,这对于大尺寸图像是一笔很大的开销。
我认为,对于这个问题有两种解决办法:
1)和其它模块共享buffer,实际限制会比较多,也会影响系统的工作频率;2)把大图像分成小块来处理,这样做IO接口的设计会比较复杂,对于带宽也有一定影响。
本文的IP为Slave模式,输入为8bit,支持断续传输。
实际应用中,需要设计一个IOinterface。
使用了6级流水线,处理速度可以达到1pixel/cycle。
作为一个IP,这个设计可能没有太多价值,毕竟实际情况千差万别。
但是,我想,作为一个学习的例子还是有一些意义的,这个设计流程已经很接近工程项目了。
算法实现起来比较简单,总共花费约5个工作日。
第一天:
找资料;
第二天:
写DesignSpec,并实现;
第三天:
写cmodel,建立仿真环境;
第四天:
debug;
第五天:
整理。
整个工程包括:
RTL,testbanch,cmodel,DesignSpec和测试向量。
要求仿真工具支持verilog2001。
这里对验证环境多说一些,严格来讲,这个只能算是仿真,验证的话需要给出functioncoverage和codecoverage报告。
因为是没有薪水的工作,所以就不愿意做这些琐碎的事情了。
凭我的直觉说应该不会有问题(千万不要对自己的老板这么说,而且bug往往出现在设计者认为不会出bug的地方)。
找Bug的工作就交给大家了:
)。
对于仿真结果的比较,不知道为什么很多人都习惯用testbanchdumpresultfile,然后和参考数据作比较。
个人觉得这种方法非常不好,我习惯用monitor做实时比较。
到了2001版本,verilog的文件操作已经做到和c一样强大了。
在这个testbanch里,激励和比对文件都是二机制的。
另外一个比较重要的东西就是cmodel了,一般在公司里都是由算法工程师给出来的(我请不起他们只有自己写了),个人认为cmodel不会对RTL的实现有所帮助(我从来不看他们的程序,而且我的设计都是和cmodel同步完成的),但是对于debug起着事半功倍的作用。
一个好的cmodel可以给出debug所需要的所有信息。
关于滤波器的实现没有太多难点,这里用的是脉动阵列结构,保证数据在你期望的时间到达就可以了。
有一些信号是根据时序凑出来的,不要深究其逻辑意义。
基本上基于算法的设计都遵循以下流程:
先实现数据通路,然后根据数据通路来凑出控制信号.
通常我看code和波形都是在debussy下面,如果你不是,应该向我学习,因为aisc工程师都是这么做的!
如果你是想学习而不是拿来用的话,我建议还是自己实现的好。
网络上的资源:
该文件内容放在.m文件中才能调用!
!
!
%中值滤波函数,X为输入矩阵,a,b为中值滤波的框大小。
%效率很低,可以用来说明中值滤波的概念。
%Y为uint8数据类型,以便用imshow画图,否则,可以改为其它和X相同的类型。
%medianforfun.m
function[Y]=medianforfun(X,a,b)
k=floor(a*b/2)+1;%k为矩阵数值中间位置的数
[M,N]=size(X);
uint8Y=zeros(M,N);
funBox=zeros(a,b);
temp=zeros(a*b);
fori=1:
M-a%matlab的坐标从(1,1)开始
forj=1:
N-b
funBox=X(i:
i+a,j:
j+b);
temp=funBox(:
);%A(:
)矩阵A以一维数组的形式输出
tempSort=sort(temp);%sort()是从小到大排列
Y(i,j)=tempSort(k);
end;
end;
调用函数:
I=imread('eight.tif');
J=imnoise(I,'salt%26amp;pepper',0.02);
K=medfilt2(J);
imshow(J),figure,imshow(K)
Z=medianforfun(J,2,2);
figure,imshow(Z)
2.
原版修改(效果更好):
function[Y]=V0(X,a,b)
k=floor(a*b/2)+1;%k为矩阵数值中间位置的数
[M,N]=size(X);
uint8Y=zeros(M,N);
funBox=zeros(a,b);
p=0;
temp=zeros(a*b);%a*b的方阵
fori=1:
M-a%matlab的坐标从(1,1)开始
forj=1:
N-b
funBox=X(i:
i+a-1,j:
j+b-1);
temp=funBox(:
);%A(:
)矩阵A以一维数组的形式输出
tempSort=sort(temp);%sort()是从小到大排列
p1=i+floor(a/2)+1;
p2=j+floor(a/2)+1;
Y(p1,p2)=tempSort(k);%找到邻接矩阵排列数的中值赋值给模板的中心点
end;
end;
调用函数:
tic;
In=imread('D:
\sp.jpg');%用P=isind('D:
\sp.png')测试,发现此图片为索引图像
I=rgb2gray(In);%那为何使用rgb2gray能转换,ind2gray却不能呢?
?
?
imhist(I);
J=imnoise(I,'salt%26amp;pepper',0.08);
%K=medfilt2(J);
imshow(J);
%figure,imshow(K)
Z=V0(J,3,3);%模板为3*3的矩阵,矩阵越大,计算量越大
figure,imshow(Z)
toc
说明:
计算程序运行时间的方式:
tic;
程序;
toc
(2)
matlab自带的中值滤波函数:
medfilt2()
判断图像文件的类型:
In=imread('D:
\sp.png');
P=isind('D:
\sp.png')
P=isrgb('D:
\sp.png')
效果如下:
图片处理前图片处理后
3.
改进版(在原版修改基础上):
传统的中值滤波中“中值”一般取“中位数”,即所有元素排序后中间位置上的元素值。
但是排序需要移动大量元素,效率较低。
个人认为,其实原版算法主要耗时的地方之一是matlab的排序函数:
sort()
说明:
耗时的原因很多!
值得改进的地方还有很多~~
基于此点,可以改进排序函数,快速排序算法是我的首选,但是不是平常意义的那种快速排序,是经过改良的快速排序。
因为它每轮移动的数字都是最后排好序的最终位置,并且,我只是为了找中值,所以不需要真的去排序。
只要在有一轮排序中,一个数字被放在中心位置,那么该数就是所要找的中值。
最终的排序虽然没有完成,但中值已找到,所以循环就可以停止了!
!
但仍需要移动元素位置。
貌似还是很耗时!
!
!
!
暂时我只能改进到这样的情况了,尽力了~!
1.快速排序法(matlab版)
%快速排序法
%基本的思想:
通过一趟排序将待排的记录分割成独立的两部分,
%其中前一部分的记录的关键字均比另一部分记录的关键字小,
%再分别对两组记录进行递归分割,达到排序的目的
%平均时间复杂度为O(log2(n))
function[data]=qsort_main(A)
data=A;low=1;high=9;
data=QSort(data,low,high);
%before=A(:
)
%after=data(:
)
functiondata=QSort(data,low,high)
ifnargin==1
low=1;
high=length(data);
end
if(low%26lt;high)
[datapivokey]=qPartition(data,low,high);
(3)
if(pivokey==5)%特定情况处理,如果第一个数就是中值,那么就可以停止该循环了!
return;
end
data=QSort(data,low,pivokey-1);%递归调用
data=QSort(data,pivokey+1,high);
end
%将数组分成两部分,前一部分的值均比后一部分值小
%返回分界点
function[datalow]=qPartition(data,low,high)
ifnargin==1
low=1;
hight=length(data);
end
pivokey=data(low);
whilelow%26lt;high
whilelow%26lt;high%26amp;data(high)%26gt;=pivokey
high=high-1;
end
c=data(low);d=data(high);
data(low)=d;data(high)=c;
whilelow%26lt;high%26amp;data(low)%26lt;=pivokey
low=low+1;
end
c=data(low);d=data(high);
data(low)=d;data(high)=c;
if(low==high%26amp;low==5)%low与high均到达中心位置!
!
!
!
!
%fprintf('ppppppppp');
return;
end
end
中值滤波函数:
function[Y]=V0(X,a,b)
k=floor(a*b/2)+1;%k为矩阵数值中间位置的数
[M,N]=size(X);
uint8Y=zeros(M,N);
funBox=zeros(a,b);
temp=zeros(a*b);%a*b的方阵
fori=1:
M-a%matlab的坐标从(1,1)开始
forj=1:
N-b
funBox=X(i:
i+a-1,j:
j+b-1);
temp=funBox(:
);%A(:
)矩阵A以一维数组的形式输出
tempSort=qsort_main(temp);%快速排序!
!
!
!
!
p1=i+floor(a/2)+1;
p2=j+floor(a/2)+1;
Y(p1,p2)=tempSort(k);%找到邻接矩阵排列数的中值赋值给模板的中心点
end;
end;
调用函数:
tic;
In=imread('D:
\sp.jpg');%用P=isind('D:
\sp.png')测试,发现此图片为索引图像
I=rgb2gray(In);%那为何使用rgb2gray能转换,ind2gray却不能呢?
?
?
imhist(I);
J=imnoise(I,'salt%26amp;pepper',0.08);
%K=medfilt2(J);
imshow(J);
%figure,imshow(K)
Z=V0(J,3,3);%模板为3*3的矩阵,矩阵越大,计算量越大
figure,imshow(Z)
toc