图像的几何变换是指改变图像的几何位置、几何形状、几何尺寸等几何特征。
一.图像的平移
图像平移是将一幅图像中所有的点都按照指定的平移量在水平、垂直方向移动,平移后的图像与原图像相同。
利用齐次坐标,变换前后图像上的点P0(x0,y0)和P(x,y)之间的关系可以用如下的矩阵变换表示为

平移变换的几点说明:
①平移后图像上的每一点都可以在原图像中找到对应的点。对于不在原图像中的点,可以直接将它的像素值统一设置为0或这255(对于灰度图就是黑色或者白色);
②若图像平移后并没被放大,说明移出的部分被截断,原图像中有像素点被移出显示区域。
③若不想丢失被移出的部分图像,则将新生成的图像扩大。
代码如下:
clear all;
close all;
I = imread('lenna.jpg');
delta_x = 10; % 水平方向的偏移量
delta_y = 10; % 垂直方向的偏移量
[M N] = size(I); % 原图像的宽度和高度
I2 = zeros(M, N);
for x = 1 : M
if x + delta_x <= M
for y = 1 : N
if y + delta_y <= N
I2(x + delta_x, y + delta_y) = I(x, y);
end
end
end
end
subplot(1, 2, 1), imshow(I);
subplot(1, 2, 2), imshow(uint8(I2));
平移后的图像显示如下:

二.图像的旋转
一般图像的旋转是以图像的中心为原点,旋转一定的角度,即将图像上的所有像素都旋转一个相同的角度。
图像的旋转变换也可以用矩阵变换表示。设点P0(x0, y0)旋转θ角后的对应点为P(x, y),则变换公式为:
或者是
利用公式进行图像旋转变换时,需要注意如下两点:
①为了避免图像信息的丢失,图像旋转后必须进行平移变换。
②图像旋转之后,会出现许多空洞点,我们必须对这些空洞点进行填充处理,否则图像旋转后的效果不好,一般也将这种操作称作为插值处理。
上述的旋转是绕坐标轴原点(0,0)进行的,如果是绕某一个指定点旋转,则先要将坐标系平移到该点,再进行旋转,然后将旋转后的图像平移回原坐标系。因此,我们得到绕任一点(x0,y0)的旋转变换公式为:
x’ = (x-x0)·cos(θ) + (y-y0)·sin(θ) + x0
y’ = -(x-x0)·sin(θ) + (y-y0)·cos(θ) + y0
代码如下:
clear all;
close all;
I = imread('lenna.jpg');
H = 1; % 矩阵pix第一个元素,即高度
W = 2; % 矩阵pix第二个元素,即宽度
[M N] = size(I); % M为原图像的高度,N为原图像的宽度
theta = 30 / 180 * pi; % 旋转角度为顺时针方向30度
rot = [cos(theta) -sin(theta) 0; sin(theta) cos(theta) 0; 0 0 1]; % 变换矩阵
inv_rot = inv(rot); % 变换矩阵的逆运算
pix1 = [1 1 1] * rot; % 变换后图像左上点的坐标
pix2 = [1 N 1] * rot; % 变换后图像右上点的坐标
pix3 = [M 1 1] * rot; % 变换后图像左下点的坐标
pix4 = [M N 1] * rot; % 变换后图像右下点的坐标
height = round(max([abs(pix1(H) - pix4(H)) abs(pix2(H) - pix3(H))]) + 0.5); % 变换后图像的高度
width = round(max([abs(pix1(W) - pix4(W)) abs(pix2(W) - pix3(W))]) + 0.5); % 变换后图像的宽度
delta_y = abs(min([pix1(H) pix2(H) pix3(H) pix4(H)])); % y方向负轴超出的偏移量
delta_x = abs(min([pix1(W) pix2(W) pix3(W) pix4(W)])); % y方向负轴超出的偏移量
I2 = zeros(height, width);
for y = 1 - delta_y : height - delta_y
for x = 1 - delta_x : width - delta_x
pix = [y x 1] * inv_rot;
if pix(H) > 0.5 && pix(W) > 0.5 && pix(H) < M && pix(W) < N
I2(y + delta_y, x + delta_x) = I(round(pix(H)), round(pix(W)));
end
end
end
subplot(1, 2, 1), imshow(I), title('原图像');
subplot(1, 2, 2), imshow(uint8(I2)), title('旋转后的图像');
旋转后的图像显示如下:

三.图像的比例缩放
图像的比例缩放变换是指给定的图像在x轴方向按比例缩放fx倍,在y轴方向缩放fy倍,从而获得一幅新的图象。比例缩放前后两点P0(x0,y0)、P(x,y)之间的关系用矩阵形式可以表现为:

在图像放大的正变换中,会出现很多的空格。因此,需要对放大后所多出来的空格填入适当的像素值。一般采用最邻近插值和线性插值法。
图像缩小代码如下:
clear all;
close all;
I = imread('lenna.jpg');
[M N] = size(I);
width = int32(0.5 * N) % 将图像宽度缩小为原来的1/2
height = int32(0.5 * M) % 将图像高度缩小为原来的1/2
I2 = uint8(zeros(height, width));
widthScale = floor(N / width);
heightScale = floor(M / height);
for y = 1 : height
for x = 1 : width
oldX = x * widthScale;
oldY = y * heightScale;
I2(y, x) = I(oldY, oldX);
end
end
a1 = subplot(1, 2, 1);
imshow(I), title('原图像');
a2 = subplot(1, 2, 2);
imshow(I2), title('缩小后的图像');
set(a2, 'XLim', get(a1, 'XLim'), 'YLim', get(a1, 'YLim')); % 将两个sunplot的x,y轴单位长度设为一样
缩小后的图像显示如下:

图像放大代码如下:
clear all;
close all;
I = imread('lenna.jpg');
[M N] = size(I);
width = 2 * N; % 将图像宽度放大为原来的2倍
height = 2 * M; % 将图像高度放大为原来的2倍
I2 = uint8(zeros(height, width));
widthScale = width / N;
heightScale = height / M;
for y = 1 : height
for x = 1 : width
oldX = round(x / widthScale);
oldY = round(y / heightScale);
if oldX == 0 oldX = 1; end
if oldY == 0 oldY = 1; end
if oldX > N oldX = N; end
if oldY > M oldY = M; end
I2(y, x) = I(oldY, oldX);
end
end
a1 = subplot(1, 2, 1);
imshow(I), title('原图像');
a2 = subplot(1, 2, 2);
imshow(I2), title('放大后的图像');
set(a1, 'XLim', get(a2, 'XLim'), 'YLim', get(a2, 'YLim')); % 将两个sunplot的x,y轴单位长度设为一样
放大后的图像显示如下:
