1. 要求
参考Sobel算子能够检测x和y方向的原理,设计合适的模板,能够检测±45°斜方向上的图像细节,分别输出正45度方向和负45度方向的图像细节,以及两者相叠加后的图像结果。将取的图像细节,叠加到原图上,实现图像锐化。
2. Sobel算子
用来强调水平边缘,
用来强调垂直边缘。
图片来自链接
这里有3个矩阵,分别是、
和
,可以看到在
矩阵中,以6为中心的3*3的小矩阵与
进行运算(对应位置相乘后求和),运算的结果存放在
矩阵中和6对应的位置。
同理,在6的右侧的元素2,经过运算,其在矩阵中对应位置的值为
(0*-1) + (1*0) + (5*1) + (6*-2) + (2*0) + (4*2) + (4*-1) + (1*0) + (0*1) = -3
一般地,如果对使用
进行卷积处理,则
这时候肯定有人会问:那矩阵左上角的元素3,它对应
矩阵中的值是多少?
这是一个很好的问题,可以看到,以3(第一行第一列)为中心的3*3的矩阵缺失了5个元素,这种情况下一般有两种处理方式:
1. Padding即对缺失的元素进行填充,一般使用0进行填充
2. 不做处理,直接用它本身的值3作为最终值填入矩阵
3. matlab代码实践
参考sobel算子中的和
,可以发现:
(1)中的元素是纵向排列,矩阵所有元素和为0,用以检测水平边缘;
(2)中的元素是横向排列,矩阵所有元素和为0,用以检测竖直边缘。
于是可以猜想:
(1)检测正45°方向的模板,其矩阵中的元素应该按负45度方向排列,且所有元素和为0;
(2)检测负45°方向的模板,其矩阵中的元素应该按正45度方向排列,且所有元素和为0。
即
其中用以检测正45度方向,
用以检测负45度方向。
matlab提供了官方函数filter2,可以使用指定的模板对图像进行卷积处理
clear, close all
% 检测正45°方向的模板
h1 = [ -1 0 0;
0 2 0;
0 0 -1];
% 检测负45°方向的模板
h2 = [ 0 0 -1;
0 2 0;
-1 0 0];
im = imread('cameraman.tif');
subplot(2,2,1), imshow(im), title('原图')
im_filter_1 = filter2(h1, im)/255;
subplot(2,2,2), imshow(im_filter_1), title('45°')
im_filter_2 = filter2(h2, im)/255;
subplot(2,2,3), imshow(im_filter_2), title('-45°')
im_filter_3 = filter2(h1+h2, im)/255;
subplot(2,2,4), imshow(im_filter_3), title('叠加')
观察下图,可以发现,在默认情况下,向filter2函数中传入模板和图像矩阵,得到的卷积结果的四条边界非常突出,进一步观察原矩阵即未除以255之前的矩阵,可以发现matlab中的filter2函数对边界值的处理,默认不采取先padding再卷积的方式,而是不做处理直接填入。
再提一下为什么要将卷积结果除以255。当出现如下情况的时候,卷积后的矩阵中会出现大于255的值,而灰度值的范围是在[0, 255],为了让卷积后的结果仍能落在这个区间,所以我对卷积结果除以了255。
为了得到锐化后的图像, 最后只需要使用im_filter_3放大一定倍数再和im进行叠加处理即可。
im是uint8类型的矩阵,im_filter_3*50的结果是double类型的矩阵,二者不能直接相加,于是我使用uint8函数将im_filter_3*50的结果转换为uint8类型(浮点数转为整数,超过255的数值变为255,低于0的数值变为0,0-255之间的数值不变)
两个uint8类型的矩阵的矩阵相加,其结果仍为uint8类型的矩阵(超过255的数值变为255,低于0的数值变为0,0-255之间的数值不变)。
这里留下一个思考:之前卷积的结果能不能不除以255,而是使用uint8进行转换?
figure
subplot(1,2,1), imshow(im), title('原图')
im_boost = im + uint8(im_filter_3*50);
subplot(1,2,2), imshow(im_boost), title('增强')
观察结果可以发现,锐化后的图像其正负45度方向的边缘明显比原图清晰突出。
4. 代码获取
关注公众号,回复“数字图像处理”即可获取完整代码