计算机视觉实验三:图像分割
1 图像分割实验(锐化及边缘检测实验)
1.1 实验目的
使用Matlab 软件进行图像的分割。通过实验体会一些主要的分割算子对图像处理的效果,以及各种因素对分割效果的影响。
1.2 实验要求
要求能够自行评价各主要算子在无噪声条件下和噪声条件下的分割性能。能够掌握分割条件(阈值等)的选择。完成规定图像的处理并要求正确评价处理结果,能够从理论上作出合理的解释。
1.3 实验内容与步骤
(1)使用Roberts 算子的图像分割实验
调入并显示图像room.tif(也许是room.png,或其它具有代表性的边缘检测图片)中图像;使用Roberts 算子对图像进行边缘检测处理; Roberts 算子为一对模板:
代码:
% 读取图像
img = imread('你图片的路径');
% 显示原始图像
figure;
imshow(img);
title('原始图像');
% (1) Roberts算子
rh = [0 1; -1 0];
rv = [1 0; 0 -1];
% 应用Roberts算子
roberts_h = conv2(double(img), rh, 'same');
roberts_v = conv2(double(img), rv, 'same');
(2)相应的矩阵为:rh = [0 1;-1 0]; rv = [1 0;0 -1];这里的rh 为水平Roberts 算子,rv为垂直Roberts 算子。分别显示处理后的水平边界和垂直边界检测结果;用“欧几里德距离”和“街区距离”方式计算梯度的模,并显示检测结果;对于检测结果进行二值化处理,并显示处理结果;
提示:先做检测结果的直方图,参考直方图中灰度的分布尝试确定阈值;应反复调节阈值的大小,直至二值化的效果最为满意为止。分别显示处理后的水平边界和垂直边界检测结果;将处理结果转化为“白底黑线条”的方式;给图像加上零均值的高斯噪声;对于噪声图像重复以上步骤。
代码:
% 显示水平和垂直边缘
figure;
subplot(1,2,1);
imshow(uint8(abs(roberts_h)));
title('水平边缘 (Roberts)');
subplot(1,2,2);
imshow(uint8(abs(roberts_v)));
title('垂直边缘 (Roberts)');
% 使用欧几里德和曼哈顿距离计算梯度幅值
gradient_magnitude_euclidean = sqrt(roberts_h.^2 + roberts_v.^2);
gradient_magnitude_manhattan = abs(roberts_h) + abs(roberts_v);
% 显示梯度幅值结果
figure;
subplot(1,2,1);
imshow(uint8(gradient_magnitude_euclidean));
title('梯度幅值 (欧几里德)');
subplot(1,2,2);
imshow(uint8(gradient_magnitude_manhattan));
title('梯度幅值 (曼哈顿)');
% 使用直方图分析对梯度幅值结果进行二值化
thresh = graythresh(gradient_magnitude_euclidean);
binary_image = imbinarize(gradient_magnitude_euclidean, thresh);
% 显示二值化图像
figure;
imshow(binary_image);
title('二值化图像 (Roberts)');
% (2) 添加高斯噪声并重复处理步骤
noisy_img = imnoise(img, 'gaussian', 0, 0.01); % 根据需要调整噪声强度
% 显示有噪声的图像
figure;
imshow(noisy_img);
title('有噪声的图像');
% 为有噪声的图像重复Roberts算子和处理步骤
% 应用Roberts算子
roberts_h_noisy = conv2(double(noisy_img), rh, 'same');
roberts_v_noisy = conv2(double(noisy_img), rv, 'same');
% 显示水平和垂直边缘
figure;
subplot(1,2,1);
imshow(uint8(abs(roberts_h_noisy)));
title('水平边缘 (Roberts) - 有噪声');
subplot(1,2,2);
imshow(uint8(abs(roberts_v_noisy)));
title('垂直边缘 (Roberts) - 有噪声');
% 计算梯度幅值
gradient_magnitude_noisy = sqrt(roberts_h_noisy.^2 + roberts_v_noisy.^2);
% 显示梯度幅值结果
figure;
imshow(uint8(gradient_magnitude_noisy));
title('梯度幅值 (Roberts) - 有噪声');
% 使用直方图分析对梯度幅值结果进行二值化
thresh_noisy = graythresh(gradient_magnitude_noisy);
binary_image_noisy = imbinarize(gradient_magnitude_noisy, thresh_noisy);
% 显示二值化图像
figure;
imshow(binary_image_noisy);
title('二值化图像 (Roberts) - 有噪声');
(3)使用Prewitt 算子的图像分割实验
使用Prewitt 算子进行内容(1)(2)中的全部步骤。
代码:
% 与Roberts相似,用Prewitt算子替换rh和rv
% (3) Prewitt算子
ph = [-1 0 1; -1 0 1; -1 0 1];
pv = [-1 -1 -1; 0 0 0; 1 1 1];
% 应用Prewitt算子
prewitt_h = conv2(double(img), ph, 'same');
prewitt_v = conv2(double(img), pv, 'same');
% 显示水平和垂直边缘
figure;
subplot(1,2,1);
imshow(uint8(abs(prewitt_h)));
title('水平边缘 (Prewitt)');
subplot(1,2,2);
imshow(uint8(abs(prewitt_v)));
title('垂直边缘 (Prewitt)');
(4)使用Sobel 算子的图像分割实验
使用Sobel 算子进行内容(1)(2)中的全部步骤。
% 与Roberts相似,用Sobel算子替换rh和rv
(5)使用LoG (拉普拉斯-高斯)算子的图像分割实验
使用LoG (拉普拉斯-高斯)算子进行内容(1)(2)中的全部步骤。提示1:处理后可以直接显示处理结果,无须另外计算梯度的模。提示2:注意调节噪声的强度以及LoG (拉普拉斯-高斯)算子的参数,观察处理结果。
% 读取图像
img = imread('图片路径');
% 显示原始图像
figure;
imshow(img);
title('原始图像');
% LoG (拉普拉斯-高斯)算子
% 提示:处理后可以直接显示处理结果,无须另外计算梯度的模。
% 设定LoG算子的参数
log_size = 15; % LoG核的大小(奇数)
log_std = 2; % 高斯分布的标准差
% 创建LoG滤波器
log_filter = fspecial('log', log_size, log_std);
% 应用LoG滤波器
log_result = imfilter(double(img), log_filter, 'symmetric', 'conv');
% 显示LoG处理结果
figure;
imshow(log_result, []);
title('LoG (拉普拉斯-高斯)处理结果');
% 添加高斯噪声并重复处理步骤
noisy_img = imnoise(img, 'gaussian', 0, 0.01); % 根据需要调整噪声强度
% 显示有噪声的图像
figure;
imshow(noisy_img);
title('有噪声的图像');
% 为有噪声的图像重复LoG算子和处理步骤
% 创建LoG滤波器
log_filter = fspecial('log', log_size, log_std);
% 应用LoG滤波器
log_result_noisy = imfilter(double(noisy_img), log_filter, 'symmetric', 'conv');
% 显示LoG处理结果
figure;
imshow(log_result_noisy, []);
title('LoG (拉普拉斯-高斯)处理结果 - 有噪声');
高斯噪声强度:0.01,LoG核的大小log_size = 15;
高斯分布的标准差log_std = 2;
高斯噪声强度:0.02,LoG核的大小log_size = 7;
高斯分布的标准差log_std = 2;
6) 用Matlab语言(或其它语言),编写Canny边缘检测器的Matlab(或其它语言)函数(根据公式设计代码,不使用自带的canny函数);利用上述函数,对一副图像进行边缘检测;利用Matlab自带的Canny边缘检测函数对同一副图像进行边缘检测;比较上述两个结果。(选做)
Canny边缘检测器算法步骤如下:
步骤1. 图像与高斯平滑滤波器卷积:
步骤2. 使用一阶有限差分计算偏导数阵列P与Q:
步骤3. 计算梯度幅值与方向角:
步骤4. 非极大值抑制(NMS ) :
去掉幅值局部变化非极大的点.
* 将梯度角离散为圆周的四个扇区之一,以便用3×3的窗口作抑制运算
步骤5. 阈值化
取高低两个阈值作用于幅值图N[i,j],得到两个边缘图:高阈值和低阈值边缘图。连接高阈值边缘图,出现断点时,在低阈值边缘图中的8邻点域搜寻边缘点。
(7) 打印全部结果并进行讨论。
下面是使用sobel监测器对图像进行分割的MATLAB程序
f=imread('C:\Users\33841\Desktop\image\room.png');
[gv,t1]=edge(f,'sobel','vertical');%使用edge函数对图像f提取垂直的边缘
imshow(gv)
[gb,t2]=edge(f,'sobel','horizontal');%使用edge函数对图像f提取垂直的边缘
figure,imshow(gb)
w45=[-2 -1 0;-1 0 1;0 1 2];%指定模版使用imfilter计算45度方向的边缘
g45=imfilter(double(f),w45,'replicate');
T=0.3*max(abs(g45(:))); %设定阈值
g45=g45>=T; %进行阈值处理
figure,imshow(g45);
在函数中使用'prewitt'和'roberts'的过程,类似于使用sobel边缘检测器的过程。
1.4 实验报告要求
(1)叙述实验过程;
(2)提交实验的原始图像和结果图像。
(3)对问题进行回答,按要求进行编程和给出对比结果。
(4)对结果进行讨论和总结。
1.5 思考题/问答题
1、评价一下Roberts 算子、Prewitt 算子、Sobel 算子对于噪声条件下边界检测的性能。
Roberts 算子:对噪声敏感,因为它是基于简单的差分操作。在存在噪声的情况下,Roberts 算子可能会导致边缘检测结果出现假阳性或假阴性。
Prewitt 算子:相较于Roberts 算子,Prewitt 算子具有更好的性能,但仍然对噪声敏感。它使用了更大的卷积核,因此在一定程度上对噪声具有平滑效果,但仍可能受到噪声的影响。
Sobel 算子:Sobel 算子相对于Roberts 和Prewitt 算子来说,对噪声具有更好的鲁棒性。Sobel 使用了更大的卷积核,这有助于平滑噪声,同时保持对真实边缘的敏感性。
2、为什么LoG梯度检测算子的处理结果不需要象Prewitt 等算子那样进行幅度组合?
LoG算子结合了高斯平滑和拉普拉斯算子,通过高斯平滑可以抑制噪声,同时拉普拉斯算子用于检测图像的边缘。在LoG算子的处理结果中,梯度信息已经包含在拉普拉斯算子的结果中,而无需额外的幅度组合。LoG直接提供了边缘的位置和强度信息,使得额外的梯度幅度计算步骤变得不必要。
3、实验中所使用的四种算子所得到的边界有什么异同?
- Roberts 算子:对边缘敏感,但对噪声较为敏感,可能导致边缘检测的误差。
- Prewitt 算子:提供相对较好的边缘检测,对噪声有一定的平滑效果,但仍可能受到噪声的干扰。
- Sobel 算子:在边缘检测中表现良好,对噪声具有一定的平滑作用,通常比前两者更鲁棒。
- LoG 算子:结合了高斯平滑和拉普拉斯算子,对噪声有较好的抑制效果,同时提供了清晰的边缘信息。
4、比较边缘提取中LOG、Canny算子的边缘提取效果。
LoG 算子:提供清晰的边缘信息,同时对噪声有较好的抑制效果。但是,LoG 算子可能产生边缘断裂的问题。
Canny 算子:Canny 算子是一种综合了多个步骤的算法,包括高斯平滑、梯度计算、非极大值抑制和双阈值处理。它在边缘检测中通常表现出色,对噪声具有较好的鲁棒性,并产生连续且细致的边缘。
1.6 实验图片
另存在项目路径,可增加其他图片进行测试。
2.Hough变换实验
2.1 实验目的
掌握hough变换原理,并通过编程实现图像hough变换,能够分析hough变换的性能和效果.
2.2 实验原理
Hough变换时最常用的直线提取方法,它的基本思想是:将直线上每一个数据点变换为参数平面中的一条直线或曲线,利用共线的数据点对应的参数曲线相交于参数空间中一点的关系,使得直线提取问题转化为计数问题。Hough变换提取直线的主要优点是受直线中的间隙和噪声影响较小。
Hough检测直线的Matlab实现:在Matlab图像处理工具箱中提供了3个与Hough变换有关的函数,分别为hough函数,houghpeaks函数和houghlines函数。
hough函数的调用格式为[H,theta,rho]=hough(BW);其中BW为二值图像,H为Hough变换矩阵,theta为变换轴间隔θ,rho为元素个数。
Houghpeaks函数是用来提取Hough变换后参数平面上的峰值点。其调用格式为peaks=houghpeaks(H,numpeaks),其中,H为Hough函数的输出,参数平面的技术结果矩阵,参数numpeaks为指定要提取的峰值数目,默认值为1;输出参数peaks为Q*2维峰值位置矩阵,其中Q为提取的峰值数目,peaks的第q行分别存储第q个峰值的行和列坐标。
Hough函数用于在图像中提取参数平面上的峰值点对应的直线。其调用格式为lines=houghlines(BW,theta,rho,peaks)
Lines=houghlines(…,param1,val1,param2,val2)
其中,BW与Hough函数的BW相同,为二值图象。theta和rho为hough函数返回的输出,指示θ轴和ρ轴各个单元对应的值。Peaks为houghpeaks函数返回的输出,指示峰值的行和列坐标,houghlines函数将根据这些峰值提取直线。Param和val是参数对,用于指定是否合并或保留直线段的相关参数,其取值有两种。当param=’MinLength’时,bal指定合并后的直线被保留的门限长度,长度小于val的直线被舍去。当param=’FillGap’时,val指定直线段被合并的门限间隔。如果两条斜率和截距均相同的直线段间隔小于val给点的值,则它们被合并为一条直线。
2.3 实验内容和要求
在实验1中的canny算子进行边缘检测的基础上(可以实现让使用者交互式的输入不同的Sigma的值) 实现边缘检测。然后运用Hough变换来找到最突出的边缘,在图像中找到并画出相关直线。
% 交互式输入Sigma值
sigma = input('请输入Sigma值: ');
% 读取图像
img = imread('图片路径'); % 请替换为实际图像路径
% Canny边缘检测
edge_img = edge(img, 'Canny', [], sigma);
% 显示Canny边缘检测结果
figure;
imshow(edge_img);
title('Canny边缘检测结果');
% 使用Hough变换找到直线
[H, theta, rho] = hough(edge_img);
% 在Hough变换空间中找到最突出的边缘
peaks = houghpeaks(H, 5, 'Threshold', 0.3 * max(H(:)));
% 通过Hough变换结果获取直线的参数
lines = houghlines(edge_img, theta, rho, peaks);
% 在原始图像上绘制直线
figure;
imshow(img);
hold on;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1), xy(:,2), 'LineWidth', 2, 'Color', 'red');
end
title('检测到的直线');
hold off;
Sigma=0.5
3.其它图像分割实验 (选做)
有兴趣的可以实现k-means, mean shift,层次聚类和Graph cut,深度学习等的图像分割算法,语言自定。