- 实验1 图像插值,图像几何变换:图像旋转、缩放
- 实验主题:
学习双线性插值算法,通过其对图片进行旋转与缩放操作。
- 实验目的:
- 掌握图像插值基本原理和图像几何变换方法。
2.学习使用程序设计环境。
3.掌握双线性插值算法,实现图像的旋转、缩放。
- 实验平台:
- 编程平台:Matlab R2020b
- 编程语言:MATLAB
- 实验要求:
根据选择的图像,编写程序使用双线性插值算法对其进行旋转、缩放处理。
- 实验代码:
- 旋转操作代码:
function rotation(image,angle) img=imread(image); [h,w]=size(img); %img2=imrotate(img,45,'bilinear'); theta=angle/180*pi; rot=[cos(theta) sin(theta) 0;-sin(theta) cos(theta) 0;0 0 1]; pix1=[1 1 1]*rot; %变换后图像左上点的坐标 pix2=[1 w 1]*rot; %变换后图像右上点的坐标 pix3=[h 1 1]*rot; %变换后图像左下点的坐标 pix4=[h w 1]*rot; %变换后图像右下点的坐标 height=round(max([abs(pix1(1)-pix4(1))+0.5 abs(pix2(1)-pix3(1))+0.5])); %变换后图像的高度 width=round(max([abs(pix1(2)-pix4(2))+0.5 abs(pix2(2)-pix3(2))+0.5])); %变换后图像的宽度 imgn=zeros(height,width); delta_y=abs(min([pix1(1) pix2(1) pix3(1) pix4(1)])); %取得y方向的负轴超出的偏移量 delta_x=abs(min([pix1(2) pix2(2) pix3(2) pix4(2)])); %取得x方向的负轴超出的偏移量 for i=1-delta_y:height-delta_y for j=1-delta_x:width-delta_x pix=[i j 1]/rot; %用变换后图像的点的坐标去寻找原图像点的坐标, %否则有些变换后的图像的像素点无法完全填充 float_Y=pix(1)-floor(pix(1)); float_X=pix(2)-floor(pix(2)); if pix(1)>=1 && pix(2)>=1 && pix(1) <= h && pix(2) <= w pix_up_left=[floor(pix(1)) floor(pix(2))]; %四个相邻的点 pix_up_right=[floor(pix(1)) ceil(pix(2))]; pix_down_left=[ceil(pix(1)) floor(pix(2))]; pix_down_right=[ceil(pix(1)) ceil(pix(2))]; value_up_left=(1-float_X)*(1-float_Y); %计算临近四个点的权重 value_up_right=float_X*(1-float_Y); value_down_left=(1-float_X)*float_Y; value_down_right=float_X*float_Y; imgn(i+delta_y,j+delta_x)=value_up_left*img(pix_up_left(1),pix_up_left(2))+ ... value_up_right*img(pix_up_right(1),pix_up_right(2))+ ... value_down_left*img(pix_down_left(1),pix_down_left(2))+ ... value_down_right*img(pix_down_right(1),pix_down_right(2)); end end end subplot(1,2,1);imshow(img);title('原图像'); subplot(1,2,2);imshow(uint8(imgn));title(sprintf('双线性插值%d度旋转结果',angle)); imwrite(uint8(imgn),'rotation.jpg');
- 缩放操作代码:
%此为控制台调用程序 %zoom('a.png',1.5,1) function zoom( input_img,x,y ) %input_img为输入图片;x,y为放大倍数 %[X, map] = imread(...) 读取索引图像X以及与之对应的颜色表到map中。颜色表中的值将归一化到[0,1]之间。 [I,~] = imread(input_img); input_img = imread(input_img); %获取原图像的长宽 [width,height,~] = size(I); %计算新图像的长宽;round()四舍五入 new_width = round(width*x); new_height = round(height*y); %figure();生成一个新窗口 figure(); imshow(input_img); title(['原图像(大小: ',num2str(width),'*',num2str(height),')']); %双线性差值法 for i = 1:new_width for j = 1:new_height %x,y为放大倍数 %原来图像的坐标,向下取整 tempx = floor((i-1)/x); tempy = floor((j-1)/y); %对四条边和四个顶点进行处理,将原坐标转换成调整后的坐标。 %将(1,j)调整为(1,tempy+1),(i,1)调整为(tempx+1,1) if tempx == 0 || tempy == 0 || tempx == width-1 || tempy == height-1 output_img(1,j,:) = input_img(1,tempy+1,:); output_img(i,1,:) = input_img(tempx+1,1,:); %对其余像素进行处理 else %计算原图像坐标减去新图像坐标的小数部分为其余像素点 a = (i-1) / x - tempx; b = (j-1) / y - tempy; %保证此图像中坐标最小值为1 tempx = tempx+1; tempy = tempy+1; %双线性插值计算公式变形 output_img(i,j,:) = input_img(tempx,tempy,:)*(1-a)*(1-b)+input_img(tempx,tempy+1,:)*(1-a)*b... +input_img(tempx+1,tempy,:)*a*(1-b)+input_img(tempx+1,tempy+1,:)*a*b; end end end figure(); imshow(output_img); title(['缩放后的图像(大小: ',num2str(new_width),'*',num2str(new_height),')']); imwrite(output_img,'resize2.jpg'); end
- 实验结果:
图1-1 图像放大结果
图1-2 图像缩小结果
图 1-3 图像旋转结果
- 实验心得:
在这次实验当中,我们学习了双线性插值算法,并在此基础之上将其编程,将其以MATLAB代码的形式进行体现,且更进一步地编写了将图片进行缩放与旋转的代码。在编写过程中,可以发现无论是缩放操作的代码,还是旋转操作的代码,都需要获取图像四个角顶点的坐标,并通过插值算法对其进行操作,将其转化为我们所需要得到的图片的角定点的坐标。
Matlab的官方工具库里其实本身也有对图片进行缩放与旋转的函数:
- imresize(image,m,method)函数可以进行对图片的缩放:
image为需要进行处理的图片;m为缩放的倍数(m>1时放大,m<1时缩小);method用于指定插值的方法,可选值为“nearest”(默认)最近邻插值、“bilinear”双线性插值、“bicubic”双三次插值。
- imrotate(image,angle,method,bbox)函数可以进行对图片的旋转:
image为需要进行处理的图片;angle为旋转的倍数(输入整数,角度制,默认逆时针);method用于指定插值的方法,可选值为“nearest”(默认)最近邻插值、“bilinear”双线性插值、“bicubic”双三次插值;bbox用于指定返回图像的尺寸,可选值为“loose”(默认)输出足够容纳整个旋转图像的图像B,“crop”输出的图像与输入的图像保持同样的尺寸。
参考博客:
1.MATLAB学习之图片放大缩小(双线性插值法)_CTR_cg的博客-CSDN博客_matlab双线性插值缩小图像
2.Matlab学习笔记——双线性插值旋转图像_HelloAndy_的博客-CSDN博客_matlab双线性插值旋转图像