首页 > 编程知识 正文

matlab数值计算实验报告,kalman滤波基础及matlab仿真pdf

时间:2023-05-06 19:37:23 阅读:22104 作者:2361

JohnCanny在1986年提出了Canny运算符。 这类似于模糊项链(LoG )边缘检测方法,也是平滑后求导数的方法。 基于上述边缘检测过程介绍了Canny检测算法的原理。 结合实验,了解了canny算法,指出了参数选择中容易出现的问题。

canny边缘检测共有四个部分:

1 .用高斯滤波器平滑图像(图像去噪)

2.1用阶偏导有限差分计算梯度幅度和方向; (特征增强)

3 .对梯度振幅进行非极大值抑制(边缘检测)

4 .用双阈值算法检测边缘并连接。 (形态学处理)

去噪canny边缘检测的前两步相对不复杂,所以我直接调用了系统函数。

im=imread(2.TIF ); im=imnoise(im; %imnoise在uint8类型中为0-255,e在双精度类型中为0-1,[m,n]=size(im ); im=double(im; %高斯滤波器w=fspecial('Gaussian ',[9]; img=imfilter(im,w,'复制'; 值得注意的是,在选择了滤波器窗口w时,根据我的实验(在没有噪声的情况下的实验中,如果有噪声,也影响之后的非极大值抑制),在滤波器窗口w的边的长度为偶数的情况下,所获得的梯度仅为单像素最大振幅值另一方面,在边缘分析中,由于应产生2像素的梯度振幅符合实际情况,所以滤波器窗口w的选择必须是基数边长。

以下是示例。 如果选择偶数边的长度,则振幅如下

基数边长时,振幅的结果如下

振幅%%sobel边缘检测w_h=[1、2、1; 0,0,0; -1、-2、-1]; %Sobel运算符,梯度方向朝上正img_h=imfilter(img,w_h,' replicate ' ); %坡度为纵边,即横边w_w=[-1、0、1; - 2,0,2; - 1,0,1; %Sobel运算符,梯度方向向右为正img_w=imfilter(img,w_w,' replicate ' ); %梯度为横向边缘,即纵向边缘img_grad=sqrt(img_w.^2img_h.^2); %坡度的绝对值grad_max=max(max(img_grad ); img_grad=img_grad/grad_max; %规范化阈值选择阈值用于后续的边缘连接处理。 高阈值表示强边缘,低阈值表示弱边缘。 OpenCV要求手动选择阈值。 在Matlab中,阈值是基于梯度振幅直方图选择的,默认情况下,振幅大小前70%的最后一个振幅被选择为高阈值,低阈值与高阈值的比率为4:10。 在我的程序中,因为需要检测强边缘,所以直方图的比率设定得很高。

另外,设定强边缘的阈值后,不需要包含所有边缘,只要弱边缘具有“点状”的分布即可,然后根据与弱边缘的8连通域的状况得到有效的边缘。 另外,如果对得到的强边缘进行打开操作和关闭操作,则去噪效果好,但在相同的操作中不能对弱边缘使用。

弱边缘图像:

强边缘图像:

代码如下。

k=1.2; percentofpixelsnotedges=1- k * (Mn )/(m * n ); %0.995; %强边缘的比例ThresholdRatio=0.52; %强弱边缘的比例thresh=[ ]; 根据ifisempty(thresh ) %直方图自动计算高低阈值大小counts=imhist ) img_grad,256的highthresh=find(cumsum(counts ) percentond %PercentOfPixelsNotEdges=0.8,即非边界比例low thresh=threshold ratio * high thresh; thresh=[lowThresh highThresh]; ElseifLength(thresh )==1 highThresh=thresh; ifthresh=1error (message (images : edge : thresholdmustbelessthanone ) ) endlowthresh=threshold ratio * thresh; thresh=[lowThresh highThresh]; ElseifLength(thresh )==2 lowThresh=thresh(1) ) 1; 高thresh=thresh (2; if(lowthresh=highthresh(|) highthresh=1) error ) message (' images 3360 edge 3360 thresholdoutofrange ' )结尾非最大值在这种情况下,非最大值抑制所进行比较

的相邻两个像素就是:

1) 0:左边 和 右边
2)45:右上 和 左下
3)90: 上边 和 下边
4)135: 左上 和 右下

这样做的好处是简单, 但是这种简化的方法无法达到最好的效果, 因为,自然图像中的边缘梯度方向不一定是沿着这四个方向的。因此,就有很大的必要进行插值,找出在一个像素点上最能吻合其所在梯度方向的两侧的像素值。

非极大值抑制是canny算法的精髓,对此理解不深的同学,可以参考(http://blog.csdn.net/kezunhai/article/details/11620357) 这里的解释,解释得非常到位。

值得一提的是,为了在噪声中得到真实的双像素边缘,可以在非极大值抑制时不选取最大值为1,只要大小为周围最大值的80%即可。

代码如下:

%%下面是非极大值抑制weak_edge2=zeros(m+2,n+2);img_grad2 = padarray(img_grad,[1 1],'replicate'); %为了计算边界上的点,要扩充一下img_h2 = padarray(img_h,[1 1],'replicate');img_w2 = padarray(img_w,[1 1],'replicate');for i=2:m+1 % 图像边缘的像素不能计算 for j=2:n+1 if img_grad2(i,j)<=lowThresh M1=2; M2=2;%这时检测点肯定是不大于1的,故isbigger=0 else %img_grad(i,j)~=0 Mx=img_w2(i,j);%梯度是横着的 My=img_h2(i,j);%梯度是竖着的 if abs(My)>=abs(Mx) %y方向梯度比x方向梯度大,梯度方向“竖着”的情况 g1=img_grad2(i-1,j);%g1是检测点正上方一行 g3=img_grad2(i+1,j);%g3是检测点正下方一行 weight=(abs(Mx)/abs(My)); if Mx*My>=0 %x,y方向梯度同号,梯度线分布在第1、3象限,当Mx*My==0时,Mx=0,weight=0 g2=img_grad2(i-1,j+1);%g2是检测点上右方 g4=img_grad2(i+1,j-1);%g4是检测点下左方 end if Mx*My<0 %x,y方向梯度异号,梯度线分布在第2、4象限 g2=img_grad2(i-1,j-1);%g2是检测点上左方 g4=img_grad2(i+1,j+1);%g4是检测点下右方 end M1=g1*(1-weight)+g2*weight;%M1是上方的插值 M2=g3*(1-weight)+g4*weight;%M2是下方的插值 end if abs(My)<abs(Mx)%x方向梯度比y方向梯度大,梯度方向“横着”的情况 g1=img_grad2(i,j+1);%g1是检测点正右方 g3=img_grad2(i,j-1);%g3是检测点正左方 weight=(abs(My)/abs(Mx)); if Mx*My>=0 %x,y方向梯度同号,梯度线分布在第1、3象限 g2=img_grad2(i-1,j+1);%g2是检测点上右方 g4=img_grad2(i+1,j-1);%g4是检测点下左方 end if Mx*My<0 %x,y方向梯度异号,梯度线分布在第2、4象限 g2=img_grad2(i+1,j+1);%g2是检测点下右方 g4=img_grad2(i-1,j-1);%g4是检测点上左方 end M1=g1*(1-weight)+g2*weight;%M1是上方的插值 M2=g3*(1-weight)+g4*weight;%M2是下方的插值 end end %此处选择与经典canny不同,考虑到噪声干扰,为了找到“双线边缘”,假定误差不超过0.9的都同为最大值 %也可根据加入噪声水平确定该值 isbigger=(img_grad2(i,j)>=(0.8*M1))&&(img_grad2(i,j)>=(0.8*M2)); %如果当前点比两边点都大,则置为白色 if isbigger weak_edge2(i,j)=255; end endendweak_edge=weak_edge2(2:m+1,2:n+1);figure(1);imshow(weak_edge)[rstrong,cstrong] = find(img_grad>highThresh & weak_edge);strong_edge=zeros(m,n);for i=1:length(rstrong) r=rstrong(i); c=cstrong(i); strong_edge(r,c)=weak_edge(r,c);endse=strel('square',2);strong_edge=imopen(strong_edge,se);se=strel('square',3);strong_edge=imclose(strong_edge,se);figure(2);imshow(strong_edge) 形态学处理

最后,以强边缘为种子,在弱边缘中寻找其8连通域,作为边缘即可。

原图:

canny算法检测到的边界:

代码如下
[rstrong,cstrong] = find(strong_edge);
edge = bwselect(weak_edge, cstrong, rstrong, 8);

在Matlab “edge()”函数中,最后还做了一个形态学瘦化处理,edge= bwmorph(edge, ‘thin’, 1); 但是我觉得得到的边缘已经足够细了,双像素边缘在之后对边缘区域的操作中也会更加有用。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。