# 7. 映射变换
变换就是把一幅图像中某个位置的像素放置到另一个图片中指定位置的过程,用一个数学公式来表示就是:
```[tex]
\texttt{g(x,y)} = f(\texttt{ h(x,y) })
```
其中的 f 就是变换方式,也就说,像素点在另一个图像中的位置是由 f 来计算的。不同方式计算得到的 f 也会得到不同的变换效果,OpenCV中有三种方式,但由于比赛原因仅介绍前两种:
- 仿射变换
- 透视变换
- 重映射
## 仿射变换
仿射变换的变换方式是,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。相对直接来说,就是源图像矩阵乘一个旋转矩阵,然后加上一个列向量,最后得到生成的新图像矩阵。从图像层面上来看,仿射变换可以使图像进行平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和错切(Shear)。
我们通常使用 `$ \texttt{3} \times \texttt{2} $` 矩阵来表示仿射变换的变换矩阵
```[tex]
A =
\left[
\begin{array}{cccc}
a_{00} & a_{01}\\
a_{10} & a_{11}
\end{array}
\right]_{\texttt{2} \times \texttt{2}}\qquad
B =
\left[
\begin{array}{cccc}
b_{00} \\ b_{10}
\end{array}
\right]_{\texttt{2} \times \texttt{1}}\\
\texttt{引入二维向量,即为一张图像}
\left[
\begin{array}{cccc}
x \\ y
\end{array}
\right]
,
T = A \cdot
\left[
\begin{array}{cccc}
x \\ y
\end{array}
\right]
+ b
\quad or \quad
T = M \cdot [x, y, 1]^{T}
```
[参考链接(知乎)](https://www.zhihu.com/question/20666664)
### 函数
#### 仿射变换
```C++
void cv::warpAffine ( InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar()
)
/**
@brief Applies an affine transformation to an image.
简介 将仿射变换应用于图像。
The function warpAffine transforms the source image using the specified matrix:
函数warpAffine使用指定的矩阵变换源图像:
*/
```
```[tex]
\texttt{dst} (x,y) = \texttt{src} ( \texttt{M} _{11} x + \texttt{M} _{12} y + \texttt{M} _{13}, \texttt{M} _{21} x + \texttt{M} _{22} y + \texttt{M} _{23})
```
```C++
/*
when the flag #WARP_INVERSE_MAP is set. Otherwise, the transformation is first inverted with #invertAffineTransform and then put in the formula above instead of M. The function cannot operate in-place.
当设置了标志#扭曲#反转#贴图时。否则,首先使用#invertAffineTransform对变换进行反转,然后将其放入上面的公式中,而不是M。该功能无法在适当位置运行。
@param src input image.
@param dst output image that has the size dsize and the same type as src .
@param M 2*3 transformation matrix.
@param dsize size of the output image.
@param flags combination of interpolation methods (see #InterpolationFlags) and the optional flag #WARP_INVERSE_MAP that means that M is the inverse transformation ( dst -> src ).
@param borderMode pixel extrapolation method (see #BorderTypes); when borderMode=#BORDER_TRANSPARENT, it means that the pixels in the destination image corresponding to the "outliers" in the source image are not modified by the function.
@param borderValue value used in case of a constant border; by default, it is 0.
@sa warpPerspective, resize, remap, getRectSubPix, transform
*/
```
仿射变换的旋转矩阵可以用两种方式得到,一种是用点与点之间的对应关系得到矩阵对应函数,即为`getAffineTransform`函数,另一种即为构建旋转矩阵,使原图像变换,即为`getRotationMatrix2D`函数。
#### 得到仿射变换核
```C++
Mat cv::getAffineTransform ( const Point2f src[],
const Point2f dst[]
)
/**
@brief Calculates an affine transform from three pairs of the corresponding points.
简介 从三对对应点计算仿射变换。
The function calculates the 2*3 matrix of an affine transform so that:
该函数计算仿射变换的2*3矩阵:
*/
```
```[tex]
\left[\begin{matrix} x^{'}_{i} \\ y^{'}_{i} \end{matrix}\right]
= \texttt{map matrix} \cdot
\left[\begin{matrix} x^{'}_{i} \\ y^{'}_{i} \\ 1 \end{matrix}\right]
\\ \textnormal{where}
\quad dst(i) = (x^{'}_{i} , y^{'}_{i}),
\quad src(i) = (x_{i} , y_{i}), \ \ i=0,1,2
```
```C++
/*
@param src Coordinates of triangle vertices in the source image.
@param dst Coordinates of the corresponding triangle vertices in the destination image.
@sa warpAffine, transform
*/
Mat cv::getAffineTransform ( InputArray src,
InputArray dst
)
/**
@overload
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
*/
```
#### 创建旋转矩阵
```C++
Mat cv::getRotationMatrix2D ( Point2f center,
double angle,
double scale
)
/**
@brief Calculates an affine matrix of 2D rotation.
简介 计算二维旋转的仿射矩阵。
The function calculates the following matrix:
该函数计算以下矩阵:
*/
```
```[tex]
\left[ \begin{matrix} \alpha & \beta & (1- \alpha ) \cdot \texttt{center.x} - \beta \cdot \texttt{center.y} \\ - \beta & \alpha & \beta \cdot \texttt{center.x} + (1- \alpha ) \cdot \texttt{center.y} \end{matrix} \right]
\\ \textnormal{where} \qquad \qquad
\begin{array}{l} \alpha = \texttt{scale} \cdot \cos \texttt{angle} , \\ \beta = \texttt{scale} \cdot \sin \texttt{angle} \end{array}
```
```C++
/*
The transformation maps the rotation center to itself. If this is not the target, adjust the shift.
变换将旋转中心映射到自身。如果这不是目标,调整档位。
@param center Center of the rotation in the source image.
@param angle Rotation angle in degrees. Positive values mean counter-clockwise rotation (the coordinate origin is assumed to be the top-left corner).
@param scale Isotropic scale factor.
@sa getAffineTransform, warpAffine, transform
*/
```
## 透视变换
透视变换是将图像从一个视平面投影到另外一个视平面的过程,所以透视变换也被称为投影映射。我们知道在图像的仿射变换中需要变换矩阵是一个`$ \texttt{2}\times\texttt{3} $`的两维平面变换矩阵,而透视变换本质上空间立体三维变换,根据其次坐标方差,要把三维坐标投影到另外一个视平面,就需要一个完全不同的变换矩阵M,所以这个是透视变换跟OpenCV中几何仿射变换最大的不同。
矩阵形式:
```[tex]
[x^{'}, y^{'}, w^{'}] = [x, y, w]
\left[\begin{matrix}
a_{11} & a_{12} & a_{13}\\
a_{21} & a_{22} & a_{23}\\
a_{31} & a_{32} & a_{33}\\
\end{matrix}\right]
```
[参考链接(CSDN)](https://blog.csdn.net/zhangjunp3/article/details/80036310)
### 函数
#### 透视变换
```C++
void cv::warpPerspective ( InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar()
)
/**
@brief Applies a perspective transformation to an image.
简介 将透视变换应用于图像。
The function warpPerspective transforms the source image using the specified matrix:
函数warpPerspective使用指定的矩阵变换源图像:
*/
```
```[tex]
\texttt{dst} (x,y) = \texttt{src} \left ( \frac{M_{11} x + M_{12} y + M_{13}}{M_{31} x + M_{32} y + M_{33}} ,
\frac{M_{21} x + M_{22} y + M_{23}}{M_{31} x + M_{32} y + M_{33}} \right )
```
```C++
/*
when the flag #WARP_INVERSE_MAP is set. Otherwise, the transformation is first inverted with invert and then put in the formula above instead of M. The function cannot operate in-place.
当设置了标志#扭曲#反转#贴图时。否则,首先使用invert对变换进行反转,然后将其放入上面的公式中,而不是M。该功能无法在适当位置运行。
@param src input image.
@param dst output image that has the size dsize and the same type as src .
@param M 3*3 transformation matrix.
@param dsize size of the output image.
@param flags combination of interpolation methods (#INTER_LINEAR or #INTER_NEAREST) and the optional flag #WARP_INVERSE_MAP, that sets M as the inverse transformation ( dst -> src ).
@param borderMode pixel extrapolation method (#BORDER_CONSTANT or #BORDER_REPLICATE).
@param borderValue value used in case of a constant border; by default, it equals 0.
@sa warpAffine, resize, remap, getRectSubPix, perspectiveTransform
*/
```
#### 获取透视变换矩阵
```C++
Mat cv::getPerspectiveTransform ( InputArray src,
InputArray dst,
int solveMethod = DECOMP_LU
)
/**
@brief Calculates a perspective transform from four pairs of the corresponding points.
简介 从四对对应点计算透视变换。
The function calculates the 3*3 matrix of a perspective transform so that:
该函数计算透视变换的3*3矩阵:
*/
```
```[tex]
\left[\begin{matrix} t_i x'_i \\ t_i y'_i \\ t_i \end{matrix}\right]
= \texttt{map matrix} \cdot
\left[\begin{matrix} x_i \\ y_i \\ 1 \end{matrix} \right]
\\ \textnormal{where}
\quad dst(i)=(x'_i,y'_i),
\quad src(i)=(x_i, y_i), i=0,1,2,3
```
```C++
/*
@param src Coordinates of quadrangle vertices in the source image.
@param dst Coordinates of the corresponding quadrangle vertices in the destination image.
@param solveMethod method passed to cv::solve (#DecompTypes)
@sa findHomography, warpPerspective, perspectiveTransform
*/
Mat cv::getPerspectiveTransform ( const Point2f src[],
const Point2f dst[],
int solveMethod = DECOMP_LU
)
/**
@overload
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
*/
```