《opencv学习笔记》-- 仿射变换

仿射变换代表的是两幅图像之间的映射关系

仿射变换是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。它保持了二维图形的“平直性”(即:直线经过变换之后依然是直线)和“平行性”(即:二维图形之间的相对位置关系保持不变,平行线依然是平行线,且直线上点的位置顺序不变)。

一个任意的仿射变换都能表示为乘以一个矩阵(线性变换)接着再加上一个向量(平移)的形式   

仿射变换三种常见的变换形式:

        旋转,rotation (线性变换)

        平移,translation(向量加)

        缩放,scale(线性变换)

通常使用2 x 3的矩阵来表示仿射变换:

《opencv学习笔记》-- 仿射变换_第1张图片

 

仿射变换的求法:

使用场景:

<1> 已知 X和T,而且我们知道他们是有联系的,求出矩阵 M

<2> 已知 M和X,求 T。用算式T = M·X. 对于这种联系的信息可以用矩阵 M 清晰的表达 (即给出明确的2×3矩阵) 或者也可以用两幅图片点之间几何关系来表达。

矩阵M 联系着两幅图片,就以 其表示两图中各三 点直接的联系为例。
《opencv学习笔记》-- 仿射变换_第2张图片

 

图中,点1, 2,3与image2中的点一 一映射。
void warpAffine(InputArray src,  OutputArray dst,  InputArray M,  
                Size dsize, int flags = INTER_LINEAR,  
                int borderMode = BORDER_CONSTANT, 
                const Scalar& borderValue = Scalar())

对图像做放射变换。

dst(x, y) = src(M11x + M12y + M13,   M21x + M22y + M23)

参数1,InputArray类型的src,源图像,Mat类的对象。

参数2,运算结果,需和源图片有一样的尺寸和类型。

参数3,InputArray类型的M,2×3的变换矩阵。

参数4,Size类型的dsize,表示输出图像的尺寸。

参数5,int类型的flags,插值方法的标识符。参数有默认值INTER_LINEAR(线性插值),可选的插值方式如下:

        INTER_NEAREST            最近邻插值

        INTER_LINEAR                线性插值(默认值)

        INTER_AREA                    区域插值

        INTER_CUBIC                   三次样条插值

        INTER_LANCZOS4            Lanczos插值

        WARP_FILL_OUTLIERS   填充所有输出图像的象素。 如果部分象素落在输入图像的边

                                                    界外,那么它们的值设定为 fillval.

        WARP_INVERSE_MAP    表示M为输出图像到输入图像的反变换,即 因此可以直接用

                                                  来做象素插值。否则, warpAffine函数从M矩阵得到反变换。

参数6,int类型的borderMode,边界像素模式,默认值为BORDER_CONSTANT。

参数7,在恒定的边界情况下取的值,默认值为Scalar(),即0。

计算二维旋转变换矩阵。变换会将旋转中心映射到它自身:

Mat getRotationMatrix2D(Point2f center, double angle, double scale)

参数1,表示源图像的旋转中心。

参数2,旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)。

参数3,缩放系数。

计算二维三角变换矩阵

Mat getAffineTransform( InputArray src, InputArray dst );

参数1,InputArray类型的src,原来三个点的坐标;

参数2,OutputArray类型的dst,映射后三个点的坐标;


//定义两组点,代表两个三角形
Point2f srcTriangle[3];
Point2f dstTriangle[3];

//定义一些Mat变量
Mat rotMat(2, 3, CV_32FC1);
Mat warpMat(2, 3, CV_32FC1);
Mat srcImage, dstImage_warp, dstImage_warp_rotate;

//加载源图像并作一些初始化
srcImage = imread("1.jpg", 1);
dstImage_warp = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());

//设置源图像和目标图像上的三组点以计算仿射变换
srcTriangle[0] = Point2f(0, 0);
srcTriangle[1] = Point2f(static_cast(srcImage.cols - 1), 0);
srcTriangle[2] = Point2f(0, static_cast(srcImage.rows - 1));
 
dstTriangle[0] = Point2f(static_cast(srcImage.cols*0.0),
                         static_cast (srcImage.rows*0.33));
dstTriangle[1] = Point2f(static_cast(srcImage.cols*0.65), 
                         static_cast(srcImage.rows*0.35));
dstTriangle[2] = Point2f(static_cast(srcImage.cols*0.15), 
                         static_cast(srcImage.rows*0.6));

//求得仿射变换
warpMat = getAffineTransform(srcTriangle, dstTriangle);

//对源图像应用求得的仿射变换
warpAffine(srcImage, dstImage_warp, warpMat, dstImage_warp.size());

//对图像进行缩放后再旋转
// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵
Point center = Point(dstImage_warp.cols / 2,  dstImage_warp.rows / 2);
double angle = -30.0;
double scale = 0.8;

// 通过上面的旋转细节信息求得旋转矩阵
rotMat = getRotationMatrix2D(center, angle, scale);

// 旋转已缩放后的图像
warpAffine(dstImage_warp, dstImage_warp_rotate, rotMat, dstImage_warp.size());

你可能感兴趣的:(opencv,opencv)