一、引言
图像的几何变换在图像处理中被经常使用,其中图像旋转又是使用频率很高的变换,不仅应用于普通的图像的处理中,也会用于机器学习中的图像数据增强。图像旋转的数学原理很简单,就是简单的矩阵乘法。
图像旋转示意图如下图所示,其中左图是旋转之前图像,右图是旋转之后的图像。
本文给出了图像旋转的详细实现过程。此外也给出了matlab软件自带的图像旋转函数imrotate的用法。
二、数学原理及公式
学过线性代数的童鞋都知道如下的矩阵表示旋转矩阵:
且当矩阵左乘向量时,表示逆时针旋转,否则表示顺时针旋转。
该旋转矩阵的由来其实也非常简单,就是用到了简单的三角公式而已。如下图所示:
假设旋转之前的坐标为(x,y),绕坐标原点旋转之后的坐标为(x*, y*),为讨论方便可以把这两组坐标点放到单位圆上。则可以得到两组坐标和角度之间的关系如下:
把右端项展开即可得:
写出矩阵形式为:
因此,对于图像旋转而言,其实就是像素的坐标旋转,像素跟着坐标走而已。
三、matlab实现图像旋转
1.旋转映射
由于图像像素旋转一定角度后,其坐标可能不再是整数坐标,而且可能会产生多个像素旋转之后对应到同一个像素而导致旋转之后的图像丢失像素。为了解决此问题,采用逆向思维,即构造一个映射,把旋转之后的像素坐标映射到原图像的像素坐标,这样就可以保证旋转之后的每个像素均有像素值。
此时旋转就变成了顺时针,因此旋转矩阵为:
由于引入了映射,即旋转变换,因此会产生非整数点的坐标,所以需要引入图像插值方法。由于本文的主要工作是图像旋转,因此仅仅采用最近邻插值方法。
2.单通道图像中心化旋转
图像旋转是以图像中心为旋转轴,因此图像在旋转之前需要把像素坐标进行中心化,然后再旋转,代码如下:
假设图像矩阵image和旋转角度angle已知,且image是单通道数据。
[ h, w ] = size( image );
im = uint8( zeros( h, w ) );%创建空的旋转图像矩阵,此处uint8是必须的
RotMatrix = [ cos(angle), -sin(angle); sin(angle), cos(angle) ];%旋转矩阵
halfH = floor( h / 2 );
halfW = floor( w / 2 );
%逐个像素计算其旋转前的位置及像素
for i = 1 : h
for j = 1 : w
coord = [ i-halfH, j-halfW ] * RotMatrix;%中心化旋转
ir = round( coord( 1 ) ) + halfH;%恢复到原图像的行坐标分量
jr = round( coord( 2 ) ) + halfW;%恢复到原图像的列坐标分量
if ir > 0 & ir <= h & jr > 0 & jr <= w
im( i, j ) = image( ir, jr ); %按照最近邻插值法获取图像数据
end
end
end
3.三通道图像中心化旋转
可以把单通道图像中心化旋转做成一个函数,然后针对R、G、B分量分别调用单通道旋转即可。
假设单通道图像旋转函数为:
function im = ImRotation( image, angle )
则三通道图像旋转可以如下实现:
imSize = size( image );
R = image( :, :, 1 );
G = image( :, :, 2 );
B = image( :, :, 3 );
imR = ImRotation( R, angle );
imG = ImRotation( G, angle );
imB = ImRotation( B, angle );
im = uint8( zeros( imSize ) );
im( :, :, 1 ) = imR;
im( :, :, 2 ) = imG;
im( :, :, 3 ) = imB;
4.完整的图像中心化旋转代码
function im = ImageRotation( image, angle )
%图像逆时针中心化旋转
imSize = size( image );
dim = numel( imSize ); %图像的维数
if( dim == 2 )%单通道图像,即灰度图像
im = ImRotation( image, angle );
else%彩色图像,即三通道图像
R = image( :, :, 1 );
G = image( :, :, 2 );
B = image( :, :, 3 );
imR = ImRotation( R, angle );
imG = ImRotation( G, angle );
imB = ImRotation( B, angle );
im = uint8( zeros( imSize ) );
im( :, :, 1 ) = imR;
im( :, :, 2 ) = imG;
im( :, :, 3 ) = imB;
%im = cat(3 ,imR, imG, imB );%将三个颜色分量合成彩色图像
end
end
%针对单通道颜色分量绕图像中心逆时针旋转
function im = ImRotation( image, angle )
[ h, w ] = size( image );
im = uint8( zeros( h, w ) );%创建空的旋转图像矩阵,此处uint8是必须的
RotMatrix = [ cos(angle), -sin(angle); sin(angle), cos(angle) ];%旋转矩阵
halfH = floor( h / 2 );
halfW = floor( w / 2 );
%逐个像素计算其旋转前的位置及像素
for i = 1 : h
for j = 1 : w
coord = [ i-halfH, j-halfW ] * RotMatrix;%中心化旋转
ir = round( coord( 1 ) ) + halfH;%恢复到原图像的行坐标分量
jr = round( coord( 2 ) ) + halfW;%恢复到原图像的列坐标分量
if ir > 0 & ir <= h & jr > 0 & jr <= w
im( i, j ) = image( ir, jr ); %按照最近邻插值法获取图像数据
end
end
end
end
5.测试上述旋转函数
clear all
clc
image = imread( '1.jpg' );
figure(1); imshow( image );
angle = pi/4;
im = ImageRotation( image, angle );
figure;imshow( im );
angle = -pi/4;
im = ImageRotation( image, angle );
figure;imshow( im );
运行结果:
四、matlab命令imrotate
语法规则:
output = imrotate( matrix, angle, method )
其中matrix是图像矩阵,可以是单通道,也可以是多通道
angle是旋转角度,单位是度°,正值为逆时针,负值为顺时针
method是插值方法,可以是nearest、bilinear等
output是旋转之后的图像。该图像将根据原图像的大小和旋转角度计算旋转之后的图像大小,以保证原图像都在视图之内。
例如:
I = imread('rice.png');
J = imrotate(I,45,'nearest');
imshow(J)
运行结果如下: