前面讲解了图像的基本操作,包括读取和显示图像以及图像的加减及其作用。这里讲解图像的乘除、邻域操作和空间变换。
图像的相除
图像的相除(相乘)的一个重要应用是阴影校正。假设一个成像传感器产生可由f(x,y)表示的完美图像与阴影函数h(x,y)的乘积来建模的图像,即g(x,y)=f(x,y)h(x,y)。如果h(x,y)已知,那么我们就可以使用h(x,y)的反函数乘以感知图像的方法得到f(x,y)[即g(x,y)/h(x,y)]。如果h(x,y)未知,但图像系统可以访问,我们可以通过对具有恒定灰度的目标成像得到一个近似的阴影函数。即若f(x,y)是由常值a组成的图像矩阵,那么经过该图像信道后得到g(x,y)那么h(x,y)=g(x,y)/f(x,y)=g(x,y)/a。
clear clc Tungsten=imread('钨丝及其支撑物的阴影.jpg'); %读取图像数据 Shadow=imread('阴影模式.jpg'); %阴影图片 Tungsten_gray=rgb2gray(Tungsten); %灰度化 Shadow_gray=rgb2gray(Shadow); figure(1) subplot(1,2,1) imshow(Tungsten_gray); title('钨丝及其支撑物的阴影') subplot(1,2,2) imshow(Shadow_gray); title('阴影模式') %%格式转化 Tungsten_gray=double(Tungsten_gray); Shadow_gray=double(Shadow_gray); %%检测除数是否含有0 Shadow_gray_min=min(min(Shadow_gray)); if Shadow_gray_min==0 Shadow_gray(Shadow_gray==0)=1; end %%图像相除 Image_Divisor=Tungsten_gray./(Shadow_gray); %%线性变换 Image_Divisor_min=min(min(Image_Divisor)); Image_Divisor_max=max(max(Image_Divisor)); Image_Adjust=(Image_Divisor-Image_Divisor_min)/(Image_Divisor_max-Image_Divisor_min)*255; %%格式转化 Tungsten_gray=uint8(Tungsten_gray); Shadow_gray=uint8(Shadow_gray); Image_Adjust=uint8(Image_Adjust); figure(2) subplot(1,2,1) imshow(Tungsten_gray); title('原图像') subplot(1,2,2) imshow(Image_Adjust); title('去除阴影后的图像')
如图所示为钨丝及其支撑物的阴影图g(x,y),及其相应的阴影h(x,y)。
运行上述代码,我们可以得到去除阴影后的图像。如图所示为去除阴影前后对比图,可以看到图像通过相除的阴影校正操作,增强了图像。注意在图像相除操作时,除数图像矩阵可能包含0灰度值,这里可以通过令其灰度值为1进行处理。
图像的相乘
clear clc Tooth=imread('牙齿的X射线数字图像.jpg'); %读取图像数据 ROI=imread('使用填充物隔离牙齿的ROI模板.jpg'); %阴影图片 Tooth_gray=rgb2gray(Tooth); %灰度化 ROI_gray=rgb2gray(ROI); figure(1) subplot(1,2,1) imshow(Tooth_gray); title('牙齿的X射线数字图像') subplot(1,2,2) imshow(ROI_gray); title('使用填充物隔离牙齿的ROI模板') %%格式转化 Tooth_gray=double(Tooth_gray); ROI_gray=double(ROI_gray); %%图像相乘 Image_Multiplying=Tooth_gray.*(ROI_gray); %%线性变换 Image_Multiplying_min=min(min(Image_Multiplying)); Image_Multiplying_max=max(max(Image_Multiplying)); Image_Adjust=(Image_Multiplying-Image_Multiplying_min)/(Image_Multiplying_max-Image_Multiplying_min)*255; %%格式转化 Tooth_gray=uint8(Tooth_gray); ROI_gray=uint8(ROI_gray); Image_Adjust=uint8(Image_Adjust); figure(2) subplot(1,2,1) imshow(Tooth_gray); title('牙齿的X射线数字图像') subplot(1,2,2) imshow(Image_Adjust); title('相乘后的结果')如图为牙齿的X射线数字图像以及使用填充物隔离牙齿的ROI模板,这里为了跟踪填充物隔离的牙齿。ROI区域为1,其余为0,其形状可以任意,通常采用矩形。
运行上述程序,可以得到下面的图示。我们可以看到,通过图像相乘,锁定了填充物隔离的牙齿。
图像的邻域操作
图像的邻域操作是指输出图像与原图像相同位置的像素由该点的邻域点集通过指定操作得到。例如在大小为m×n的图像中,点(x,y)的值由以该点为中心的矩形领域中的像素的平均值决定。
平均值操作可以通过imfilter图像滤波器得到,相当于图像与大小为m×n的元素全为1的矩阵模板卷积得到。
data=imread('大动脉血管造影.jpg'); [m,n,l]=size(data); % A=[2,3,4;3,4,5;6,7,8]; % h=[1,1;1,1]; % B=imfilter(A,h); % B; m=41; n=41; h=ones(m,n)/(m*n); newdata=imfilter(data,h); figure(1) subplot(1,2,1) imshow(data) title('原图像') subplot(1,2,2) imshow(newdata) title('平均值操作')
运行上述程序,可以得到原图像与平均值操作对比图。平均值操作有模糊图像的效果,如果m和n取值合理,可以取到一定的平滑去噪的效果。
图像的空间变换
图像的几何空间变换是通过改变图像中像素间的空间关系实现的。
空间变换可以由以下公式得到:
这个变换可以根据矩阵T中元素所选择的值,对一组坐标点做尺度、旋转、平移或偏移。
图像的空间变换可以通过imresize等Matlab自带程序实现,这里我们采用上述公式自行实现。
首先读入图像,并获取图像的大小。
clear clc data=imread('字母T.jpg'); figure(1) imshow(data); title('字母T') [m,n,l]=size(data);
这里可以采用imresize函数,也可通过构造T矩阵得到。这里令其纵向放大3倍,横向放大5倍。
mrows=3*m; ncols=5*n; newdata= imresize(data, [mrows ncols]) ; figure(2) imshow(newdata); title('放大缩小') cx=3; cy=5; T=zeros(3,3); %拉伸 T(1,1)=cx; T(2,2)=cy; T(3,3)=1;
下面是通过自己按照公式编写程序。
首先构造T矩阵。这里以旋转45°为例。
%旋转 arg=pi()*1/4; T(1,1)=cos(arg); T(2,2)=T(1,1); T(1,2)=sin(arg); T(2,1)=-T(1,2); T(3,3)=1;
其次生成坐标矩阵。格式为[1,1,1;1,2,1;1,3,1;...;2,1,1;2,2,1;2,3,1;...m,1,1;m,2,1;...;m,n,1]。
%%生成坐标矩阵 k=1; for i=1:m for j=1:n A(k,1)=i; A(k,2)=j; A(k,3)=1; k=k+1; end end
然后进行坐标变换,注意由于这里含有三角函数,相乘后会含有小数,因此用floor函数取最大整数。
%%坐标变换 B=floor(A*T);这里需要进行矩阵调整,这是因为上述计算会使得结果中包含0;而Matlab矩阵下标是从1开始的。
%%矩阵调整 B(:,1)=B(:,1)-min(B(:,1))+1; B(:,2)=B(:,2)-min(B(:,2))+1;这里加入白色背景(也可不加)。
%%加入白色背景 maxrow=max(B(:,1)); maxcol=max(B(:,2)); newdata=uint8(2^8*ones(maxrow,maxcol,3));
矩阵取值,取变换前相对应的像素值。
%%取值 k=1; for i=1:m for j=1:n newdata(B(k,1),B(k,2),:)=data(i,j,:); k=k+1; end end figure(3) imshow(newdata);
经过旋转后的图像,由于加入白色背景,可以看到,里面包含很多白色斑点,这是由于空间变换后,很多坐标点中没有填充像素,这是需要进行插值或者滤波处理。这里简单的进行平均值滤波,模板大小取原图像的64分之一。
%%平均值滤波 [m,n,l]=size(newdata); st=64; line=floor(m/st); column=floor(n/st); h=ones(line,column)/(line*column); newdata2=imfilter(newdata,h); figure(4) imshow(newdata2)
可以看到滤波后的图像,较原图像有较大改善。
这里我们减小模板大小,取st=128。可以看到该图像相比较64有较大改善。但是仍然可以看出,图像中包含横纵纹理。这里可以通过插值的方式得以改善。一般的线性插值的方式相比较平均值仅仅是送入imfilter的矩阵不再是元素相同的1矩阵。这里不再赘述。