图像处理刚体变换

2019-10-04 19:01:53 Vichael_Chan 阅读数 375

数字图像处理:图像变换的基本模型

一、常用图象的变换模型

变换模型是指根据待匹配图像与背景图像之间几何畸变的情况,所选择的能最佳拟合两幅图像之间变化的几何变换模型。可采用的变换模型有如下几种:刚性变换、仿射变换、透视变换和非线形变换等,如下图:
在这里插入图片描述
(1) 刚体变换
如果一幅图像中的两点间的距离经变换到另一幅图像中后仍然保持不变,则这种变换称为刚体变换(Rigid Transform)。刚体变换仅局限于平移、旋转和反转(镜像)。在二维空间中,点(x,y)力经过刚体变换到点(x’,y’)的变换公式为:
在这里插入图片描述
(2) 仿射变换
如果一幅图像中的直线经过后映射到另一幅图像上仍为直线,并且保持平行关系,则这种变换称为仿射变换(Affine Transform。仿射变换适应于平移、旋转、缩放和反转(镜像)情况。可以用以下公式表示:
在这里插入图片描述
(3) 投影变换
如果一幅图像中的直线经过后映射到另一幅图像上仍为直线,但平行关系基本不保持,则这种变换称为投影变换(Projective Transform )。二维平面投影变换是关于齐次三维矢量的线性变换,在齐次坐标系下,二维平面上的投影变换具体可用下面的非奇异3x3矩阵形式来描述,即:
在这里插入图片描述

(4) 非线性变换
非线性变换又称为弯曲变换(Curved Transform),经过非线性变换,一幅图像上的直线映射到另一幅图像上不一定是直线,可能是曲线,在二维空间中,可以用以下公式表示:
在这里插入图片描述
在得到两幅图像间的变换模型参数后,要将输入图像做相应参数的变换使之与参考图像处于同一坐标系下,则可实现目标图像与背景的图像的匹配,这里目标图像变换后所得点坐标不一定为整像素数,此时应进行插值处理。

2016-06-07 15:37:10 shenshen211 阅读数 1270

From:  遥感图像拼接算法研究






           




1 刚体变换




2  仿射变换



3  投影变换

      投影变换(Projective Transformation)是指变换过程中,图像中的直线只保持“平



4  非线性变换

2016-05-23 14:37:51 lpsl1882 阅读数 3176

图像几何变换基础

    我们实际获取的图像,常常因为各种原因,相对于原图有一定的几何形变,或者出于处理考虑,需要进行几何变换。二维图像坐标的几何变换写为:(x,y)=r(x,y)。根据图像几何变换的程度,可以将图像几何变换划分为如下几类:

  • 刚体变换 如果一幅图像中的两点间的距离经变换到另一幅图像中后仍然保持不变,则这种变换称为刚体变换(Rigid Transform)。刚体变换仅局限于平移、旋转和反转(镜像)。
  • 仿射变换 如果一幅图像中的直线经过后映射到另一幅图像上仍为直线,并且保持平行关系,则这种变换称为仿射变换(Affine Transform。仿射变换适应于平移、旋转、缩放和反转(镜像)情况。
  • 投影变换 如果一幅图像中的直线经过后映射到另一幅图像上仍为直线,但平行关系基本不保持,则这种变换称为投影变换(Projective Transform )。
  • 非线性变换 非线性变换又称为弯曲变换(Curved Transform)或者弹性变换,经过非线性变换,一幅图像上的直线映射到另一幅图像上不一定是直线,可能是曲线。

广义来讲,非线性变换包含投影变换;投影变换包含仿射变换;仿射变换包含刚体变换。非线性变换下,新旧坐标的一类简单的表达式写为:

xkykwk=a11xmk+a12xm1kyk+...a1mymk+a1wk=a21xmk+a22xm1kyk+...a2mymk+a2wk=a31xmk+a32xm1kyk+...a3mymk+a3wk,n=1,2,3...(1)

在投影变换范围下,新旧坐标的变换呈线性,表达式较为简单:
xkykwk=a1xk+a2yk+a3wk=a4xk+a5yk+a6wk=a7xk+a8yk+a9wk,k=1,2,3...n(2)

same as x1x2x3...xny1y2y3ynw1w2w3wn=a1a4a7a2a5a8a3a6a9x1x2x3...xny1y2y3ynw1w2w3wnB=AX(3)

A称为空间变换矩阵。其中[a1a4a2a5]控制旋转、缩放和斜切,[a7a8]控制平移,[a3a6]控制透视变换;w是归一化因子,要求wkwk都是1,在特殊情况下为了便于分析可以不为1。三维图像空间变换同理,扩展出z变量,组成一个4×4的变换矩阵即可。
    如果我们知道需要做何种变换,直接在单位空间变化矩阵上修改相应系数即可;如果我们不知道图像相比原图像做了什么变换,那么就需要设法获取图像的变换信息。常见的方法是手工标记前后两幅图像中的对应特征点,根据特征点的变换来计算得到变换的矩阵。
    我这里的计算限制于透视变换,或者非弹性变换。当我们获取足够的变换特征点信息,就可以计算变换矩阵,方法是求解(2)式中的系数矩阵A。这里单独看方程式很像求解多元一次方程组,但是多元一次方程组求解的是x,y而不是系数;求解系数矩阵的一个著名方法,前面在【机器学习】线性回归小结提到,即最小二乘法。
   假设我要变换一个256x256的图像,目标图像的四个边角坐标为(0,0),(180,75),(255,255),(75,180)。由于图像通常是方形的,因此四个边角点可以作为变换特征点。在《数字图像处理》书中,对四边形的空间变换使用了双线性方程来描述,这里我们直接使用空间变换矩阵,写成:
0180255750752551801111=a1a4a7a2a5a8a3a6a902552550002552551111
用最小二乘法得到
A0.7060.29400.2940.7060001

原图
原图
空间变换
变换后

2014-02-22 20:54:38 lxy201700 阅读数 2383

一、仿射变换

       仿射变换的性质:平面上任意两条直线,经仿射变换后,仍然保持平行。

仿射变换的功能,是一种二维坐标到二维坐标之间的线性变换,保持二维图形的“平直性”(straightness,即变换后直线还是直线不会打弯,圆弧还是圆弧)和“平行性”(parallelness,其实是指保二维图形间的相对位置关系不变,平行线还是平行线,相交直线的交角不变)。仿射变换可以通过一系列的原子变换的复合来实现,包括:平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和剪切(Shear)。

       此类变换可以用一个3×3的矩阵来表示,其最后一行为(0, 0, 1)。该变换矩阵将原坐标(x, y)变换为新坐标(x', y'),这里原坐标和新坐标皆视为最末一行为(1)的三维列向量,原列向量左乘变换矩阵得到新的列向量:

[x']     [a00 a01       a02] [x]      [a00*x+a01*y+a02]

[y'] = [a10 a11 a12] [y] = [a10*x+a11*y+a12]

[1 ]         [0    0 1] [1]      [ 1           ]

仿射变换的矩阵由图像上不共线的三个点的坐标确定,看做2*3的矩阵。

       几种典型的仿射变换:

平移变换,将每一点移动到(x+tx, y+ty),变换矩阵为:

[ 1 0 tx   ]

[ 0 1 ty   ]

[ 0 0 1 ]

平移变换是一种“刚体变换”,就是不会产生形变的理想物体,平移当然不会改变二维图形的形状。同理,下面的“旋转变换”也是刚体变换,而“缩放”、“错切”都是会改变图形形状的。

缩放变换,将每一点的横坐标放大(缩小)至sx倍,纵坐标放大(缩小)至sy倍,变换矩阵为:

[ sx 0 0 ]

[ 0 sy 0 ]

[ 0 0 1 ]

剪切变换,变换矩阵为:

[ 1 shx 0 ]

[   shy 1 0 ]

[ 0     0 1 ]

相当于一个横向剪切与一个纵向剪切的复合,即

[ 1    0 0 ][ 1 shx 0 ]

[   shy 1 0 ][ 0     1     0 ]

[ 0    0 1 ][ 0 0     1 ]

“剪切变换”又称“错切变换”,指的是类似于四边形不稳定性那种性质,街边小商店那种铁拉门都见过吧?想象一下上面铁条构成的菱形拉动的过程,那就是“错切”的过程。

旋转变换原点,目标图形围绕原点顺时针旋转theta弧度,变换矩阵为:

[ cos(theta) -sin(theta) 0 ]

[ sin(theta)     cos(theta) 0 ]

[    0          0          1 ]

旋转变换,目标图形以(x, y)为轴心顺时针旋转theta弧度,变换矩阵为:

[ cos(theta) -sin(theta) x-x*cos+y*sin]

[ sin(theta)     cos(theta) y-x*sin-y*cos ]

[    0               0           1       ]

相当于两次平移变换与一次原点旋转变换的复合:

[1   0   -x] [cos(theta)   -sin(theta)   0] [1   0   x]

[0   1   -y] [sin(theta) cos(theta)   0] [0   1   y]

[0   0   1 ] [     0         0        1 ] [0   0   1]

opencv中的实现函数:

void cvWarpAffine( const CvArr* src, CvArr* dst, const CvMat* map_matrix,

                    int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,

                   CvScalar fillval=cvScalarAll(0) );

实现图像的仿射变换,map_matrix是2*3的仿射矩阵,要求输入和输出图像有相同的数据类型。

通过下面两个函数得到仿射矩阵:

CvMat* cvGetAffineTransform( const CvPoint2D32f* src, const CvPoint2D32f* dst,

CvMat* map_matrix ); //由三个不共线的点得到,这样才具有唯一性

CvMat* cv2DRotationMatrix( CvPoint2D32f center, double angle, double scale,

CvMat* map_matrix ); //由旋转中心,旋转角度和各向通行因子,矩阵如下:

[ a b (1-a)*center.x-b*center.y ]

[-b a b*center.x-(1-a)*center.y ] 其中:a=scale*cos(angle), b=scale*sin(angle)

void cvGetQuadrangleSubPix( const CvArr* src, CvArr* dst, const CvMat* map_matrix );

实现图像的仿射变换,使用于亚像素。

实现图像旋转的例子

#include "cv.h"  
#include "highgui.h"  
#include "math.h"  
int main(int argc, char* argv[])  
{  
	IplImage *src = 0;  
	IplImage *dst = 0;  
	IplImage *dst1 = 0;  

	/* the first command line parameter must be image file name */  
		src = cvLoadImage ("src.jpg", CV_WINDOW_AUTOSIZE);  
		int delta = 1;  
		int angle = 0;  
		int opt = 0;            
		// 1: 旋转加缩放 
		// 0: 仅仅旋转  
		double factor;  

		dst = cvCloneImage (src);  
		dst1 = cvCloneImage (src);  
		cvNamedWindow ("src", 1);  
		cvShowImage ("src", src);  

		for (;;)  
		{  
			float m[6];  
			// Matrix m looks like:  
			//  
			// [ m0 m1 m2 ] ===> [ A11 A12   b1 ]  
			// [ m3 m4 m5 ]       [ A21 A22   b2 ]  
			//  
			CvMat M = cvMat (2, 3, CV_32F, m);  
			int w = src->width;  
			int h = src->height;  
			if (opt)           // 旋转加缩放  
				factor = (cos (angle * CV_PI / 180.) + 1.0) * 2;  
			else                // 仅仅旋转  
				factor = 1;  
			m[0] = (float) (factor * cos (-angle * 2 * CV_PI / 180.));  
			m[1] = (float) (factor * sin (-angle * 2 * CV_PI / 180.));  
			m[3] = -m[1];  
			m[4] = m[0];  
			// 将旋转中心移至图像中间  
			m[2] = w * 0.5f;  
			m[5] = h * 0.5f;  
			// dst(x,y) = A * src(x,y) + b  
			cvZero (dst);  
			cvGetQuadrangleSubPix (src, dst, &M);  
			cvNamedWindow ("dst", 1);  
			cvShowImage ("dst", dst);  
			if (cvWaitKey (1) == 27)       //ESC  
				break;  
			angle = (int) (angle + delta) % 360;  
		}                   // for-loop  
	 
	return 0;  
}  

两个函数的区别:

前者要求输入和输出图像具有相同的数据类型,有更大的资源开销(因此对小图像不太合适)且部分输出图像可以保持不变。

后者可以精确的从8位图像中提取四边形到浮点数缓存区中,具有比较小的系统开销,且总是全部改变输出图像的内容。

实验:使用例子中的仿射矩阵使用前者进行仿射变换,效果是不一样的。

对于前者:

[ m0 m1 m2 ]

[ m3 m4 m5 ]

       m0 = factor * cos (angle);

       m1 = factor * sin (angle);

       m3 = - factor * sin (angle);

       m4 = factor * cos (angle);

       m2 = x * (1- factor * cos (angle)) – y * factor * sin (angle); //x * (1-m0) – y * m1

       m5 = y * (1- factor * cos (angle)) + x * factor * sin (angle); //y * (1-m0) + x* m1

图像逆时针旋转Angle弧度。如果factor=1,图像不进行缩放,factor>1,图像会放大显示,factor<1,图像缩小显示。(m2,m5)由(x,y)确定,表示源图像以(x,y)位置为中心,对图像进行缩放和旋转。部分没有灰度值的区域的元素灰度值置0。以上矩阵可以通过函数cv2DRotationMatrix( cvPoint2D32f(x, y), angle, factor, map_matrix ); 其中,CvMat* map_matrix。直观上,先将变换后的图像保存为与源图像一样大小的,然后从左上角开始取出与目的图像一样大小的图像,作为输出结果,没有灰度值的置为0。

对于后者:

[ m0 m1 m2 ]

[ m3 m4 m5 ]

       m0 = factor * cos (angle); //同前

       m1 = factor * sin (angle); //同前

       m3 = - factor * sin (angle); //同前

       m4 = factor * cos (angle); //同前

       m2 = x;

       m5 = y;

以上表示:图像顺时针旋转Angle弧度。如果factor=1,图像不进行缩放,factor>1,图像会缩小显示,factor<1,图像放大显示。(m2,m5):表示将源图像中的(m2,m5)位置移动到新图像的中心位置,然后在新图像的中心位置处对图像进行缩放和旋转。部分没有灰度值的区域会使用附近的边界灰度值进行插值。根据输出图像的大小,直观上,输出前面旋转好后图像中心位置向外扩展的输出图像大小的图像部分,没有灰度值的部分进行插值。

二、透视变换

opencv中的实现函数:

void cvWarpPerspective( const CvArr* src, CvArr* dst, const CvMat* map_matrix, int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, CvScalar fillval=cvScalarAll(0));

实现透视变换,map_matrix是3*3的变换矩阵,有下面函数可得到:

CvMat* cvGetPerspectiveTransform( const CvPoint2D32f* src, const CvPoint2D32f* dst, CvMat* map_matrix ); //用四边形的四个点得到

三、二次线性变换

目前为止还没使用过。

程序运行结果是图片进行360°不间断旋转。




                                    
2019-07-10 21:14:13 qq_33590958 阅读数 705

一、常用的图像变换模型
:刚性变换、仿射变换、透视变换和非线形变换等。如下图所示:
在这里插入图片描述
进一步理解
在这里插入图片描述
(1) 刚体变换 
如果一幅图像中的两点间的距离经变换到另一幅图像中后仍然保持不变,则这种变换称为刚体变换(Rigid Transform)。刚体变换仅局限于平移、旋转和反转(镜像)。
(2)仿射变换
如果一幅图像中的直线经过变换到另一幅图像上仍为直线,并且保持平行关系,则这种变换称为仿射变换(Affine Transform。仿射变换适应于平移、旋转、缩放和反转(镜像)情况。
(3) 投影变换 
如果一幅图像中的直线经过后映射到另一幅图像上仍为直线,但平行关系基本不保持,则这种变换称为投影变换(Projective Transform )。

二、接下来主要讨论仿射变换
Affine Transformation是一种二维坐标到二维坐标之间的线性变换,保持二维图形的“平直性”(译注:straightness,即变换后直线还是直线不会打弯,圆弧还是圆弧)和“平行性”(译注:parallelness,其实是指保二维图形间的相对位置关系不变,平行线还是平行线)。
在这里插入图片描述
仿射变换可以通过一系列的原子变换的复合来实现,包括:平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和剪切(Shear)。如下图所示:
在这里插入图片描述
仿射变换用下式表示:
在这里插入图片描述
对上面表示的解释,如下图所示:
在这里插入图片描述
这和平时见到的仿射变换不太一样,但是差别也不大,只是矩阵部分最后多了一行元素,以构成齐次坐标。
所谓齐次坐标,简而言之,就是用N+1维来代表N维坐标。我们可以在一个2D笛卡尔坐标末尾加上一个额外的变量w来形成2D齐次坐标,因此,一个点(X,Y)在齐次坐标里面变成了(x,y,w),并且有
X = x/w
Y = y/w
例如,笛卡尔坐标系下(1,2)的齐次坐标可以表示为(1,2,1),如果点(1,2)移动到无限远处,在笛卡尔坐标下它变为(∞,∞),然后它的齐次坐标表示为(1,2,0),因为(1/0, 2/0) = (∞,∞),这样我们可以不用”∞"来表示一个无穷远处的点了。此外,我们把齐次坐标转化为笛卡尔坐标的方法是前面n-1个坐标分量分别除以最后一个分量即可。

几种典型的仿射变换如下:
平移变换 Translation
将每一点移动(x+tx,y+ ty),变换矩阵为:
在这里插入图片描述
平移变换是一种“刚体变换”,rigid-body transformation,就是不会产生形变的理想物体。
效果如下:
在这里插入图片描述
缩放变换(Scale)
将每一点的横坐标放大(缩小)至sx倍,纵坐标放大(缩小)至sy倍,变换矩阵为:
在这里插入图片描述
效果如下:
在这里插入图片描述

剪切变换(Shear)(关于这个,不是看得太明白,主要是剪切这个地方,在这里剪切是何意?)
变换矩阵为:
在这里插入图片描述
相当于一个横向剪切与一个纵向剪切的复合
在这里插入图片描述
效果如下:
在这里插入图片描述
旋转变换(Rotation)
目标图形围绕原点顺时针旋转theta弧度,变换矩阵为:
在这里插入图片描述
效果如下:
在这里插入图片描述
组合(即多种变换同时进行,而不是单单执行一种变换)
旋转变换,目标图形以(x, y)为轴心顺时针旋转theta弧度,变换矩阵为:
在这里插入图片描述
相当于两次平移变换与一次原点旋转变换的复合:
在这里插入图片描述
相当于是先移动到中心节点,然后旋转,然后再移动回去。

一些常用变换矩阵如下:
在这里插入图片描述