执行一般的二维空间变换包括如下三步:
1. 定义空间变换的参数;
2. 创建变换结构体TFORM,它定义了你所要执行变换的类型;
TFORM结构体包含了执行变换需要的所有参数。你可以定义很多类型的空间变换,包括放射变换affine transformations(如平移translation,缩放scaling,旋转rotation,剪切shearing)、投影变换projective transformations和自定义的变换custom transformations。
创建结构体的方法有两种:使用maketform或者使用cp2tform。
3. 执行变换。
通过将要变换的图像和TFORM结构体传递给imtransform函数即可实现变换。
用图来表示就是
下面以一个简单的平移仿射变换来展示空间变换的使用方法。
Step 1: 导入要变换的图像
Matlab提供了一个棋盘图像,可以以此作为例子,它的调用函数为checkerboard,它将创建一个80X80像素的图像。
% 导入图像
cb = checkerboard;
figure
imshow(cb)
Step 2: 定义空间变换
定义二维的空间变换需要一个3X3的变换矩阵,也可以通过在输入图像和输出图像上指定对应点的方式由maketform自动创建变换矩阵。
这里使用如下的变换矩阵来定义空间平移变换
% 定义变换矩阵
xform = [ 1 0 0
0 1 0
20 40 1 ];
在这个矩阵中,xform(3, 1)定义了图像在水平方向上平移的像素数,xform(3, 2)定义了图像在垂直方向上平移的像素数。
Step 3: 创建TFORM结构体
使用maketform函数可以创建TFORM结构体,参数为希望执行变换的类型和变换矩阵。
% 创建TFORM结构体
tform_translate = maketform('affine', xform);
Step 4: 执行变换
使用imtransform函数执行变换,参数为要变换的图像和TFORM结构体,函数将返回变换后的图像。
% 执行变换
[cb_trans xdata ydata]= imtransform(cb, tform_translate);
返回值中包含的另两个额外输出参数xdata和ydata,表示输出图像在输出坐标空间的位置。xdata包含了输出图像拐角处像素的x坐标,ydata包含了这些像素的y坐标(这里说的x、y坐标是指像素的中点)。
下图展示了平移变换的效果,可以看到,(1, 1)点的像素转移到了(41, 41)的位置,注意那一点的像素值没有变。
imtransform函数决定输出图像的像素值是把新位置映射回输入图像的相应位置。在平移变换中,由于图像的大小和旋转角度没有变,所以是一一映射;对于其他类型的变换,如放缩、旋转,此函数将在输入图像上插值计算输出图像的像素值。学过图像处理的这个应该很清楚。
Step 5: 观察输出图像
使用如下语句显示变换后的图像
% 显示变换结果
figure
imshow(cb_trans)
从结果看来,貌似变换没有效果,变换后图像和原图像是一样的。但如果你检查xdata和ydata的数值,就会看到图像的空间坐标已经改变了。原始图像左上角的坐标由(1, 1)变为了(41, 41),右下角由(80, 80)变为了(120, 120),40已经被加到了每个像素的空间坐标上。
>> xdata
xdata =
41 120
>> ydata
ydata =
41 120
而显示结果上没有变化的原因是函数imtransform得到的输出图像足够包含了变换后的图像,但没有包含全部的坐标空间。要看到变换的效果,需要使用imtransform函数的额外输入参数来指定输出图像的大小和能包含输出图像的输出空间。
下面的代码使用了XData和YData两个额外参数来指定能包含输出图像的输出空间,而对于输出空间中不在输出图像上的像素默认为黑色,这可以通过改变imtransform函数的FillValues参数来指定。
% 修正的变换结果
cb_trans2 = imtransform(cb, tform_translate,...
'XData', [1 (size(cb,2)+ xform(3,1))],...
'YData', [1 (size(cb,1)+ xform(3,2))]);
figure,
imshow(cb_trans2)
下面来讨论定义空间变换的两种方式:使用变换矩阵和使用对应点。
Maketform函数可以接受一个N维的变换矩阵来产生TFORM结构体。而由于imtransform只能做二维变换,故只能指定3X3的转换矩阵。
如使用3X3的矩阵来指定任何的仿射变换,而对于仿射变换,最后一列必须是0 0 1,所以你指定3X2的矩阵就足够了,在这种情况下,imtransform会自动添加第三列。
下面的表格列举了imtransform可以执行的仿射变换以及相应矩阵的定义方法。
除了指定变换矩阵,你还可以通过使用对应点来定义一个变换,让maketform自动生成变换矩阵。
要对一个仿射变换使用此方法,需要在输入、输出图像上拾取3对非线性的点,而对于投影变换,则需要指定四对点。如
in_points = [11 11;21 11; 21 21];
out_points = [51 51;61 51;61 61];
tform2 = maketform('affine', in_points, out_points);
有了上面的变换数据,就可以用maketform创建TFORM结构体了,也可以使用cp2tform函数来创建,具体详见Image Registration。
在使用 maketform 创建 TFORM 结构时,需要指定必要的变换方式。如要做平移变换需要指定为仿射变换方式,除此 maketform 还支持投影变换,另外可以使用 custom 和 composite 选项来指定任意的空间变换。下表列出了 maketform 支持的变换类型
有了上面的TFORM结构体,就可以调用imtransform执行变换了。正如上面例子中所使用的那样
[cb_trans xdata ydata]= imtransform(cb, tform_translate);
另外,imtransform函数还支持几个可选输入参数来控制转换的不同效果,如输出图像的大小、填充值等。上面例子中的XData和YData就是控制输出图像大小的输入参数。对于填充值可以如下设置。
当执行一个变换时,输出图像上有很多像素不在位于原输入图像的位置,这些像素必须被赋予一些值,这就是填充值。默认情况下,imtransform函数设置这些像素为0,显示为黑色。而通过使用FillValues参数可以指定不同的颜色。
如果待转换的图像是灰度图像,就需要指定一个标量值来设置灰度的阴暗度。如下
cb_fill = imtransform(cb, tform_translate,...
'XData', [1 (size(cb,2)+xform(3,1))],...
'YData', [1 (size(cb,1)+xform(3,2))],...
'FillValues', .7 );
Figure
imshow(cb_fill)
得到结果为
对于RGB彩色图像,可以使用一个标量值或者一个1X3的向量。如果使用标量,imtransform会使用相应阴暗度的灰度值来填充;如果使用向量,则会将其按RGB彩色值来使用。
% 彩色图像处理
rgb = imread('onion.png');
xform = [ 1 0 0
0 1 0
40 40 1 ];
tform_translate = maketform('affine',xform);
cb_rgb = imtransform(rgb, tform_translate,...
'XData', [1 (size(rgb,2)+xform(3,1))],...
'YData', [1 (size(rgb,1)+xform(3,2))],...
'FillValues', [187;192;57]);
figure
imshow(cb_rgb)
结果如下