邻域处理有以下几个步骤:
(1)选取中心点(x,y);
(2)仅对预先定义的关于点(x,y)的邻域内的像素执行操作;
(3)令运算结果为该点处的响应;
(4)对图像中的每一点重复该处理。
中心点移动的过程会产生新的邻域,每个邻域对应输入图像上的一个像素。用来标识该处理的两个主要术语是邻域处理和空间滤波,其中后者更为通用。若对邻域中像素执行的计算为线性的,则称该操作为线性空间滤波(也用术语空间卷积);否则称为非线性空间滤波。
滤波线性运算包括将邻域中每个像素与相应的系数相乘,然后将结果进行累加,从而得到点(x,y)处的响应。若邻域大小为mxn,则总共需要mn个系数。这些系数排列为一个矩阵,我们称其为滤波器、模板、滤波模板、核、掩模或窗口,也用卷积滤波、卷积模板或卷积核等术语。
对于一个大小为mxn的掩模,假定m=2a+1且n=2b+1,其中a和b为非负整数。所有假设都基于掩模大小应均为奇数的原则,有意义掩模的最小尺寸是3x3(1x1的掩模价值不大),尽管不是一个必须具备的条件,但处理奇数尺寸的掩模会更加直观,因为它们都有唯一的一个中心点。
在执行线性空间滤波时,需清楚两个意义相近的概念。一个是相关,另一个是卷积。相关是指掩模w按照一定方式在图像f中移动的过程。卷积是相同过程,只是在图像f中移动w前,要将w旋转180度。
一维相关和卷积操作示例
工具箱使用函数imfilter来实现线性空间滤波,该函数语法为
g = imfilter(f,w,filtering_mode,boundary_options,size_options)
通用语法为:
g = imfilter(f,w,‘replicate’)
使用预先旋转滤波器或对称滤波器时,执行卷积计算的语法:
g = imfilter(f, w, ‘conv’,‘replicate’)
或使用函数rot90(w, 2)将w旋转180度,然后使用imfilter(f, w, ‘replicate’),若需提高精度,则f需要在使用函数imfiter之前利用im2double或double转换为double类。
以下为使用imfilte函数的实验数据:
图像1为原图像(原图像为double类)
图像3为使用选项’circular’的结果(出现的问题与零填充问题相同,周期的使用可以使得图像的黑暗部分靠近光亮部分)
图像4是将图像1转换为uint8类图像,当输出通过imfilter转换为与输入相同的类(uint8类)时,剪切会引起数据丢失。原因是掩模的系数并不在范围[0,1]内求和,因而会导致滤波后的结果超出范围[0,255]。要想避免此类问题,我们可使用一个用来归一化系数的选项,以便使得系数和限定在范围[0,1]内(现有条件下,,可以使用系数除以31的平方,以便和为1),或者以double格式输入数据。但要注意的是,即使是以double格式输入数据,数据仍需要归一化为某个点处的一种有效图像格式。
非线性空间滤波也基于邻域操作的,且与前一节讨论的那样,可通过定义一个大小为m x n的邻域,以其中心点滑过一幅图像的方式进行操作。线性空间滤波基于计算乘积之和(这是个线性操作)而非线性空间滤波则基于非线性操作,这种操作包含了一个邻域的像素。例如:令每个中心点处响应等于其邻域内的最大像素值的操作即为非线性滤波。另一个基本区别是,掩模的概念在非线性处理中并不流行。滤波的概念仍然存在,但滤波器应看做是一个基于邻域像素操作的非线性函数,其响应组成了在邻域的中心像素处操作的响应。
工具箱提供了两个执行常规非线性滤波的函数,即函数nlfilter和函数colfilt。函数nlfilter直接执行二维操作,而函数colfilt则以列的形式组织数据。虽然colfilt需要占用更多的内存,但是执行起来要比nlfilter快得多。在大多数图像处理应用中,速度是最重要的因素,因此,在执行常规的非线性空间滤波时,我们更多采用的是colfilt而不是nilfilt。
函数colfilt的语法为:
g = colfilt(f, [m,n],‘sliding’,@fun,parameters)
m和n也是滤波区域的维数,'sliding’表示处理过程是在输入图像f中逐个像素地滑动该m x n区域,@fun引用一个函数,parameters表示函数fun可能需要的参数(由逗号分隔开)。符号@称为函数句柄,它是一种MATLAB数据类型,它包含有引用函数用到的一些信息。
基于矩阵A的组织形式,函数fun必须分别对矩阵的每一列操作,并返回一个包含所有列的结果的行向量v。v的第k个元素表示的是对A中的第k列进行fun操作后的结果。因而,A中可以有MN列,v的最大维数为1xMN。
在使用colfilt时,在进行滤波之前,输入图像必须经过了填充。为此,我们可使用函数padarray,对于二维函数,它的语法为:
fp = padarray(f, [r,c],method,direction)
其中,f为输入图像,fp为填充后的图像,[r c]用于给出填充f的行数和列数,method和direction的意义见表3.3。
令f = [1 2; 3 4],多次变换method和direction得到结果:
使用函数colfilt实现非线性空间滤波
现在我们执行一个非线性滤波,该非线性滤波在任何点处的响应都是中心在该点的邻域内的像素亮度值的几何平均。大小为m x n的邻域中几何平均。大小为m x n的邻域中的几何平均是邻域内亮度值的乘积的1/mn次幂。首先执行非线性滤波函数,调用gmean:
图1为原图像
图2为填充之后的图像
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lXwnbgbt-1593096064953)(https://s2.ax1x.com/2019/06/26/ZefiDO.md.png)]
图3为经过非线性滤波处理后的图像
函数colfilt仍然是进行非线性滤波操作的最好选择,还没有可以取而代之的函数。
工具箱支持一些预定义的二维线性空间滤波器,这些空间滤波器可通过使用函数fspecial来实现。用来生成滤波掩模w的函数fspecia的语法为:
w = fspecial(‘type’,parameters)
其中,'type’表示滤波器类型,'parameters’进一步定义了指定的滤波器。见图3.4
IPT中常用于生成非线性空间滤波的一个工具是函数ordfilt2,它可以生成统计排序(order statistic)滤波器。其他非线性空间滤波器,其响应基于对图像邻域中所包含的像素进行排序,然后使用排序结果确定的值来代替邻域中的中心像素的值。
函数ordfilt2的语法为:
g = ordfilt2(f,order,domain)
该函数生成输出图像g的方式如下:使用邻域的一组排序元素中的第order个元素来代替f中的每个元素,而邻域则由domain中的非零元素指定。这里,domain是一个由0和1组成的大小为m x n的矩阵,该矩阵指定了将在计算中使用的邻域中的像素位置。在这种情况下,domain的作用类似于掩模。计算中不使用对应于矩阵domain中的0的邻域中的像素。例如,要实现大小为m x n的最小过滤器,可使用语法
g = ordfilt2(f,1,ones(m,n))
在该语句中,1表示mn个样本中的第一个样本,ones(m,n)创建了一个元素值为1,大小为m x n的矩阵,表明邻域内的所有样本都将用于计算。
基于实际应用中的重要性,工具箱提供了一个二维中值滤波函数:
g = medfilt2(f, [m n],padopt)
数组[m n]定义了一个大小为m x n的邻域,中值就在该邻域上计算,而padopt指定了三个可能的边界填充选项之一;‘zeros’(默认值);‘symmetric’,此地f按照镜像反射方式对称地沿其边界扩展;‘indexed’,若f是double类图像,则以1来填充图像,否则以0来填充图像。该函数的默认形式为
g = medfilt2(f)
它使用一个大小为3 x 3的邻域来计算中值,并用0来填充图像的边界。
使用函数medfilt2进行中值滤波(中值滤波是降低图像椒盐噪声的有效工具)。
图像处理工具箱将彩色图像当作索引图像或RGB图像(红,绿,蓝)来处理。
一幅RGB图像就是彩色像素的一个MxNx3数组,其中每一个彩色像素点都是在特定空间位置的彩色图像相对应的红,绿,蓝三个分量。RGB也可以看成是一个由三幅灰度图像形成的“堆”。形成一幅RGB彩色图像的三个图像常称为红,绿或蓝分量图像。分量图像的数据类决定了它们的取值范围。double类的取值范围为[0,1],uint8或uint16类的取值范围为[0,255]或[0,65535]。用来代表这些分量图像素值的比特数决定了一幅RGB图像的比特深度。例如,若每个分量图像都是8比特的图像,则对应的RGB图像的深度就是24比特。一般来说,所有分量图像的比特数都是相同的。这种情况下,一幅RGB图像可能有的色彩就是\(\left(2{b}\right){3}\),其中b是每个分量图像的比特数。对于8比特的例子,颜色数为1677216。
令fR,fG和fB分别代表三种RGB分量图像。一幅RGB图像就是利用cat(级联)操作符将这些分量图像组合成的彩色图像:
rgb_iimage = cat(3, fR, fG, fB)
在操作中,图像按顺序放置。一般来说,cat(dim,A1,A2,…)沿着dim指定的方向级联数组。例如,若dim = 1,则数组垂直放置,若dim = 2,则数组水平放置,若dim = 3,则它们会在第三个方向放置。
若所有的分量图像都是一样的,则结果是一幅灰度图像。下面命令可以提取出三幅分量图像:
>>fR = rgb_image(:, :, 1);
>>fG = rgb_image(:, :, 2);
>>fB = rgb_image(:, :, 3);
索引图像有两个分量,即整数的数据矩阵x和彩色映射矩阵map。矩阵map是一个大小为m x 3且由范围在[0,1]之间的浮点值构成的double类数组。map的长度m同它所定义的颜色数目相等。map的每一行都定义单色的红,绿,蓝三个分量。索引图像将像素的亮度值“直接映射”到彩色值。每个像素的颜色由对应的整数矩阵x的值作为指向map的一个指针决定。若x属double类,则其小于或等于1的所有分量都指向map的第1行,所有等于2的分量都指向第2行,以此类推。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8DzeDFaH-1593096064961)(https://s2.ax1x.com/2019/06/28/ZuLXtI.png)]
为了显示出一幅索引图像,可以使用语句
imshow(X,map)或image(x) colormap(map)
colormap是和索引图像共同储存的,当用函数imread加载图像时,它会自动地和图像一起载入。有时需要用较少的颜色来近似一幅索引图像。可以使用函数imapprox,其语法为:
[Y, newmap] = imapprox(X, map, n)
该函数利用彩色映射newmap返回一个数组Y,该数组最多有n种颜色。输入数组X可是uint8类,uint16类或double类。若n小于或等于256,则输出数组Y是uiint8类,若n大于256,则Y是double类。
当map中的行数比X中的不同整数值的数目少时,X中的多个值将在map中用同样的颜色加以显示。指定一幅彩色图的方法有很多。一种方法就是利用如下语句:
map(k, : ) = [r(k) g(k) b(k)]
使用语句whitebg(‘g’) , whitebg(‘green’) , **whitebg([0 1 0])**可以把一幅图像的背景色改成绿色。
MATLAB提供一些预定义的彩色图,可使用下面的命令访问:
**colormap(map_name)**
该命令将彩色映射设定为矩阵map_name;例如,
colormap(copper)其中copper是MATLAB预定义的彩色映射之一。图像可以直接用期望的彩色映射来显示:imshow(X,copper)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dr1X8dxw-1593096064962)(https://s2.ax1x.com/2019/06/28/ZMHZeH.md.png)]
函数dither可以用于灰度图像和彩色图像。“抖动”是在印刷行业和出版业中常用的一种处理,它在由点组成的印刷页上给出色调变化的直观效果。在灰度图像的情况下,“抖动”调色试图用在白色背景上产生黑点的二值图像来得到灰色调。点的大小变化多样,从明亮区域的小点到黑暗区域的逐渐增大的较大点。执行“抖动”算法的关键问题是要折中考虑视觉感受的精确性和计算的复杂度。函数dither处理灰度图像的语法是
bw = dither(gray_image)
当处理彩色图像时,“抖动”主要于函数rgb2ind结合使用,以减少图像中的颜色数目。
函数grayslice的语法为:X = grayslice(gray_image, n)
该函数通过赋给gray_image一个阈值来生成一幅索引图像。
NTSC制式中,图像数据由三部分组成,亮度(Y),色调(I)和饱和度(Q)。
[ Y I Q ] = [ 0.299 0.587 0.114 0.596 − 0.274 − 0.322 0.211 − 0.523 0.312 ] [ R G B ] \left[\begin{array}{l}{Y} \\ {I} \\ {Q}\end{array}\right]=\left[\begin{array}{rrr}{0.299} & {0.587} & {0.114} \\ {0.596} & {-0.274} & {-0.322} \\ {0.211} & {-0.523} & {0.312}\end{array}\right]\left[\begin{array}{l}{R} \\ {G} \\ {B}\end{array}\right] ⎣⎡YIQ⎦⎤=⎣⎡0.2990.5960.2110.587−0.274−0.5230.114−0.3220.312⎦⎤⎣⎡RGB⎦⎤
第一行的各元素之和为1,而下两行的和为0.这和预想的一样,因为在一幅灰度图像中,所有的RGB分量都相等,所以对这样的图像来说,I和Q分量必然为零。
函数rgb2ntsc可执行这样的变换:
rgb_image = ntsc2rgb(yiq_image)
其中,输入RGB图像可以是uint8类,uint16类或double类。输出图像为double类图像,大小为MxNx3。分量图像yiq_image(:,:,1)代表亮度,yiq_image(:,:,2)代表色度,yiq_image(:,:,3)代表饱和度。
例如:以图片太阳花为例,进行RGB图像转换为NTSC图像
图像1为原始图像
图像2为NTSC图像
rgb_image = ntsc2rgb(yiq_image)
输入和输出的图像都是double类图像。
**ycbcr\_image = rgb2ycbcr(rgb\_image)** 和 **rgb\_image = ycbCr2rgb(ycbcr\_image)**
还是以太阳花为例,得到如下结果:
HSV(色调,饱和度,数值)是调色板或颜色轮中挑选颜色,该颜色系统更接近于人们对色彩的感知。
将RGB转换为HSV的函数是rgb2hsv,其语法为
hsv_image = rgb2hsv(rgb_image)和rgb_image = hsv2rgb(hsv_image)
输入图像必须是double类,输出图像也是double类。
RGB转换为CMY。该转换用到了方程:
[ C M Y ] = [ 1 1 1 ] − [ R G B ] \left[\begin{array}{l}{C} \\ {M} \\ {Y}\end{array}\right]=\left[\begin{array}{l}{1} \\ {1} \\ {1}\end{array}\right]-\left[\begin{array}{l}{R} \\ {G} \\ {B}\end{array}\right] ⎣⎡CMY⎦⎤=⎣⎡111⎦⎤−⎣⎡RGB⎦⎤
函数imcomplement可把RGB图像转换为CMY图像:
cmy_image = imcomplement(rgb_image)
若给出一幅RGB彩色图像,则每个RGB像素的H分量可用下面的方程得出: $$ H=\left\{\begin{array}{l}{\theta}\\ {360-\theta}\end{array}\right.若B<=G,若B>G $$
$$
\theta=\arccos \left\{\frac{\frac{1}{2}[(R-G)+(R-B)]}{\left[(R-G)^{2}+(R-B)(G-B)\right]^{1 / 2}}\right\}
$$
饱和度分量由下式给出:
$$
S=1-\frac{3}{(R+G+B)}[\min (R, G, B)]
$$
亮度由下式给出;
$$
I=\frac{1}{3}(R+G+B)
$$