canny算子代码
- 格式:doc
- 大小:51.00 KB
- 文档页数:12
canny边缘检测matlab代码Canny边缘检测是一种常用的图像处理算法,它可以有效地检测图像中的边缘,并将其显示为白色线条。
在Matlab中,可以使用以下代码实现Canny边缘检测:1. 读取图像首先,需要读取待处理的图像。
可以使用imread函数来读取图片:```matlabimg = imread('image.jpg');```其中,image.jpg是待处理的图片文件名。
2. 灰度化Canny算法只能处理灰度图像,因此需要将彩色图像转换为灰度图像。
可以使用rgb2gray函数来实现:```matlabgray_img = rgb2gray(img);```3. 高斯滤波在进行边缘检测之前,需要对图像进行高斯滤波来消除噪声。
可以使用fspecial和imfilter函数来实现:```matlabgaussian_filter = fspecial('gaussian', [5 5], 1);blur_img = imfilter(gray_img, gaussian_filter, 'replicate');```其中,[5 5]表示高斯核的大小为5x5,1表示标准差。
4. 计算梯度幅值和方向接下来,需要计算每个像素点的梯度幅值和方向。
可以使用Sobel算子来计算梯度,并利用arctan函数计算方向角度:```matlabsobel_x = [-1 0 1; -2 0 2; -1 0 1];sobel_y = [-1 -2 -1; 0 0 0; 1 2 1];grad_x = imfilter(blur_img, sobel_x, 'replicate');grad_y = imfilter(blur_img, sobel_y, 'replicate');grad_mag = sqrt(grad_x.^2 + grad_y.^2);grad_dir = atan(grad_y ./ grad_x);```5. 非极大值抑制由于Sobel算子计算出的梯度幅值可能会有多个峰值,因此需要进行非极大值抑制来保留边缘。
一、编写程序完成不同滤波器的图像频域降噪和边缘增强的算法并进行比较,得出结论。
1、不同滤波器的频域降噪1.1 理想低通滤波器(ILPF)I1=imread('eight.tif'); %读取图像I2=im2double(I1);I3=imnoise(I2,'gaussian',0.01);I4=imnoise(I3,'salt & pepper',0.01);figure,subplot(1,3,1);imshow(I2) %显示灰度图像title('原始图像'); %为图像添加标题subplot(1,3,2);imshow(I4) %加入混合躁声后显示图像title('加噪后的图像');s=fftshift(fft2(I4)); %将灰度图像的二维不连续Fourier 变换的零频率成分移到频谱的中心[M,N]=size(s); %分别返回s的行数到M中,列数到N中n1=floor(M/2); %对M/2进行取整n2=floor(N/2); %对N/2进行取整d0=40; %初始化d0for i=1:Mfor j=1:Nd=sqrt((i-n1)^2+(j-n2)^2); %点(i,j)到傅立叶变换中心的距离 if d<=d0 %点(i,j)在通带内的情况h=1; %通带变换函数else %点(i,j)在阻带内的情况h=0; %阻带变换函数ends(i,j)=h*s(i,j); %ILPF滤波后的频域表示endends=ifftshift(s); %对s进行反FFT移动s=im2uint8(real(ifft2(s))); %对s进行二维反离散的Fourier变换后,取复数的实部转化为无符号8位整数subplot(1,3,3); %创建图形图像对象imshow(s); %显示ILPF滤波后的图像title('ILPF滤波后的图像(d=40)');运行结果:1.2 二阶巴特沃斯低通滤波器(BLPF)I1=imread('eight.tif'); %读取图像I2=im2double(I1);I3=imnoise(I2,'gaussian',0.01);I4=imnoise(I3,'salt & pepper',0.01);figure,subplot(1,3,1);imshow(I2) %显示灰度图像title('原始图像'); %为图像添加标题subplot(1,3,2);imshow(I4) %加入混合躁声后显示图像title('加噪后的图像');s=fftshift(fft2(I4));%将灰度图像的二维不连续Fourier 变换的零频率成分移到频谱的中心[M,N]=size(s); %分别返回s的行数到M中,列数到N中n=2; %对n赋初值n1=floor(M/2); %对M/2进行取整n2=floor(N/2); %对N/2进行取整d0=40; %初始化d0for i=1:Mfor j=1:Nd=sqrt((i-n1)^2+(j-n2)^2); %点(i,j)到傅立叶变换中心的距离 h=1/(1+(d/d0)^(2*n)); %BLPF滤波函数s(i,j)=h*s(i,j); %ILPF滤波后的频域表示endends=ifftshift(s); %对s进行反FFT移动s=im2uint8(real(ifft2(s))); %对s进行二维反离散的Fourier变换后,取复数的实部转化为无符号8位整数subplot(1,3,3); %创建图形图像对象imshow(s); %显示ILPF滤波后的图像title('BLPF滤波后的图像(d=40)');实验结果:1.3 指数型低通滤波器(ELPF)I1=imread('eight.tif'); %读取图像I2=im2double(I1);I3=imnoise(I2,'gaussian',0.01);I4=imnoise(I3,'salt & pepper',0.01);figure,subplot(1,3,1);imshow(I2) %显示灰度图像title('原始图像'); %为图像添加标题subplot(1,3,2);imshow(I4) %加入混合躁声后显示图像title('加噪后的图像');s=fftshift(fft2(I4));%将灰度图像的二维不连续Fourier 变换的零频率成分移到频谱的中心[M,N]=size(s); %分别返回s的行数到M中,列数到N中n1=floor(M/2); %对M/2进行取整n2=floor(N/2); %对N/2进行取整d0=40;for i=1:Mfor j=1:Nd=sqrt((i-n1)^2+(j-n2)^2); %点(i,j)到傅立叶变换中心的距离 h=exp(log(1/sqrt(2))*(d/d0)^2);s(i,j)=h*s(i,j); %ILPF滤波后的频域表示endends=ifftshift(s); %对s进行反FFT移动s=im2uint8(real(ifft2(s))); %对s进行二维反离散的Fourier变换后,取复数的实部转化为无符号8位整数subplot(1,3,3); %创建图形图像对象imshow(s); %显示ILPF滤波后的图像title('ELPF滤波后的图像(d=40)');运行结果:1.4 梯形低通滤波器(TLPF)I1=imread('eight.tif'); %读取图像I2=im2double(I1);I3=imnoise(I2,'gaussian',0.01);I4=imnoise(I3,'salt & pepper',0.01);figure,subplot(1,3,1);imshow(I2) %显示灰度图像title('原始图像'); %为图像添加标题subplot(1,3,2);imshow(I4) %加入混合躁声后显示图像title('加噪后的图像');s=fftshift(fft2(I4));%将灰度图像的二维不连续Fourier 变换的零频率成分移到频谱的中心[M,N]=size(s); %分别返回s的行数到M中,列数到N中n1=floor(M/2); %对M/2进行取整n2=floor(N/2); %对N/2进行取整d0=10;d1=160;for i=1:Mfor j=1:Nd=sqrt((i-n1)^2+(j-n2)^2); %点(i,j)到傅立叶变换中心的距离 if (d<=d0)h=1;else if (d0<=d1)h=(d-d1)/(d0-d1);else h=0;endends(i,j)=h*s(i,j); %ILPF滤波后的频域表示endends=ifftshift(s); %对s进行反FFT移动s=im2uint8(real(ifft2(s))); %对s进行二维反离散的Fourier变换后,取复数的实部转化为无符号8位整数subplot(1,3,3); %创建图形图像对象imshow(s); %显示ILPF滤波后的图像title('TLPF滤波后的图像'); %为图像添加标题运行结果:1.5 高斯低通滤波器(GLPF)I1=imread('eight.tif'); %读取图像I2=im2double(I1);I3=imnoise(I2,'gaussian',0.01);I4=imnoise(I3,'salt & pepper',0.01);figure,subplot(1,3,1);imshow(I2) %显示灰度图像title('原始图像'); %为图像添加标题subplot(1,3,2);imshow(I4) %加入混合躁声后显示图像title('加噪后的图像');s=fftshift(fft2(I4));%将灰度图像的二维不连续Fourier 变换的零频率成分移到频谱的中心[M,N]=size(s); %分别返回s的行数到M中,列数到N中n1=floor(M/2); %对M/2进行取整n2=floor(N/2); %对N/2进行取整d0=40;for i=1:Mfor j=1:Nd=sqrt((i-n1)^2+(j-n2)^2); %点(i,j)到傅立叶变换中心的距离 h=1*exp(-1/2*(d^2/d0^2)); %GLPF滤波函数s(i,j)=h*s(i,j); %ILPF滤波后的频域表示endends=ifftshift(s); %对s进行反FFT移动s=im2uint8(real(ifft2(s))); %对s进行二维反离散的Fourier变换后,取复数的实部转化为无符号8位整数subplot(1,3,3); %创建图形图像对象imshow(s); %显示ILPF滤波后的图像title('GLPF滤波后的图像(d=40)');运行结果:1.6 维纳滤波器[B,Cmap]=imread('eight.tif'); %读取MATLAB中的名为eight的图像I1=im2double(B);I2=imnoise(I1,'gaussian',0.01);I3=imnoise(I2,'salt & pepper',0.01);figure,subplot(1,3,1);imshow(I1) %显示灰度图像title('原始图像'); %为图像添加标题subplot(1,3,2);imshow(I3) %加入混合躁声后显示图像title('加噪后的图像');I4=wiener2(I3);subplot(1,3,3);imshow(I4); %显示wiener滤波后的图像title('wiener滤波后的图像');运行结果:结论:理想低通滤波器,虽然有陡峭的截止频率,却不能产生良好的效果,图像由于高频分量的滤除而变得模糊,同时还产生振铃效应。
Canny算子提取边缘Matlab源代码介绍function e=canny_edge(I,sigma)%functione=edge(I,'canny',thresh,sigma);%该函数实现Canny算子提取边缘点%输入图像为I,标准差sigma,输出为边缘图像e[m,n]=size(I);Rr=2:m-1;cc=2:n-1;e=repmat(logical(uint8(0)),m,n);%产生同样大小的边缘图像e,初始化为1 ,即初始化边缘GaussianDieOff=-0.001;%设定高斯函数消失门限PercentOfPixelsNotEdges=-7;%用于计算边缘门限ThresholdRatio=-4;%设置两个门限的比例%首先设计高斯滤波器和它的微分pw=1:30;%设定滤波器宽度ssq=sigma*sigma;%计算方差width=max(find(exp(-(pw.*pw)/(2*sigma*sigma))>GaussianDieOff)); %计算滤波算子宽度t=(-width:width);len=2*width+1;t3=[t-.5;t;t+.5];%对每个像素左右各半个像素位置的值进行平均gau=sum(exp(-(t3.*t3)/(2*ssq))).'/(6*pi*ssq);%一维高斯滤波器dgau=(-t.*exp(-(t.*t)/(2*ssq))/ssq).';%高斯滤波器的微分ra=size(I,1);ca=size(I,2);ay=255*double(I);ax=255*double(I');h=conv(gau,dgau);%利用高斯函数滤除噪声和用高斯算子的一阶微分对图像滤波合并为一个算子ax=conv2(ax,h,'same').';%产生x方向滤波ay=conv2(ay,h,'same');%产生y方向滤波mag=sqrt((ax.*ax)+(ay.*ay));%计算滤波结果的幅度magmax=max(mag(:));if magmax>0mag=mag/magmax;%对滤波幅度进行归一化end%下面根据滤波幅度的概率密度计算滤波门限[counts,x]=imhist(mag,64);%计算滤波结果的幅度的直方图highThresh=min(find(cumsum(counts)>PercentOfPixelsNotEdges*m*n))/64; %通过设定非边缘点的比例来确定高门限lowThresh=ThresholdRatio*highThresh;%设置低门限为高门限乘以比例因子thresh=[lowThresh,highThresh];%下面进行非极大抑制%大于高门限的点归于强边缘图像%小于低门限的点归于弱边缘图像idxStrong=[];for dir=1:4idxLocalMax=cannyFindLocalMaxima(dir,ax,ay,mag); idxWeak=idxLocalMax(mag(idxLocalMax)>lowThresh);e(idxWeak)=1;idxStrong=[idxStrong;idxWeak(mag(idxWeak)>highThresh)]; endrstrong=rem(idxStrong-1,m)+1;%rem是求余数cstrong=floor((idxStrong-1)/m)+1;%向-∞取整e=bwselect(e,cstrong,rstrong,8);%通过形态学算子将两幅图像的边缘进行连接(资料素材和资料部分来自网络,供参考。
附录Part1:对cameraman原始图像处理的仿真程序:clcclear allclose allA = imread('cameraman.bmp'); % 读入图像subplot(2,4,1);imshow(A);title('原图');x_mask = [1 0;0 -1]; % 建立X方向的模板y_mask = rot90(x_mask); % 建立Y方向的模板I = im2double(A); % 将图像数据转化为双精度dx = imfilter(I, x_mask); % 计算X方向的梯度分量dy = imfilter(I, y_mask); % 计算Y方向的梯度分量grad = sqrt(dx.*dx + dy.*dy); % 计算梯度grad = mat2gray(grad); % 将梯度矩阵转换为灰度图像level = graythresh(grad); % 计算灰度阈值BW = im2bw(grad,level); % 用阈值分割梯度图像subplot(2,4,2);imshow(BW); % 显示分割后的图像即边缘图像title('Roberts');y_mask = [-1 -2 -1;0 0 0;1 2 1];x_mask = y_mask';I = im2double(A);dx = imfilter(I, x_mask);dy = imfilter(I, y_mask);grad = sqrt(dx.*dx + dy.*dy); % 计算梯度grad = mat2gray(grad);level = graythresh(grad);BW = im2bw(grad,level);subplot(2,4,3);imshow(BW); % 显示分割后的图像即边缘图像title('Sobel');y_mask = [-1 -1 -1;0 0 0;1 1 1];x_mask = y_mask';dx = imfilter(I, x_mask);dy = imfilter(I, y_mask);grad = sqrt(dx.*dx + dy.*dy); % 计算梯度grad = mat2gray(grad);level = graythresh(grad);BW = im2bw(grad,level); % 用阈值分割梯度图像subplot(2,4,4);imshow(BW); % 显示分割后的图像即边缘图像title('Prewitt');mask=[0,-1,0;-1,4,-1;0,-1,0]; % 建立模板dx = imfilter(I, mask); % 计算梯度矩阵grad = mat2gray(dx); % 将梯度矩阵转化为灰度图像BW = im2bw(grad,0.58); % 用阈值分割梯度图像subplot(2,4,5);imshow(BW); % 显示分割后的图像,即梯度图像title('Laplacian');mask=[0,0,-1,0,0;0,-1,-2,-1,0;-1,-2,16,-2,-1;0,-1,-2,-1,0;0,0,-1,0,0]; % 建立模板dx = imfilter(I, mask); % 计算梯度矩阵grad = mat2gray(dx); % 将梯度矩阵转化为灰度图像BW = im2bw(grad,0.58);subplot(2,4,6);imshow(BW); % 显示分割后的图像,即梯度图像title('log');BW1 = edge(I,'canny'); % 调用canny函数subplot(2,4,7);imshow(BW1); % 显示分割后的图像,即梯度图像title('Canny');mask1=[-1 -2 -1;0 0 0;1 2 1]; % 建立方向模板mask2=[-2 -1 0;-1 0 1;0 1 2];mask3=[-1 0 1;-2 0 2;-1 0 1];mask4=[0 1 2;-1 0 1;-2 -1 0];mask5=[1 2 1;0 0 0;-1 -2 -1];mask6=[2 1 0;1 0 -1;0 -1 -2];mask7=[1 0 -1;2 0 -2;1 0 -1];mask8=[0 -1 -2;1 0 -1;2 1 0];d1 = imfilter(I, mask1); % 计算8个领域的灰度变化d2 = imfilter(I, mask2);d3 = imfilter(I, mask3);d4 = imfilter(I, mask4);d5 = imfilter(I, mask5);d6 = imfilter(I, mask6);d7 = imfilter(I, mask7);d8 = imfilter(I, mask8);dd = max(abs(d1),abs(d2)); % 取差值变化最大的元素组成灰度变化矩阵dd = max(dd,abs(d3));dd = max(dd,abs(d4));dd = max(dd,abs(d5));dd = max(dd,abs(d6));dd = max(dd,abs(d7));dd = max(dd,abs(d8));grad = mat2gray(dd); % 将灰度变化矩阵转化为灰度图像BB = grad;FW=median(BB(:))/0.6745;B = BB.*BB;B = sum(B(:));FX= sqrt(B/256^2);FS=sqrt(max(FX^2-FW^2,0));T=sqrt(2)*FW^2/FS; % 计算最佳阈值grad = mat2gray(BB);BW2=im2bw(grad,T); % 用最佳阈值分割梯度图像subplot(2,4,8);imshow(BW2); % 显示分割后的图像,即边缘图像title('sobel改进算子');Part2加入高斯噪声后的cameraman仿真程序:clcclear allclose allA = imread('cameraman.bmp'); % 读入图像V=0.009;X=imnoise(A,'gaussian',0,V);subplot(2,4,1);imshow(X);%添加均值为0、方差0.09的高斯噪声x_mask = [1 0;0 -1]; % 创建X方向的模板y_mask = rot90(x_mask); % 创建Y方向的模板I = im2double(X); % 图像数据双精度转化dx = imfilter(I, x_mask); % X方向的梯度分量的计算dy = imfilter(I, y_mask); % Y方向的梯度分量的计算grad = sqrt(dx.*dx + dy.*dy); % 梯度计算grad = mat2gray(grad); % 梯度矩阵转换成灰度图像level = graythresh(grad); % 计算灰度阈值BW = im2bw(grad,level); % 使用阈值分割梯度图像subplot(2,4,2);imshow(BW); % 显示分割后的图像即边缘图像title('Roberts');y_mask = [-1 -2 -1;0 0 0;1 2 1];x_mask = y_mask';dx = imfilter(I, x_mask);dy = imfilter(I, y_mask);grad = sqrt(dx.*dx + dy.*dy);grad = mat2gray(grad); % 梯度矩阵转为灰度图像level = graythresh(grad); % 计算灰度阈值BW = im2bw(grad,level); % 用阈值分割梯度图像subplot(2,4,3);imshow(BW); % 显示分割后的图像即边缘图像title('Sobel');y_mask = [-1 -1 -1;0 0 0;1 1 1];x_mask = y_mask';dx = imfilter(I, x_mask);dy = imfilter(I, y_mask);grad = sqrt(dx.*dx + dy.*dy);grad = mat2gray(grad);level = graythresh(grad);BW = im2bw(grad,level);subplot(2,4,4);imshow(BW); % 显示分割后的图像即边缘图像title('Prewitt');mask=[0,-1,0;-1,4,-1;0,-1,0]; % 建立模板dx = imfilter(I, mask); % 计算梯度矩阵grad = mat2gray(dx); % 将梯度矩阵转化为灰度图像BW = im2bw(grad,0.58); % 用阈值分割梯度图像subplot(2,4,5);imshow(BW); % 显示分割后的图像,即梯度图像title('Laplacian');mask=[0,0,-1,0,0;0,-1,-2,-1,0;-1,-2,16,-2,-1;0,-1,-2,-1,0;0,0,-1,0,0]; % 建立模板dx = imfilter(I, mask); % 计算梯度矩阵grad = mat2gray(dx); % 将梯度矩阵转化为灰度图像BW = im2bw(grad,0.58); % 用阈值分割梯度图像subplot(2,4,6);imshow(BW); % 显示分割后的图像,即梯度图像title('log');BW1 = edge(I,'canny'); % 调用canny函数subplot(2,4,7);imshow(BW1); % 显示分割后的图像,即梯度图像title('Canny');mask1=[-1 -2 -1;0 0 0;1 2 1]; % 建立方向模板mask2=[-2 -1 0;-1 0 1;0 1 2];mask3=[-1 0 1;-2 0 2;-1 0 1];mask4=[0 1 2;-1 0 1;-2 -1 0];mask5=[1 2 1;0 0 0;-1 -2 -1];mask6=[2 1 0;1 0 -1;0 -1 -2];mask7=[1 0 -1;2 0 -2;1 0 -1];mask8=[0 -1 -2;1 0 -1;2 1 0];d1 = imfilter(I, mask1); % 计算8个领域的灰度变化d2 = imfilter(I, mask2);d3 = imfilter(I, mask3);d4 = imfilter(I, mask4);d5 = imfilter(I, mask5);d6 = imfilter(I, mask6);d7 = imfilter(I, mask7);d8 = imfilter(I, mask8);dd = max(abs(d1),abs(d2)); % 取差值变化最大的元素组成灰度变化矩阵dd = max(dd,abs(d3));dd = max(dd,abs(d4));dd = max(dd,abs(d5));dd = max(dd,abs(d6));dd = max(dd,abs(d7));dd = max(dd,abs(d8));grad = mat2gray(dd); % 将灰度变化矩阵转化为灰度图像BB = grad;FW=median(BB(:))/0.6745;B = BB.*BB;B = sum(B(:));FX= sqrt(B/256^2);FS=sqrt(max(FX^2-FW^2,0));T=sqrt(2)*FW^2/FS; % 计算最佳阈值grad = mat2gray(BB); % 将梯度矩阵转化为灰度图像BW2=im2bw(grad,T); % 用最佳阈值分割梯度图像subplot(2,4,8);imshow(BW2); % 显示分割后的图像,即边缘图像title('sobel改进算子');加入椒盐噪声的边缘检测程序:function jingdianI=imread('lenna.bmp');I1=imnoise(I,'salt & pepper');%添加椒盐噪声,默认值为0.02 figure,imshow(I1);%添加均值为0、方差0.002的高斯噪声title('添加椒盐噪声后原图')B1=edge(I1,'roberts');B2=edge(I1,'sobel');B3=edge(I1,'prewitt');B4=edge(I1,'canny');B5=edge(I1,'log');subplot(2,3,1);imshow(B1);title('roberts算子检测');subplot(2,3,2);imshow(B2);title('sobel算子检测');subplot(2,3,3);imshow(B3);title('prewitt算子检测');subplot(2,3,4);imshow(B4);title('canny算子检测');subplot(2,3,5)imshow(B5);title('log算子检测');B1=edge(I1,'roberts');%调用roberts算子检测图像B2=edge(I1,'sobel');%调用soble算子进行边缘检测B3=edge(I1,'prewitt');%调用prewitt算子进行边缘检测B4=edge(I1,'canny');%调用canny算子对图像进行边缘检测B5=edge(I1,'log');%调用log算子对图像进行边缘检测subplot(2,3,1);%设置图像布局imshow(B1);title('roberts算子检测');%现实图像并命名为roberts算子检测subplot(2,3,2);imshow(B2);title('sobel算子检测');subplot(2,3,3);imshow(B3);title('prewitt算子检测');subplot(2,3,4);imshow(B4);title('canny算子检测');subplot(2,3,5)imshow(B5);title('log算子检测');mask1=[-1 -2 -1;0 0 0;1 2 1]; % 建立方向模板mask2=[-2 -1 0;-1 0 1;0 1 2];mask3=[-1 0 1;-2 0 2;-1 0 1];mask4=[0 1 2;-1 0 1;-2 -1 0];mask5=[1 2 1;0 0 0;-1 -2 -1];mask6=[2 1 0;1 0 -1;0 -1 -2];mask7=[1 0 -1;2 0 -2;1 0 -1];mask8=[0 -1 -2;1 0 -1;2 1 0];I = im2double(I1); % 将数据图像转化为双精度d1 = imfilter(I, mask1); % 计算8个领域的灰度变化d2 = imfilter(I, mask2);d3 = imfilter(I, mask3);d4 = imfilter(I, mask4);d5 = imfilter(I, mask5);d6 = imfilter(I, mask6);d7 = imfilter(I, mask7);d8 = imfilter(I, mask8);dd = max(abs(d1),abs(d2)); % 取差值变化最大的元素组成灰度变化矩阵dd = max(dd,abs(d3));dd = max(dd,abs(d4));dd = max(dd,abs(d5));dd = max(dd,abs(d6));dd = max(dd,abs(d7));dd = max(dd,abs(d8));grad = mat2gray(dd); % 将灰度变化矩阵转化为灰度图像level = graythresh(grad); % 计算灰度阈值BW = im2bw(grad,level); % 用阈值分割梯度图像BB = grad;FW=median(BB(:))/0.6745;B = BB.*BB;B = sum(B(:));FX= sqrt(B/256^2);FS=sqrt(max(FX^2-FW^2,0));T=sqrt(2)*FW^2/FS; % 计算最佳阈值grad = mat2gray(BB); % 将梯度矩阵转化为灰度图像BW2=im2bw(grad,T); % 用最佳阈值分割梯度图像subplot(2,3,6);imshow(BW2); % 显示分割后的图像,即边缘图像title('加入椒盐噪声的sobel改进算子');。
1、边缘检测原理及步骤在之前的博文中,作者从一维函数的跃变检测开始,循序渐进的对二维图像边缘检测的基本原理进行了通俗化的描述。
结论是:实现图像的边缘检测,就是要用离散化梯度逼近函数根据二维灰度矩阵梯度向量来寻找图像灰度矩阵的灰度跃变位置,然后在图像中将这些位置的点连起来就构成了所谓的图像边缘(图像边缘在这里是一个统称,包括了二维图像上的边缘、角点、纹理等基元图)。
在实际情况中理想的灰度阶跃及其线条边缘图像是很少见到的,同时大多数的传感器件具有低频滤波特性,这样会使得阶跃边缘变为斜坡性边缘,看起来其中的强度变化不是瞬间的,而是跨越了一定的距离。
这就使得在边缘检测中首先要进行的工作是滤波。
1)滤波:边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测器的性能。
常见的滤波方法主要有高斯滤波,即采用离散化的高斯函数产生一组归一化的高斯核(具体见“高斯滤波原理及其编程离散化实现方法”一文),然后基于高斯核函数对图像灰度矩阵的每一点进行加权求和(具体程序实现见下文)。
2)增强:增强边缘的基础是确定图像各点邻域强度的变化值。
增强算法可以将图像灰度点邻域强度值有显著变化的点凸显出来。
在具体编程实现时,可通过计算梯度幅值来确定。
3)检测:经过增强的图像,往往邻域中有很多点的梯度值比较大,而在特定的应用中,这些点并不是我们要找的边缘点,所以应该采用某种方法来对这些点进行取舍。
实际工程中,常用的方法是通过阈值化方法来检测。
2、Canny边缘检测算法原理JohnCanny于1986年提出Canny算子,它与Marr(LoG)边缘检测方法类似,也属于是先平滑后求导数的方法。
本节对根据上述的边缘检测过程对Canny检测算法的原理进行介绍。
2.1 对原始图像进行灰度化Canny算法通常处理的图像为灰度图,因此如果摄像机获取的是彩色图像,那首先就得进行灰度化。
对一幅彩色图进行灰度化,就是根据图像各个通道的采样值进行加权平均。
分享到:2012-04-24 20:42网友采纳clcclear allclose allI = imread('cameraman.tif'); % 读入图像imshow(I);title('原图')BW1 = edge(I,'canny'); % 调用canny函数figure,imshow(BW1); % 显示分割后的图像,即梯度图像title('Canny')用Lena标准检测图像,图像与代码下面注明了是哪张图像。
一、没有噪声时的检测结果 1 原始图像2 Sobel算子边缘检测3 Prewitt算子边缘检测4 Roberts算子边缘检测5 Laplace算子边缘检测6 Canny算子边缘检测二、加入高斯噪声(μ=0,σ^2=0.01)检测结果 1 原始图像2 Sobel算子边缘检测3 Prewitt算子边缘检测4 Roberts算子边缘检测5 Laplace算子边缘检测6 Canny算子边缘检测三、加入高斯噪声(μ=0,σ^2=0.02)检测结果 1 原始图像2 Sobel算子边缘检测3 Prewitt算子边缘检测4 Roberts算子边缘检测5 Laplace算子边缘检测6 Canny算子边缘检测clear all; close all;warning off all;I = imread('lena.bmp'); %%如果是其他类型图像,请先转换为灰度图%%没有噪声时的检测结果BW_sobel = edge(I,'sobel');BW_prewitt = edge(I,'prewitt');BW_roberts = edge(I,'roberts');BW_laplace = edge(I,'log');BW_canny = edge(I,'canny'); figure(1);subplot(2,3,1),imshow(I),xlabel('原始图像');subplot(2,3,2),imshow(BW_sobel),xlabel('sobel检测');subplot(2,3,3),imshow(BW_prewitt),xlabel('prewitt检测');subplot(2,3,4),imshow(BW_roberts),xlabel('roberts检测');subplot(2,3,5),imshow(BW_laplace),xlabel('laplace检测');subplot(2,3,6),imshow(BW_canny),xlabel('canny检测');%%加入高斯噪声(μ=0,σ^2=0.01)检测结果I_g1 = imnoise(I,'gaussian',0,0.01);BW_sobel = edge(I_g1,'sobel');BW_prewitt = edge(I_g1,'prewitt');BW_roberts = edge(I_g1,'roberts');BW_laplace = edge(I_g1,'log');BW_canny = edge(I_g1,'canny'); figure(2);subplot(2,3,1),imshow(I_g1),xlabel('加入高斯噪声(μ=0,σ^2=0.01)图像'); subplot(2,3,2),imshow(BW_sobel),xlabel('sobel检测');subplot(2,3,3),imshow(BW_prewitt),xlabel('prewitt检测');subplot(2,3,4),imshow(BW_roberts),xlabel('roberts检测');subplot(2,3,5),imshow(BW_laplace),xlabel('laplace检测');subplot(2,3,6),imshow(BW_canny),xlabel('canny检测');%%加入高斯噪声(μ=0,σ^2=0.02)检测结果I_g2 = imnoise(I,'gaussian',0,0.02);BW_sobel = edge(I_g2,'sobel');BW_prewitt = edge(I_g2,'prewitt');BW_roberts = edge(I_g2,'roberts');BW_laplace = edge(I_g2,'log');BW_canny = edge(I_g2,'canny'); figure(3);subplot(2,3,1),imshow(I_g2),xlabel('加入高斯噪声(μ=0,σ^2=0.02)图像'); subplot(2,3,2),imshow(BW_sobel),xlabel('sobel检测');subplot(2,3,3),imshow(BW_prewitt),xlabel('prewitt检测');subplot(2,3,4),imshow(BW_roberts),xlabel('roberts检测');subplot(2,3,5),imshow(BW_laplace),xlabel('laplace检测');subplot(2,3,6),imshow(BW_canny),xlabel('canny检测');199条建筑设计知识1. 公共建筑通常以交通、使用、辅助三种空间组成2. 美国著名建筑师沙利文提出的名言‘形式由功能而来’3. 密斯.凡.德.罗设计的巴塞罗那博览会德国馆采用的是‘自由灵活的空间组合’开创了流动空间的新概念4. 美国纽约赖特设计的古根海姆美术馆的展厅空间布置采用形式是串联式5. 电影放映院不需采光6. 点式住宅可设天井或平面凹凸布置可增加外墙面,有利于每层户数较多时的采光和通风7. 对结构形式有规定性的有大小和容量、物理环境、形状的规定性8. 功能与流线分析是现代建筑设计最常用的手段9. 垂直方向高的建筑需要考虑透视变形的矫正10. 橙色是暖色,而紫色含有蓝色的成分,所以偏冷;青色比黄色冷、红色比黄色暖、蓝色比绿色冷11. 同样大小冷色调较暖色调给人的感觉要大12. 同样距离,暖色较冷色给人以靠近感13. 为保持室内空间稳定感,房间的低处宜采用低明度色彩14. 冷色调给人以幽雅宁静的气氛15. 色相、明度、彩度是色彩的三要素;三元色为红、黄、蓝16. 尺度的概念是建筑物整体或局部给人的视角印象大小和其实际大小的关系17. 美的比例,必然正确的体现材料的力学特征18. 不同文化形成独特的比例形式19. 西方古典建筑高度与开间的比例,愈高大愈狭长,愈低矮愈宽阔20. ‘稳定’所涉及的要素是上与下之间的相对轻重关系的处理21. 人眼观赏规律H 18°~45°局部、细部2H 18°~27°整体3H <18°整体及环境22. 黄金分隔比例为1:1.61823. 通风屋面只能隔离太阳辐射不能保温,适宜于南方24. 总图布置要因地制宜,建筑物与周围环境之间关系紧凑,节约因地;适当处理个体与群体,空间与体形,绿化和小品的关系;合理解决采光、通风、朝向、交通与人流的组织25. 热水系统舒适稳定适用于居住建筑和托幼蒸汽系统加热快,适用于间歇采暖建筑如会堂、剧场26. 渐变具有韵律感27. 要使一座建筑显得富有活力,形式生动,在构图中应采用对比的手法对比的手法有轴线对比、体量对比、方向对比、虚实对比、色彩对比28. 要使柱子看起来显得细一些,可以采用暗色和冷色29. 巴西国会大厅在体型组合中采用了对比与协调的手法30. 展览建筑应使用穿套式的空间组合形式31. 室外空间的构成,主要依赖于建筑和建筑群体组合32. 在意大利威尼斯的圣马可广场的布局中,采用了强调了各种空间之间的对比33. 当坡地坡度较缓时,应采用平行等高线布置34. 建筑的有效面积=建筑面积-结构面积35. 加大开窗面积的方法来解决采光和通风问题较易办到36. 中国古代木结构大致可分为抬梁式、穿斗式和井干式三种37. 建筑构图原理的基本范畴有主从与重点、对比与呼应、均衡与稳定、节奏与韵律和比例与尺度38. 建筑构图的基本规律是多样统一39. 超过8层的建筑中,电梯就成为主要的交通工具了40. 建筑的模数分为基本模数、扩大模数和分模数41. 建筑楼梯梯段的最大坡度不宜超过38°42. 住宅起居室、卧室、厨房应直接采光,窗地比为1/7,其他为1/1243. 住宅套内楼梯梯段的最小净宽两边墙的0.9M,一边临空的0.75M住宅室内楼梯踏步宽不应小于0.22M,踏步高度不应小大0.20M44. 住宅底层严禁布置火灾危险性甲乙类物质的商店,不应布置产生噪声的娱乐场所45. 地下室、贮藏室等房间的最低净高不应低于2.0米46. 室内坡道水平投影长度超过15米时,宜设休息平台47. 外墙内保温所占面积不计入使用面积烟道、风道、管道井不计入使用面积阳台面积不计入使用面积壁柜应计入使用面积48. 旋转楼梯两级的平面角度不大于10度,且每级离内侧扶手中心0.25处的踏步宽度要大于0.22米49. 两个安全出口之间的净距不应小于5米50. 楼梯正面门扇开足时宜保持0.6米平台净宽,侧墙门口距踏步不宜小于0.4米,其门扇开足时不应减少梯段的净宽35. 加大开窗面积的方法来解决采光和通风问题较易办到36. 中国古代木结构大致可分为抬梁式、穿斗式和井干式三种37. 建筑构图原理的基本范畴有主从与重点、对比与呼应、均衡与稳定、节奏与韵律和比例与尺度38. 建筑构图的基本规律是多样统一39. 超过8层的建筑中,电梯就成为主要的交通工具了40. 建筑的模数分为基本模数、扩大模数和分模数41. 建筑楼梯梯段的最大坡度不宜超过38°42. 住宅起居室、卧室、厨房应直接采光,窗地比为1/7,其他为1/1243. 住宅套内楼梯梯段的最小净宽两边墙的0.9M,一边临空的0.75M住宅室内楼梯踏步宽不应小于0.22M,踏步高度不应小大0.20M44. 住宅底层严禁布置火灾危险性甲乙类物质的商店,不应布置产生噪声的娱乐场所45. 地下室、贮藏室等房间的最低净高不应低于2.0米46. 室内坡道水平投影长度超过15米时,宜设休息平台47. 外墙内保温所占面积不计入使用面积烟道、风道、管道井不计入使用面积阳台面积不计入使用面积壁柜应计入使用面积48. 旋转楼梯两级的平面角度不大于10度,且每级离内侧扶手中心0.25处的踏步宽度要大于0.22米49. 两个安全出口之间的净距不应小于5米50. 楼梯正面门扇开足时宜保持0.6米平台净宽,侧墙门口距踏步不宜小于0.4米,其门扇开足时不应减少梯段的净宽35. 加大开窗面积的方法来解决采光和通风问题较易办到36. 中国古代木结构大致可分为抬梁式、穿斗式和井干式三种37. 建筑构图原理的基本范畴有主从与重点、对比与呼应、均衡与稳定、节奏与韵律和比例与尺度38. 建筑构图的基本规律是多样统一39. 超过8层的建筑中,电梯就成为主要的交通工具了40. 建筑的模数分为基本模数、扩大模数和分模数41. 建筑楼梯梯段的最大坡度不宜超过38°42. 住宅起居室、卧室、厨房应直接采光,窗地比为1/7,其他为1/1243. 住宅套内楼梯梯段的最小净宽两边墙的0.9M,一边临空的0.75M住宅室内楼梯踏步宽不应小于0.22M,踏步高度不应小大0.20M44. 住宅底层严禁布置火灾危险性甲乙类物质的商店,不应布置产生噪声的娱乐场所45. 地下室、贮藏室等房间的最低净高不应低于2.0米46. 室内坡道水平投影长度超过15米时,宜设休息平台47. 外墙内保温所占面积不计入使用面积烟道、风道、管道井不计入使用面积阳台面积不计入使用面积壁柜应计入使用面积48. 旋转楼梯两级的平面角度不大于10度,且每级离内侧扶手中心0.25处的踏步宽度要大于0.22米49. 两个安全出口之间的净距不应小于5米50. 楼梯正面门扇开足时宜保持0.6米平台净宽,侧墙门口距踏步不宜小于0.4米,其门扇开足时不应减少梯段的净宽51. 入地下车库的坡道端部宜设挡水反坡和横向通长雨水篦子52. 室内台阶宜150*300;室外台阶宽宜350左右,高宽比不宜大于1:2.553. 住宅公用楼梯踏步宽不应小于0.26M,踏步高度不应大于0.175M54. 梯段宽度不应小于1.1M(6层及以下一边设栏杆的可为1.0M),净空高度2.2M55. 休息平台宽度应大于梯段宽度,且不应小于1.2M,净空高度2.0M56. 梯扶手高度0.9M,水平段栏杆长度大于0.5M时应为1.05M57. 楼梯垂直杆件净空不应大于0.11M,梯井净空宽大于0.11M时应采取防护措施58. 门洞共用外门宽1.2M,户门卧室起居室0.9M,厨房0.8M,卫生间及阳台门0.7M,所有门洞高为2.0M59. 住宅层高不宜高于2.8M60. 卧室起居室净高≥2.4M,其局部净高≥2.1M(且其不应大于使用面积的1/3)61. 利用坡顶作起居室卧室的,一半面积净高不应低于2.1M利用坡顶空间时,净高低于1.2M处不计使用面积;1.2--2.1M计一半使用面积;高于2.1M全计使用面积62. 放家具墙面长3M,无直接采光的厅面积不应大于10M263. 厨房面积Ⅰ、Ⅱ≥4M2;Ⅲ、Ⅳ≥5M264. 厨房净宽单面设备不应小于1.5M;双面布置设备间净距不应小于0.9M65. 对于大套住宅,其使用面积必须满足45平方米66. 住宅套型共分四类使用面积分别为34、45、56、68M267. 单人卧室≥6M2;双人卧室≥10M2;兼起居室卧室≥12M2;68. 卫生间面积三件3M2;二件2--2.5M2;一件1.1M269. 厨房、卫生间净高2.2M70. 住宅楼梯窗台距楼地面净高度低于0.9米时,不论窗开启与否,均应有防护措施71. 阳台栏杆净高1.05M;中高层为1.1M(但要<1.2);杆件净距0.1172. 无外窗的卫生间应设置防回流构造的排气通风道、预留排气机械的位置、门下设进风百叶窗或与地面间留出一定缝隙73. 每套应设阳台或平台、应设置晾衣设施、顶层应设雨罩;阳台、雨罩均应作有组织排水;阳台宜做防水;雨罩应做防水74. 寒冷、夏热冬冷和夏热冬暖地区的住宅,西面应采取遮阳措施75. 严寒地区的住宅出入口,各种朝向均应设防寒门斗或保温门76. 住宅建筑中不宜设置的附属公共用房有锅炉房、变压器室、易燃易爆化学物品商店但有厨房的饮食店可设77. 住宅设计应考虑防触电、防盗、防坠落78. 跃层指套内空间跨跃两楼层及以上的住宅79. 在坡地上建住宅,当建筑物与等高线垂直时,采用跌落方式较为经济80. 住宅建筑工程评估指标体系表中有一级和二级指标81. 7层及以上(16米)住宅必须设电梯82. 宿舍最高居住层的楼地面距入口层地面的高度大于20米时,应设电梯83. 医院病房楼,设有空调的多层旅馆,超过5层的公建室内疏散楼梯,均应设置封闭楼梯间(包括首层扩大封闭楼梯间)设歌舞厅放映厅且超过3层的地上建筑,应设封闭楼梯间。
matlabcanny边缘检测代码接霍夫变换-概述说明以及解释1.引言1.1 概述边缘检测是图像处理中的一个重要任务,它广泛应用于计算机视觉、图像分析和模式识别等领域。
边缘检测的目标是找到图像中不同区域之间的边界,并将其表示为像素强度的变化。
Canny边缘检测算法是一种经典且常用的边缘检测方法。
它通过一系列的图像处理步骤来提取图像中的边缘信息。
Canny算法的特点是能够检测出细且准确的边缘,并且对于图像中的噪声具有较好的抵抗能力。
Matlab是一种功能强大的数学软件,广泛应用于科学计算、数据可视化和图像处理等领域。
Matlab提供了丰富的图像处理函数和工具箱,其中包括了Canny边缘检测的实现代码。
本文的主要目的是介绍Matlab中Canny边缘检测的代码实现,并结合Hough变换算法进行边缘检测的应用。
通过使用Matlab中的相关函数和工具,我们可以有效地实现Canny边缘检测,并结合Hough变换来进一步处理和分析图像中的边缘特征。
本文将首先回顾Canny边缘检测算法的原理和步骤,然后介绍Matlab中的Canny边缘检测代码的使用方法。
接着,我们将介绍Hough 变换算法的原理和应用,并展示如何将Canny边缘检测与Hough变换相结合来实现更精确的边缘检测。
最后,我们将对Canny边缘检测和Hough变换的优缺点进行讨论,总结这两种方法在边缘检测中的应用。
同时,我们也将展望未来的研究方向,探讨如何进一步改进和优化边缘检测算法,以满足不断发展的图像处理需求。
通过阅读本文,读者将能够理解Canny边缘检测算法和Hough变换算法的原理,掌握Matlab中相关代码的使用方法,并了解边缘检测在实际应用中的优势和局限性。
希望本文能为读者在图像处理领域的学习和研究提供一定的帮助和启示。
文章结构是指文章的整体框架和组织形式。
一个良好的文章结构可以使读者更好地理解和领会文章的内容,同时也有助于文章的逻辑性和条理性。
matlab圆半径测量代码概述及解释说明1. 引言1.1 概述在科学研究和工程应用中,圆的半径测量是一个重要且常见的问题。
精确地测量圆的半径可以为我们提供关于形状、面积和体积等参数的信息,对于实现精确的计算和设计具有重要作用。
然而,由于传统手动测量方法存在一定的误差和不便之处,因此开发出自动化的圆半径测量代码成为许多研究者关注的课题。
本文旨在介绍以Matlab为工具开发的圆半径测量代码,包括其原理、实现方法、实验设计和结果分析等。
通过深入探讨与解释这些方面内容,读者将能够全面了解该代码的基本功能及其应用潜力。
1.2 文章结构本文共分为五个主要部分,每部分围绕特定主题展开。
首先是引言部分,在这一部分中将对文章进行简要介绍,并阐明撰写本文所追求的目标。
随后,在"2. Matlab圆半径测量代码原理"部分将详细介绍圆的数学定义与特性,并解释Matlab中基于算法实现圆半径测量的基本原理。
在"3. Matlab圆半径测量代码实现方法"部分,将详细讨论数据采集与预处理、图像处理与边缘检测算法选择以及半径计算与结果输出等实现过程中的关键步骤。
接下来,在"4. 实验设计与结果分析"部分将介绍我们设计的实验,并展示和讨论实验结果。
最后,在"5. 结论与展望"部分将对整篇文章进行总结,并展望未来可能的改进方向和应用场景。
1.3 目的本文的主要目的是向读者介绍Matlab圆半径测量代码的重要性和应用价值,并详细解释其背后所涉及到的原理和方法。
通过阅读本文,读者将能够深入了解如何使用该代码进行自动化圆半径测量,从而提高相关领域的工作效率和准确性。
同时,本文还将通过实验设计和结果分析部分验证该代码在不同情况下的可靠性,并为读者提供相关改进方向和扩展思路。
通过对Matlab圆半径测量代码进行全面解析,我希望本文能够为科研人员、工程师以及对此感兴趣的读者提供有价值的参考和指导,促进相关领域的研究和应用进展。
1.图像反转MATLAB 程序实现如下:I=imread('xian.bmp');J=double(I);J=-J+(256-1);% 图像反转线性变换H=uint8(J);subplot(1,2,1),imshow(I);subplot(1,2,2),imshow(H);2.灰度线性变换MATLAB 程序实现如下:I=imread('xian.bmp');subplot(2,2,1),imshow(I);title(' 原始图像 ');axis([50,250,50,200]);axis on;% 显示坐标系I1=rgb2gray(I);subplot(2,2,2),imshow(I1);title(' 灰度图像 ');axis([50,250,50,200]);axis on;% 显示坐标系J=imadjust(I1,[0.1 0.5],[]); %局部拉伸,把[0.1 0.5]内的灰度拉伸为[0 1]subplot(2,2,3),imshow(J);title(' 线性变换图像 [0.1 0.5]');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系K=imadjust(I1,[0.30.7],[]);% 局部拉伸,把[0.30.7] 内的灰度拉伸为 [0 1]subplot(2,2,4),imshow(K);title(' 线性变换图像 [0.3 0.7]');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系3. 非线性变换MATLAB 程序实现如下:I=imread('xian.bmp');I1=rgb2gray(I);subplot(1,2,1),imshow(I1);title(' 灰度图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系J=double(I1);J=40*(log(J+1));H=uint8(J);subplot(1,2,2),imshow(H);title(' 对数变换图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系4. 直方图均衡化MATLAB 程序实现如下:I=imread('xian.bmp');I=rgb2gray(I);figure;subplot(2,2,1);imshow(I);subplot(2,2,2);imhist(I);I1=histeq(I);figure;subplot(2,2,1);imshow(I1);subplot(2,2,2);imhist(I1);5.线性平滑滤波器用 MATLAB 实现领域平均法抑制噪声程序:I=imread('xian.bmp');subplot(231)imshow(I)title(' 原始图像 ')I=rgb2gray(I);I1=imnoise(I,'salt & pepper',0.02);subplot(232)imshow(I1)title(' 添加椒盐噪声的图像')k1=filter2(fspecial('average',3),I1)/255;% 进行 3*3 模板平滑滤波k2=filter2(fspecial('average',5),I1)/255;% 进行 5*5 模板平滑滤波k3=filter2(fspecial('average',7),I1)/255;% 进行 7*7 模板平滑滤波k4=filter2(fspecial('average',9),I1)/255;% 进行 9*9 模板平滑滤波subplot(233),imshow(k1);title('3*3 模板平滑滤波 ');subplot(234),imshow(k2);title('5*5 模板平滑滤波 ');subplot(235),imshow(k3);title('7*7 模板平滑滤波 ');subplot(236),imshow(k4);title('9*9 模板平滑滤波 ');6.中值滤波器用 MATLAB 实现中值滤波程序如下:I=imread('xian.bmp');I=rgb2gray(I);J=imnoise(I,'salt&pepper',0.02);subplot(231),imshow(I);title(' 原图像 ');subplot(232),imshow(J);title(' 添加椒盐噪声图像'); k1=medfilt2(J);% 进行 3*3 模板中值滤波k2=medfilt2(J,[5,5]);% 进行 5*5 模板中值滤波k3=medfilt2(J,[7,7]);% 进行 7*7 模板中值滤波k4=medfilt2(J,[9,9]);% 进行 9*9 模板中值滤波subplot(233),imshow(k1);title('3*3 模板中值滤波 '); subplot(234),imshow(k2);title('5*5 模板中值滤波'); subplot(235),imshow(k3);title('7*7 模板中值滤波 '); subplot(236),imshow(k4);title('9*9 模板中值滤波 '); 7.用 Sobel 算子和拉普拉斯对图像锐化:I=imread('xian.bmp');subplot(2,2,1),imshow(I);title(' 原始图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系I1=im2bw(I);subplot(2,2,2),imshow(I1);title(' 二值图像');axis([50,250,50,200]);grid on; axis on;% 显示网格线%显示坐标系H=fspecial('sobel'); J=filter2(H,I1);% 选择 sobel 算子% 卷积运算subplot(2,2,3),imshow(J);title('sobel 算子锐化图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系h=[0 1 0,1 -4 1,0 1 0];% 拉普拉斯算子J1=conv2(I1,h,'same');% 卷积运算subplot(2,2,4),imshow(J1);title(' 拉普拉斯算子锐化图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系8.梯度算子检测边缘用 MATLAB 实现如下:I=imread('xian.bmp');subplot(2,3,1);imshow(I);title(' 原始图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系I1=im2bw(I);subplot(2,3,2);imshow(I1);title(' 二值图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系I2=edge(I1,'roberts');figure;subplot(2,3,3);imshow(I2);title('roberts算子分割结果');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系I3=edge(I1,'sobel');subplot(2,3,4);imshow(I3);title('sobel算子分割结果 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系I4=edge(I1,'Prewitt');subplot(2,3,5);imshow(I4);title('Prewitt算子分割结果 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系9.LOG 算子检测边缘用 MATLAB 程序实现如下:I=imread('xian.bmp');subplot(2,2,1);imshow(I);title(' 原始图像 ');I1=rgb2gray(I);subplot(2,2,2);imshow(I1);title(' 灰度图像 ');I2=edge(I1,'log');subplot(2,2,3);imshow(I2);title('log 算子分割结果 '); 10.Canny 算子检测边缘用 MATLAB 程序实现如下:I=imread('xian.bmp'); subplot(2,2,1);imshow(I);title(' 原始图像 ')I1=rgb2gray(I);subplot(2,2,2);imshow(I1);title(' 灰度图像 ');I2=edge(I1,'canny'); subplot(2,2,3);imshow(I2);title('canny 算子分割结果 ');11. 边界跟踪(bwtraceboundary函数)clcclear allI=imread('xian.bmp');figureimshow(I);title('原始图像');I1=rgb2gray(I); threshold=graythresh(I1);% 将彩色图像转化灰度图像% 计算将灰度图像转化为二值图像所需的门限BW=im2bw(I1,threshold);% 将灰度图像转化为二值图像figureimshow(BW);title('二值图像');dim=size(BW);col=round(dim(2)/2)-90;% 计算起始点列坐标row=find(BW(:,col),1);% 计算起始点行坐标connectivity=8;num_points=180;contour=bwtraceboundary(BW,[row,col],'N',connectivity,num_p oints);%提取边界figureimshow(I1);hold on;plot(contour(:,2),contour(:,1), 'g','LineWidth' ,2); title(' 边界跟踪图像 ');12.Hough 变换I= imread('xian.bmp');rotI=rgb2gray(I);subplot(2,2,1);imshow(rotI);title(' 灰度图像 ');axis([50,250,50,200]);grid on;axis on;BW=edge(rotI,'prewitt');subplot(2,2,2);imshow(BW);title('prewitt算子边缘检测后图像');axis([50,250,50,200]);grid on;axis on;[H,T,R]=hough(BW);subplot(2,2,3);imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit'); title(' 霍夫变换图 ');xlabel('\theta'),ylabel('\rho');axis on , axis normal, hold on;P=houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));x=T(P(:,2));y=R(P(:,1));plot(x,y,'s','color','white');lines=houghlines(BW,T,R,P ,'FillGap',5,'MinLength',7); subplot(2,2,4);,imshow(rotI);title(' 霍夫变换图像检测');axis([50,250,50,200]);grid on;axis on;hold on;max_len=0;for k=1:length(lines)xy=[lines(k).point1;lines(k).point2];plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');len=norm(lines(k).point1-lines(k).point2);if(len>max_len)max_len=len;xy_long=xy;endendplot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','cyan');13.直方图阈值法用 MATLAB 实现直方图阈值法:I=imread('xian.bmp');I1=rgb2gray(I);figure;subplot(2,2,1);imshow(I1);title(' 灰度图像 ')axis([50,250,50,200]);grid on;% 显示网格线axis on;%显示坐标系[m,n]=size(I1);% 测量图像尺寸参数GP=zeros(1,256);% 预创建存放灰度出现概率的向量for k=0:255GP(k+1)=length(find(I1==k))/(m*n);% 计算每级灰度出现的概率,将其存入GP 中相应位置endsubplot(2,2,2),bar(0:255,GP ,'g')% 绘制直方图title(' 灰度直方图 ')xlabel(' 灰度值 ')ylabel(' 出现概率 ')I2=im2bw(I,150/255);subplot(2,2,3),imshow(I2);title(' 阈值 150 的分割图像 ')axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系I3=im2bw(I,200/255);%subplot(2,2,4),imshow(I3);title(' 阈值 200 的分割图像 ')axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系14. 自动阈值法: Otsu 法用MATLAB 实现 Otsu 算法:clcclear allI=imread('xian.bmp');subplot(1,2,1),imshow(I);title(' 原始图像 ')axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系level=graythresh(I);% 确定灰度阈值BW=im2bw(I,level);subplot(1,2,2),imshow(BW);title('Otsu 法阈值分割图像 ')axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系15. 膨胀操作I=imread('xian.bmp');% 载入图像I1=rgb2gray(I);subplot(1,2,1);imshow(I1);title(' 灰度图像 ')axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系se=strel('disk',1);% 生成圆形结构元素I2=imdilate(I1,se);% 用生成的结构元素对图像进行膨胀subplot(1,2,2);imshow(I2);title(' 膨胀后图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系16. 腐蚀操作MATLAB 实现腐蚀操作I=imread('xian.bmp');% 载入图像I1=rgb2gray(I);subplot(1,2,1);imshow(I1);title(' 灰度图像 ')axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系se=strel('disk',1);% 生成圆形结构元素I2=imerode(I1,se);% 用生成的结构元素对图像进行腐蚀subplot(1,2,2);imshow(I2);title(' 腐蚀后图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系17.开启和闭合操作用 MATLAB 实现开启和闭合操作I=imread('xian.bmp');% 载入图像subplot(2,2,1),imshow(I);title(' 原始图像 ');axis([50,250,50,200]);axis on;% 显示坐标系I1=rgb2gray(I);subplot(2,2,2),imshow(I1);title(' 灰度图像');axis([50,250,50,200]);axis on;% 显示坐标系se=strel('disk',1);% 采用半径为1的圆作为结构元素I3=imclose(I1,se);% 闭合操作subplot(2,2,3),imshow(I2);title(' 开启运算后图像 ');axis([50,250,50,200]);axis on;% 显示坐标系subplot(2,2,4),imshow(I3);title(' 闭合运算后图像 ');axis([50,250,50,200]);axis on;% 显示坐标系18.开启和闭合组合操作I=imread('xian.bmp');% 载入图像subplot(3,2,1),imshow(I);title(' 原始图像 ');axis([50,250,50,200]);axis on;% 显示坐标系I1=rgb2gray(I);subplot(3,2,2),imshow(I1);title(' 灰度图像 ');axis([50,250,50,200]);axis on;% 显示坐标系se=strel('disk',1);I3=imclose(I1,se);%闭合操作subplot(3,2,3),imshow(I2);title(' 开启运算后图像 ');axis([50,250,50,200]);axis on;% 显示坐标系subplot(3,2,4),imshow(I3);title(' 闭合运算后图像 ');axis([50,250,50,200]);axis on;% 显示坐标系se=strel('disk',1);I4=imopen(I1,se);I5=imclose(I4,se);subplot(3,2,5),imshow(I5);% 开—闭运算图像title(' 开—闭运算图像 ');axis([50,250,50,200]);axis on;% 显示坐标系I6=imclose(I1,se);I7=imopen(I6,se);subplot(3,2,6),imshow(I7);% 闭—开运算图像title(' 闭—开运算图像 ');axis([50,250,50,200]);axis on;% 显示坐标系19. 形态学边界提取利用 MATLAB 实现如下:I=imread('xian.bmp');% 载入图像subplot(1,3,1),imshow(I);title(' 原始图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系I1=im2bw(I);subplot(1,3,2),imshow(I1);title(' 二值化图像 ');axis([50,250,50,200]);grid on;% 显示网格线axis on;% 显示坐标系I2=bwperim(I1);% 获取区域的周长subplot(1,3,3),imshow(I2);title(' 边界周长的二值图像 ');axis([50,250,50,200]);grid on;axis on;20.形态学骨架提取利用 MATLAB 实现如下:I=imread('xian.bmp'); subplot(2,2,1),imshow(I); title(' 原始图像 ');axis([50,250,50,200]); axis on;I1=im2bw(I);subplot(2,2,2),imshow(I1); title(' 二值图像 ');axis([50,250,50,200]); axis on;I2=bwmorph(I1,'skel',1); subplot(2,2,3),imshow(I2); title('1 次骨架提取 ');axis([50,250,50,200]); axis on;I3=bwmorph(I1,'skel',2); subplot(2,2,4),imshow(I3); title('2 次骨架提取 ');axis([50,250,50,200]); axis on;21.直接提取四个顶点坐标I = imread('xian.bmp');I = I(:,:,1);BW=im2bw(I);figureimshow(~BW)[x,y]=getpts。
canny算子代码void CreatGauss(double sigma, double **pdKernel, int *pnWidowSize);void GaussianSmooth(SIZE sz, LPBYTE pGray, LPBYTE pResult, double sigma);void Grad(SIZE sz, LPBYTE pGray, int *pGradX, int *pGradY, int *pMag);void NonmaxSuppress(int *pMag, int *pGradX, int *pGradY, SIZE sz, LPBYTE pNSRst); void EstimateThreshold(int *pMag, SIZE sz, int *pThrHigh, int *pThrLow, LPBYTE pGray, double dRatHigh, double dRatLow);void Hysteresis(int *pMag, SIZE sz, double dRatLow, double dRatHigh, LPBYTE pResult); void TraceEdge(int y, int x, int nThrLow, LPBYTE pResult, int *pMag, SIZE sz);void Canny(LPBYTE pGray, SIZE sz, double sigma, double dRatLow,double dRatHigh, LPBYTE pResult);#include "afx.h"#include "math.h"#include "canny.h"// 一维高斯分布函数,用于平滑函数中生成的高斯滤波系数void CreateGauss(double sigma, double **pdKernel, int *pnWidowSize){LONG i;//数组中心点int nCenter;//数组中一点到中心点距离double dDis;//中间变量double dValue;double dSum;dSum = 0;// [-3*sigma,3*sigma] 以内数据,会覆盖绝大部分滤波系数*pnWidowSize = 1+ 2*ceil(3*sigma);nCenter = (*pnWidowSize)/2;*pdKernel = new double[*pnWidowSize];//生成高斯数据for(i=0;i <(*pnWidowSize);i++){dDis = double(i - nCenter);dValue = exp(-(1/2)*dDis*dDis/(sigma*sigma))/(sqrt(2*3.1415926)*sigma);(*pdKernel)[i] = dValue;dSum+=dValue;}//归一化for(i=0;i <(*pnWidowSize);i++){(*pdKernel)[i]/=dSum;}}//用高斯滤波器平滑原图像void GaussianSmooth(SIZE sz, LPBYTE pGray, LPBYTE pResult, double sigma) {LONG x, y;LONG i;//高斯滤波器长度int nWindowSize;//窗口长度int nLen;//一维高斯滤波器double *pdKernel;//高斯系数与图像数据的点乘double dDotMul;//滤波系数总和double dWeightSum;double *pdTemp;pdTemp = new double[sz.cx*sz.cy];//产生一维高斯数据CreatGauss(sigma, &pdKernel, &nWindowSize);nLen = nWindowSize/2;//x方向滤波for(y=0;y <sz.cy;y++){for(x=0;x <sz.cx;x++){dDotMul = 0;dWeightSum = 0;for(i=(-nLen);i <=nLen;i++){//判断是否在图像内部if((i+x)>=0 && (i+x) <sz.cx){dDotMul+=(double)pGray[y*sz.cx+(i+x)] * pdKernel[nLen+i];dWeightSum += pdKernel[nLen+i];}}pdTemp[y*sz.cx+x] = dDotMul/dWeightSum;}}//y方向滤波for(x=0; x <sz.cx;x++){for(y=0; y <sz.cy; y++){dDotMul = 0;dWeightSum = 0;for(i=(-nLen);i <=nLen;i++){if((i+y)>=0 && (i+y) < sz.cy){dDotMul += (double)pdTemp[(y+i)*sz.cx+x]*pdKernel[nLen+i];dWeightSum += pdKernel[nLen+i];}}pResult[y*sz.cx+x] = (unsigned char)dDotMul/dWeightSum;}}delete []pdKernel;pdKernel = NULL;delete []pdTemp;pdTemp = NULL;}// 方向导数,求梯度void Grad(SIZE sz, LPBYTE pGray, int *pGradX, int *pGradY, int *pMag) {LONG y,x;//x方向的方向导数for(y=1;y <sz.cy-1;y++){for(x=1;x <sz.cx-1;x++){pGradX[y*sz.cx +x] = (int)( pGray[y*sz.cx+x+1]-pGray[y*sz.cx+ x-1] );}}//y方向方向导数for(x=1;x <sz.cx-1;x++){for(y=1;y <sz.cy-1;y++){pGradY[y*sz.cx +x] = (int)(pGray[(y+1)*sz.cx +x] - pGray[(y-1)*sz.cx +x]);}}//求梯度//中间变量double dSqt1;double dSqt2;for(y=0; y <sz.cy; y++){for(x=0; x <sz.cx; x++){//二阶范数求梯度dSqt1 = pGradX[y*sz.cx + x]*pGradX[y*sz.cx + x];dSqt2 = pGradY[y*sz.cx + x]*pGradY[y*sz.cx + x];pMag[y*sz.cx+x] = (int)(sqrt(dSqt1+dSqt2)+0.5);}}}//非最大抑制void NonmaxSuppress(int *pMag, int *pGradX, int *pGradY, SIZE sz, LPBYTE pNSRst) {LONG y,x;int nPos;//梯度分量int gx;int gy;//中间变量int g1,g2,g3,g4;double weight;double dTmp,dTmp1,dTmp2;//设置图像边缘为不可能的分界点for(x=0;x <sz.cx;x++){pNSRst[x] = 0;pNSRst[(sz.cy-1)*sz.cx+x] = 0;}for(y=0;y <sz.cy;y++){pNSRst[y*sz.cx] = 0;pNSRst[y*sz.cx + sz.cx-1] = 0;}for(y=1;y <sz.cy-1;y++){for(x=1;x <sz.cx-1;x++){//当前点nPos = y*sz.cx + x;//如果当前像素梯度幅度为0,则不是边界点if(pMag[nPos] == 0){pNSRst[nPos] = 0;}else{//当前点的梯度幅度dTmp = pMag[nPos];//x,y方向导数gx = pGradX[nPos];gy = pGradY[nPos];//如果方向导数y分量比x分量大,说明导数方向趋向于y分量if(abs(gy) > abs(gx)){//计算插值比例weight = fabs(gx)/fabs(gy);g2 = pMag[nPos-sz.cx];g4 = pMag[nPos+sz.cx];//如果x,y两个方向导数的符号相同//C 为当前像素,与g1-g4 的位置关系为://g1 g2// C// g4 g3if(gx*gy>0){g1 = pMag[nPos-sz.cx-1];g3 = pMag[nPos+sz.cx+1];}//如果x,y两个方向的方向导数方向相反//C是当前像素,与g1-g4的关系为:// g2 g1// C// g3 g4else{g1 = pMag[nPos-sz.cx+1];g3 = pMag[nPos+sz.cx-1];}}//如果方向导数x分量比y分量大,说明导数的方向趋向于x分量else{//插值比例weight = fabs(gy)/fabs(gx);g2 = pMag[nPos+1];g4 = pMag[nPos-1];//如果x,y两个方向的方向导数符号相同//当前像素C与g1-g4的关系为// g3// g4 C g2// g1if(gx * gy > 0){g1 = pMag[nPos+sz.cx+1];g3 = pMag[nPos-sz.cx-1];}//如果x,y两个方向导数的方向相反// C与g1-g4的关系为// g1// g4 C g2// g3else{g1 = pMag[nPos-sz.cx+1];g3 = pMag[nPos+sz.cx-1];}}//利用g1-g4 对梯度进行插值{dTmp1 = weight*g1 + (1-weight)*g2;dTmp2 = weight*g3 + (1-weight)*g4;//当前像素的梯度是局部的最大值//该点可能是边界点if(dTmp>=dTmp1 && dTmp>=dTmp2){pNSRst[nPos] = 128;}else{//不可能是边界点pNSRst[nPos] = 0;}}}}}}// 统计pMag的直方图,判定阈值void EstimateThreshold(int *pMag, SIZE sz, int *pThrHigh, int *pThrLow, LPBYTE pGray, double dRatHigh, double dRatLow){LONG y,x,k;//该数组的大小和梯度值的范围有关,如果采用本程序的算法//那么梯度的范围不会超过pow(2,10)int nHist[256];//可能边界数int nEdgeNum;//最大梯度数int nMaxMag;int nHighCount;nMaxMag = 0;//初始化for(k=0;k <256;k++){nHist[k] = 0;}//统计直方图,利用直方图计算阈值for(y=0;y <sz.cy;y++){for(x=0;x <sz.cx;x++){if(pGray[y*sz.cx+x]==128){nHist[pMag[y*sz.cx+x]]++;}}}nEdgeNum = nHist[0];nMaxMag = 0;//统计经过“非最大值抑制”后有多少像素for(k=1;k <256;k++){if(nHist[k] != 0){nMaxMag = k;}//梯度为0的点是不可能为边界点的//经过non-maximum suppression后有多少像素nEdgeNum += nHist[k];}//梯度比高阈值*pThrHigh 小的像素点总数目nHighCount = (int)(dRatHigh * nEdgeNum + 0.5);k=1;nEdgeNum = nHist[1];//计算高阈值while((k <(nMaxMag-1)) && (nEdgeNum < nHighCount)){k++;nEdgeNum += nHist[k];}*pThrHigh = k;//低阈值*pThrLow = (int)((*pThrHigh) * dRatLow + 0.5);}//利用函数寻找边界起点void Hysteresis(int *pMag, SIZE sz, double dRatLow, double dRatHigh, LPBYTE pResult) {LONG y,x;int nThrHigh,nThrLow;int nPos;//估计TraceEdge 函数需要的低阈值,以及Hysteresis函数使用的高阈值EstimateThreshold(pMag, sz,&nThrHigh,&nThrLow,pResult,dRatHigh,dRatLow);//寻找大于dThrHigh的点,这些点用来当作边界点,//然后用TraceEdge函数跟踪该点对应的边界for(y=0;y <sz.cy;y++){for(x=0;x <sz.cx;x++){nPos = y*sz.cx + x;//如果该像素是可能的边界点,并且梯度大于高阈值,//该像素作为一个边界的起点if((pResult[nPos]==128) && (pMag[nPos] >= nThrHigh)){//设置该点为边界点pResult[nPos] = 255;TraceEdge(y,x,nThrLow,pResult,pMag,sz);}}}//其他点已经不可能为边界点for(y=0;y <sz.cy;y++){for(x=0;x <sz.cx;x++){nPos = y*sz.cx + x;if(pResult[nPos] != 255){pResult[nPos] = 0;}}}}//根据Hysteresis 执行的结果,从一个像素点开始搜索,搜索以该像素点为边界起点的一条边界的//一条边界的所有边界点,函数采用了递归算法// 从(x,y)坐标出发,进行边界点的跟踪,跟踪只考虑pResult中没有处理并且可能是边界// 点的像素(=128),像素值为0表明该点不可能是边界点,像素值为255表明该点已经是边界点void TraceEdge(int y, int x, int nThrLow, LPBYTE pResult, int *pMag, SIZE sz){//对8邻域像素进行查询int xNum[8] = {1,1,0,-1,-1,-1,0,1};int yNum[8] = {0,1,1,1,0,-1,-1,-1};LONG yy,xx,k;for(k=0;k <8;k++){yy = y+yNum[k];xx = x+xNum[k];if(pResult[yy*sz.cx+xx]==128 && pMag[yy*sz.cx+xx]>=nThrLow ) {//该点设为边界点pResult[yy*sz.cx+xx] = 255;//以该点为中心再进行跟踪TraceEdge(yy,xx,nThrLow,pResult,pMag,sz);}}}// Canny算子void Canny(LPBYTE pGray, SIZE sz, double sigma, double dRatLow, double dRatHigh, LPBYTE pResult){//经过高斯滤波后的图像LPBYTE pGaussSmooth;pGaussSmooth = new unsigned char[sz.cx*sz.cy];//x方向导数的指针int *pGradX;pGradX = new int[sz.cx*sz.cy];//y方向int *pGradY;pGradY = new int[sz.cx*sz.cy];//梯度的幅度int *pGradMag;pGradMag = new int[sz.cx*sz.cy];//对原图高斯滤波GaussianSmooth(sz,pGray,pGaussSmooth,sigma);//计算方向导数和梯度的幅度Grad(sz,pGaussSmooth,pGradX,pGradY,pGradMag);//应用非最大抑制NonmaxSuppress(pGradMag,pGradX,pGradY,sz,pResult);//应用Hysteresis,找到所有边界Hysteresis(pGradMag,sz,dRatLow,dRatHigh,pResult);delete[] pGradX;pGradX = NULL;delete[] pGradY;pGradY = NULL;delete[] pGradMag;pGradMag = NULL;delete[] pGaussSmooth; pGaussSmooth = NULL;}/*void CChildWnd::OnCanny(){if (! m_fOpenFile){return;}m_fDone = TRUE;RGBToGray(szImg, aRGB, aGray, BPP); Canny(aGray,szImg,0.1,0.9,0.76,aBinImg);ShowGrayImage("l",szImg,aBinImg);}//*/。