Matlab之山东大学数字图像处理实验二(几何变换与变形)
本文属于原创,转载请注明出处。
实验2.1:图像缩放
- 实现一个图像缩放函数,可以对输入图像进行任意倍数的缩放;
- 采用双线性插值进行重采样;
- X,Y方向的缩放倍数参函数参数的形式传入;
- 可以只考虑输入图像为3通道,8位深度的情况;
- 不能调用图像处理库的缩放函数来完成;
实验2.2:图像变形
记[x’, y’]=f([x, y])为像素坐标的一个映射,实现f所表示的图像形变。f的逆映射为:
在讲实验之前,先说一下变量,之后的变量都是这样,水平方向为height或y,垂直方向为width或x。
实验2.1:图像缩放
图像缩放要求使用双线性差值算法,算法如下:
转到二维矩阵中,除掉四条边缘线,该算法可以解释为:
设x和y为缩放倍数,i,j为新图像的某个坐标,tempx,tempy为原图像的坐标,a和b为原图像坐标减去新图像坐标的小数部分,即上图公式中的x,y两个参数,其中floor()函数为向下取整函数,他们之间的关系为:
tempx = floor((i-1)/x);
tempy = floor((j-1)/y);
a = (i-1) / x - tempx;
b = (j-1) / y - tempy;
然后上图公式就可以转化成二维矩阵的公式:
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;
当然得对四条边缘进行处理,否则矩阵会越界,具体代码如下所示:
function resize( input_img,x,y )
%RESIZE 此处显示有关此函数的摘要
% input_img为输入图像,output_img为输出图像,x,y为缩放倍数
[I,map] = imread(input_img);
input_img = imread(input_img);
%获取原图像的长宽
[width,height,dimension] = size(I);
%计算新图像的长宽
new_width = round(width*x);
new_height = round(height*y);
figure();
imshow(input_img);
title(['原图像(大小: ',num2str(width),'*',num2str(height),'*',num2str(dimension),')']);
%双线性差值法
for i = 1:new_width
for j = 1:new_height
%原来图像的坐标,向下取整
tempx = floor((i-1)/x);
tempy = floor((j-1)/y);
%对四条边和四个顶点进行处理
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),'*',num2str(dimension)',')']);
imwrite(output_img,'resize.jpg');
现在看看缩放效果:
resize('a.jpg',1.3,0.6);
实验2.2:图像变形
这里的公式在实验要求之中,这里就不多说了,直接给出代码:
function reshape(input_img)
%RESHAPE 此处显示有关此函数的摘要
% input_img为输入图像,output_img为输出图像,angle为顺时针旋转角度
[I,map] = imread(input_img);
input_img = imread(input_img);
%获取原图像的长宽
[width,height,dimension] = size(I);
for i = 1:width-1
for j = 1:height-1
%中心归一化坐标
tempx = (i-0.5*width)/(0.5*width);
tempy = (j-0.5*height)/(0.5*height);
%获取r和angle
r = sqrt(tempx^2 + tempy^2);
angle = (1-r)^2;
if r >= 1
x = tempx;
y = tempy;
else
x = cos(angle)*tempx - sin(angle)*tempy;
y = sin(angle)*tempx + cos(angle)*tempy;
end
%必须使用(uint16()函数进行处理坐标,将其转化成无符号16位的int类型,否则坐标索引会出错
old_x = uint16((x + 1)*0.5*width);
old_y = uint16((y + 1)*0.5*height);
%输出图像
output_img(i,j,:) = input_img(old_x,old_y,:);
end
end
imshow(output_img);
title('变形后的图像');
imwrite(output_img,'reshape.jpg');
end
这里唯一要注意的就是old_x = uint16((x + 1)*0.5*width);
,这个地方得将原来中心归一化后的坐标转回到原来的坐标,并且使用uint16()函数进行处理,将其转化成无符号16位的int类型,否则坐标索引会出错。
re_shape('a.jpg');
下面看看效果: