一、实验目的
1.学会使用编程实现不同算法的边缘检测。
2.学会使用编程实现不同算法的图像分割。
3.能够根据实验结果分析各种算法的特点及其应用场合,培养处理实际图像的能力。
二、实验要求
1.实验课前需要写预习实验报告,内容为本次实验要求中的所有程序清单。
2.实验课对预习报告中的编程代码进行上机调试,完成实验指导书中全部实验要求内容。
3.实验课后写出实验报告。报告要求有实验目的,实验内容与步骤,调试完成的准确编程代码,实验小结,回答问题。
三、实验内容(每一个内容编写一个*.m文件)
1.边缘检测:
(1)利用边缘检测函数edge ()对灰度图像(house.tif)进行边缘检测,检测算子分别选择'roberts'、'sobel'、'prewitt'、LOG、'Canny'(其他参数选择:default),比较不同检测算子对边缘检测的效果;
Roberts算子对于细节较多的图像效果不太好,而且对于噪声敏感。
Sobel算子相对于Roberts算子来说能够更好地处理细节部分,但是仍然对噪声比较敏感。
Prewitt算子和Sobel算子类似,但是它对噪声更加稳健。
Laplacian算子对于细节比较多的图像效果比较好,但是对于噪声较多的图像来说效果不太好。
Canny算子能够很好地处理细节复杂的图像,并且对于噪声的抗干扰性也比较好。
clear
% 加载图像
img = imread('house.tif');
% 边缘检测算子
operators = {'roberts', 'sobel', 'prewitt', 'log', 'canny'};
for i = 1:length(operators)
operator = operators{i};
% 应用不同的算子进行边缘检测
switch operator
case 'roberts'
edges = edge(img, 'Roberts');
case 'sobel'
edges = edge(img, 'Sobel');
case 'prewitt'
edges = edge(img, 'Prewitt');
case 'log'
edges = edge(img, 'log');
case 'canny'
edges = edge(img, 'Canny');
end
% 显示边缘检测结果
figure;
imshow(edges);
title(operator);
end
(2)利用工具箱函数imfilter()和如图1所示四种不同方向的线检测模板w1/w2/w3/w4对图像(Fig0908(a).tif)进行边缘检测,比较不同方向的检测算子对边缘检测的效果;
-1 | -2 | -1 | -1 | 0 | 1 | 0 | 1 | 2 | -2 | -1 | 0 | |||
0 | 0 | 0 | -2 | 0 | 2 | -1 | 0 | 1 | -1 | 0 | 1 | |||
1 | 2 | 1 | -1 | 0 | 1 | -2 | -1 | 0 | 0 | 1 | 2 |
图1 w1(水平) w2(垂直) w3 (+45°) w4(-45°)
w1(水平方向):能够检测出图像中水平方向的边缘,如图像中的水平线条。
w2(垂直方向):能够检测出图像中垂直方向的边缘,如图像中的垂直线条。
w3(+45°方向):能够检测出图像中+45°方向的边缘,如图像中的斜线。
w4(-45°方向):能够检测出图像中-45°方向的边缘,如图像中的斜线。
% 读取图像
image = imread('Fig0908(a).tif');
% 定义四个不同方向的线检测模板
w1 = [-1 -2 -1; 0 0 0; 1 2 1];
w2 = [-1 0 1; -2 0 2; -1 0 1];
w3 = [0 1 2; -1 0 1; -2 -1 0];
w4 = [-2 -1 0; -1 0 1; 0 1 2];
% 对图像应用四个模板进行边缘检测
result1 = imfilter(image, w1);
result2 = imfilter(image, w2);
result3 = imfilter(image, w3);
result4 = imfilter(image, w4);
% 显示原始图像和边缘检测结果
figure;
subplot(2, 3, 1), imshow(image), title('原始图像');
subplot(2, 3, 2), imshow(result1), title('w1(水平)');
subplot(2, 3, 3), imshow(result2), title('w2(垂直)');
subplot(2, 3, 4), imshow(result3), title('w3(+45°)');
subplot(2, 3, 5), imshow(result4), title('w4(-45°)');
2.对灰度图像(rice.tif)编程实现图像锐化增强(算子如图2所示):
(1)利用robert算子检测图像边缘,并采用门限法得到锐化增强图像(T=10,T=50);
(2)利用sobel算子检测图像边缘并得到锐化增强图像;
(3)利用Laplacian算子检测图像边缘,分H1和H2两种情况,并得到锐化增强图像;
(4)比较采用不同边缘检测算子锐化增强图像的不同效果。
H1 H2
-1 | 0 | 0 | -1 | -1 | 0 | 1 | -1 | -2 | -1 | 0 | 1 | 0 | 1 | 1 | 1 | |||||
0 | 1 | 1 | 0 | -2 | 0 | 2 | 0 | 0 | 0 | 1 | -4 | 1 | 1 | -8 | 1 | |||||
-1 | 0 | 1 | 1 | 2 | 1 | 0 | 1 | 0 | 1 | 1 | 1 |
图2 robert算子 sobel算子 Laplaci算子
% 读取图像
image = imread('rice.tif');
% 定义 Robert 算子模板
robert_h1 = [-1 0; 0 1];
robert_h2 = [0 -1; 1 0];
% 定义 Sobel 算子模板
sobel_h1 = [-1 0 1; -2 0 2; -1 0 1];
sobel_h2 = [-1 -2 -1; 0 0 0; 1 2 1];
% 定义 Laplacian 算子模板
laplacian_h1 = [-1 -1 -1; -1 8 -1; -1 -1 -1];
laplacian_h2 = [0 -1 0; -1 4 -1; 0 -1 0];
% Robert 算子锐化增强(门限法)
robert_result1 = abs(imfilter(image, robert_h1)) > 10;
robert_result2 = abs(imfilter(image, robert_h1)) > 50;
% Sobel 算子锐化增强
sobel_result = abs(imfilter(image, sobel_h1)) + abs(imfilter(image, sobel_h2));
% Laplacian 算子锐化增强
laplacian_result1 = abs(imfilter(image, laplacian_h1));
laplacian_result2 = abs(imfilter(image, laplacian_h2));
% 显示原始图像和锐化增强结果
figure;
subplot(2, 4, 1), imshow(image), title('原始图像');
subplot(2, 4, 2), imshow(robert_result1), title('Robert算子 T=10');
subplot(2, 4, 3), imshow(robert_result2), title('Robert算子 T=50');
subplot(2, 4, 4), imshow(sobel_result), title('Sobel算子');
subplot(2, 4, 5), imshow(laplacian_result1), title('Laplacian算子 H1');
subplot(2, 4, 6), imshow(laplacian_result2), title('Laplacian算子 H2');
Robert算子通常对图像中细节和边缘有着较好的响应,但对噪声比较敏感。它的锐化结果可能会突出一些细微的纹理和边缘特征。
Sobel算子在检测边缘时会考虑到像素的梯度变化,因此在图像锐化中会产生更加平滑和连续的边缘效果。它相对对噪声有一定的抑制作用。
Laplacian算子可以在不同方向上检测边缘,其H1和H2两种情况会产生不同的效果。它通常对于边缘的粗略检测有比较好的表现,并且在图像锐化中会强调更加整体的边缘特征。
3. 对灰度图像(Fig1018(a).tif)实现基于阈值处理的图像分割(1为必做内容,2-4为选做内容):
(1)利用函数graythresh ()和otsuthresh()找到全局阈值,对图像进行分割;
(2)采用迭代阈值选取方法,编程实现基于图像数据自动地选择阈值,对图像进行全局阈值分割;
(3)使用Otsu阈值选取方法,编程实现对图像进行最佳全局阈值分割;
(4)比较迭代法和Otsu法两种不同的阈值处理方法对图像进行分割的效果。
clear
% 读取图像
image = imread('Fig1018(a).tif');
% 计算直方图
counts = imhist(image);
global_thresh = graythresh(image);
segmented_image_1 = imbinarize(image, global_thresh);
threshold = mean(image(:));
prev_threshold = 0;
while abs(threshold - prev_threshold) > 1e-3
prev_threshold = threshold;
foreground = image > threshold;
background = image <= threshold;
threshold = (mean(image(foreground)) + mean(image(background))) / 2;
end
segmented_image_2 = imbinarize(image, threshold);
otsu_thresh = otsuthresh(counts);
segmented_image_3 = imbinarize(image, otsu_thresh);
figure;
subplot(2, 2, 1), imshow(image), title('原始图像');
subplot(2, 2, 2), imshow(segmented_image_1), title('全局阈值分割(graythresh)');
subplot(2, 2, 3), imshow(segmented_image_2), title('迭代法阈值分割');
subplot(2, 2, 4), imshow(segmented_image_3), title('Otsu阈值分割');
四、问题与讨论
1.比较不同检测算子对灰度图像('house.tif')边缘检测的效果有什么不同?
w1(水平方向):能够检测出图像中水平方向的边缘,如图像中的水平线条。
w2(垂直方向):能够检测出图像中垂直方向的边缘,如图像中的垂直线条。
w3(+45°方向):能够检测出图像中+45°方向的边缘,如图像中的斜线。
w4(-45°方向):能够检测出图像中-45°方向的边缘,如图像中的斜线。
2.比较不同方向的检测算子对边缘检测的效果有什么不同?
Robert算子通常对图像中细节和边缘有着较好的响应,但对噪声比较敏感。它的锐化结果可能会突出一些细微的纹理和边缘特征。
Sobel算子在检测边缘时会考虑到像素的梯度变化,因此在图像锐化中会产生更加平滑和连续的边缘效果。它相对对噪声有一定的抑制作用。
Laplacian算子可以在不同方向上检测边缘,其H1和H2两种情况会产生不同的效果。它通常对于边缘的粗略检测有比较好的表现,并且在图像锐化中会强调更加整体的边缘特征。
3.迭代法和Otsu法两种不同的阈值处理方法对图像进行分割的效果有什么不同?
迭代法是一种基于统计信息的阈值选取方法。它通过迭代计算前景和背景的平均灰度值,并以它们的平均值作为阈值进行分割。该方法需要预设一个初始阈值,并在每次迭代中根据前景和背景的平均灰度值来更新阈值,直到阈值收敛为止。迭代法的优点是简单易实现,但对于复杂图像可能需要较多的迭代次数才能达到较好的分割效果。
Otsu法是一种基于类间方差最大化的自适应阈值选取方法。它通过计算不同阈值下前景和背景之间的类间方差,选择使得类间方差最大的阈值作为全局阈值。Otsu法的优点是能够自动选择最佳的阈值,不需要事先设定初始阈值。它适用于不同光照条件下的图像分割,并且对于复杂图像也有较好的效果