OpenCV——几何变换

目录

3.1仿射变换

3.1.1 平移

3.1.2 放大和缩小

3.1.3 旋转

3.1.4 计算仿射矩阵

3.1.5 插值算法

3.1.6 旋转函数Rotate

3.2投影变换

3.3极坐标变换

1. 将笛卡儿坐标转换为极坐标

2. 将极坐标转换为笛卡儿坐标

3. 利用极坐标变换对图像进行变换


 

3.1仿射变换

基本的仿射变换类型:平移、缩放、旋转。变换过程就是构造仿射变换矩阵A。

\left(\begin{array}{l}{\tilde{x}} \\ {\tilde{y}} \\ {1}\end{array}\right)=A\left(\begin{array}{l}{x} \\ {y} \\ {1}\end{array}\right)\boldsymbol{A}=\left(\begin{array}{ccc}{a_{11}} & {a_{12}} & {a_{13}} \\ {a_{21}} & {a_{22}} & {a_{23}} \\ {0} & {0} & {1}\end{array}\right),引入第三个数值为1的坐标,实现齐次坐标。

3.1.1 平移

(\tilde{x}, \tilde{y})=\left(x+t_{x}, y+t_{y}\right),假设任意空间坐标(\mathrm{x}, \mathrm{y}),沿x轴平移t_{x},再沿y轴平移t_{\mathrm{y}}

\left(\begin{array}{c}{\tilde{x}} \\ {\tilde{y}} \\ {1}\end{array}\right)=\left(\begin{array}{ccc}{1} & {0} & {t_{x}} \\ {0} & {1} & {t_{y}} \\ {0} & {0} & {1}\end{array}\right)\left(\begin{array}{l}{x} \\ {y} \\ {1}\end{array}\right)

3.1.2 放大和缩小

(\tilde{x}, \tilde{y})=\left(x_{0}+s_{x}\left(x-x_{0}\right), y_{0}+s_{y}\left(y-y_{0}\right)\right),显然,缩放后的坐标位置离中心点的水平距离变为原来的sx倍,离中心点的垂直距离变为原来的sy 倍。可以将该变换过程理解为先将原点平移到中心点,再以原点为中心进行缩放,然后移回坐标原点,用矩阵形式可以表示为:

\left(\begin{array}{c}{\tilde{x}} \\ {\tilde{y}} \\ {\tilde{y}}\end{array}\right)=\left(\begin{array}{ccc}{1} & {0} & {x_{0}} \\ {0} & {1} & {y_{0}} \\ {0} & {0} & {1}\end{array}\right)\left(\begin{array}{ccc}{s_{x}} & {0} & {0} \\ {0} & {s_{y}} & {0} \\ {0} & {0} & {1}\end{array}\right)\left(\begin{array}{ccc}{1} & {0} & {-x_{0}} \\ {0} & {1} & {-y_{0}} \\ {0} & {0} & {1}\end{array}\right)\left(\begin{array}{l}{x} \\ {y} \\ {1}\end{array}\right),(从右往左计算)

这里显示了齐次坐标的优势,以任意一点为中心的缩放仿射变换矩阵是平移矩阵和以(00)为中心的缩放仿射变换矩阵组合相乘而得到的。

3.1.3 旋转

首先计算顺时针旋转后的坐标 (\tilde{x}, \tilde{y})\cos \theta=\frac{x}{p}, \sin \theta=\frac{y}{p}  , 其中p代表(xy)到中心点(00)的距离,则

\cos (\theta+\alpha)=\cos \theta \cos \alpha-\sin \theta \sin \alpha=\frac{x}{p} \cos \alpha-\frac{y}{p} \sin \alpha=\frac{\tilde{x}}{p}

\sin (\theta+\alpha)=\sin \theta \cos \alpha+\cos \theta \sin \alpha=\frac{y}{p} \cos \alpha+\frac{x}{p} \sin \alpha=\frac{\tilde{y}}{p}

化简以上两个公式,可得\tilde{X}=\mathrm{x} \cos \alpha-y \sin \alpha,\tilde{y}=x \sin \alpha+y \cos \alpha用矩阵形式表示为:

\left(\begin{array}{c}{\tilde{x}} \\ {\tilde{y}} \\ {1}\end{array}\right)=\left(\begin{array}{ccc}{\cos a} & {-\sin \alpha} & {0} \\ {\sin \alpha} & {\cos \alpha} & {0} \\ {0} & {0} & {1}\end{array}\right)\left(\begin{array}{l}{x} \\ {y} \\ {1}\end{array}\right),令A=\left(\begin{array}{ccc}{\cos \theta} & {-\sin \alpha} & {0} \\ {\sin \alpha} & {\cos \theta} & {0} \\ {0} & {0} & {1}\end{array}\right)

3.1.4 计算仿射矩阵

对于空间变换的仿射矩阵有两种计算方式:解方程组法 和 基本仿射变换矩阵相乘法;

1、方程法:仿射变换矩阵有六个未知数,所以只需要三组对应位置的坐标,构造出由六个方程组成的方程组即可解六个未知数。

OpenCV提供的函数: cv2.getAffineTransform(src, dst)

就是通过方程法计算参数srcdst的对应仿射变换矩阵的。对于该函数的Py thonAPI,输入参数srcdst分别代表原坐标和变换后的坐标,且均为32列的二维ndarray每一行代表一个坐标,且数据类型必须为浮点型,否则会报错。

 2、矩阵法

上仿射变换矩阵是由平移矩阵乘以缩放矩阵得到的。需要注意的是,虽然先缩放再平移,但是仿射变换矩阵是平移仿射矩阵乘以缩放仿射矩阵,而不是缩放仿射矩阵乘以平移仿射矩阵,即等式右边的运算是从右向左进行的。

对于这种等比例缩放的仿射变换,OpenCV提供了函数:cv2.getRotationMatrix2D(center, angle, scale)

3.1.5 插值算法

显然经过仿射变换后,有些位置坐标处的函数值是无法设置的,因此需要利用已知的整数坐标处的函数值估算非整数坐标处的函数值——插值算法。

1、最近邻插值:最近邻插值就是从(xy)的四个相邻整数坐标中找到离它最近的一个函数值。

使用最近邻插值方法完成图像几何变换,输出图像会出现锯齿状外观,对图像放大处理的效果会更明显。

2、双线性插值:

OpenCV——几何变换_第1张图片

OpenCV——几何变换_第2张图片 

3、高阶的插值函数,如三次样条插值、Legendre中心函数和sinaxs)函数,高阶插值常使用二维离散卷积运算来实现。

3.1.6 旋转函数Rotate

OpenCV 3.X中通过定义函数:void rotate(InputArray src , OutputArray dst , int rotateCode) 完成图像矩阵顺时针旋转90°,180°,270°

注意:虽然是图像矩阵的旋转,但该函数不需要利用仿射变换来完成这类旋转,只是行列的互换,类似于矩阵的转置操作,所以该函数声明在头文件opencv2/core.hpp中。

3.2投影变换

在对仿射变换的讨论中,校正物体都是在二维空间中完成的,如果物体在三维空间中发生了旋转,那么这种变换通常被称为投影变换。

\left(\begin{array}{c}{\tilde{x}} \\ {\tilde{y}} \\ {\tilde{z}}\end{array}\right)=\left(\begin{array}{ccc}{a_{11}} & {a_{12}} & {a_{13}} \\ {a_{21}} & {a_{22}} & {a_{23}} \\ {a_{31}} & {a_{32}} & {a_{33}}\end{array}\right)\left(\begin{array}{l}{x} \\ {y} \\ {z}\end{array}\right)

与用方程法计算仿射变换矩阵的函数getAffineTransform类似,OpenCV提供了函数:

cv2.getPerspectiveTransform(src, dst)  需要提供四组对应的坐标变换;

3.3极坐标变换

通常利用极坐标变换来校正图像中的圆形物体或被包含在圆环中的物体。

1. 将笛卡儿坐标转换为极坐标

笛卡儿坐标系xoy平面上的任意一点(xy),以 为中心,通过以下计算公式对应到极坐标系θor上的极坐标(θr):

r=\sqrt{(x-\overline{x})^{2}+(y-\overline{y})^{2}}\theta=\left\{\begin{array}{ll}{2 \pi+\arctan 2(y-\overline{y}, x-\overline{x}),} & {y-\overline{y} \leqslant 0} \\ {\arctan 2(y-\overline{y}, x-\overline{x}),} & {y-\overline{y}>0}\end{array}\right.

OpenCV提供函数:

cartToPolar(x, y[, magnitude[, angle[, angleInDegree] ] ])实现的就是将原点移动到变换中心后的笛卡儿坐标向极坐标的变换

 

2. 将极坐标转换为笛卡儿坐标

极坐标变换也是可逆的,在已知极坐标(θr)和笛卡儿坐标 的条件下,计算哪个笛卡儿坐标(xy)以 为中心的极坐标变换是(θr),可通过以下公式计算:

 x=\overline{x}+r \cos \theta ,y=\overline{y}+r \sin \theta

来实现将极坐标转换为笛卡儿坐标,其参数解释与函数cartToPolar类似。注意:返回的是以原点(00)为中心的笛卡儿坐标,即已知(θr)和 ,计算出的是(x-\overline{x}, y-\overline{y})

OpenCV提供了函数:

cv2.polarToCart(magnitude, angle[, x[, y[, angleInDegree ] ] ])

3. 利用极坐标变换对图像进行变换

假设输入图像矩阵为I(\overline{x}, \overline{y}) 代表极坐标空间变换的中心,输出图像矩阵为O,比较直观的策略是利用极坐标和笛卡儿坐标的一一对应关系得到O的每一个像素值,

\boldsymbol{O}(r, \theta)=f_{\boldsymbol{I}}(\overline{x}+r \cos \theta, \overline{y}+r \sin \theta)

这里的θr都是以1为步长进行离散化的,由于变换步长较大,输出图像矩阵O可能会损失原图的很多信息。可以通过以下方式进行改进,假设要将与(\overline{x}, \overline{y}) 的距离 范围为[rminrmax]、角度范围在[θminθmax]内的点进行极坐标向笛卡儿坐标的变换,当然这个范围内的点也是无穷多的,仍需要离散化;假设r的变换步长为rstep0<sstep≤1θ的变换步长为θstepθstep一般取 \frac{360}{180 * N}N ≥2,则输出图像矩阵的宽\mathrm{w} \approx\frac{r_{\max }-r_{\min }}{r_{\text { step }}}+1,高 \mathrm{h} \approx\frac{\theta_{\max }-\theta_{\min }}{\theta_{\text { step }}}+1图像矩阵O的第i行第j列的值通过以下公式进行计算:

线性极坐标函数linearPolar:

void linearPolar(InputArray src, OutputArray dst, Point2f center, double maxRadius, int flags);

对数极坐标函数logPolar:

void logPolar(InputArray src , OutputArray dst, Point2f center, double M, int flags)

 

 

你可能感兴趣的:(OpenCV,OpenCV,图像处理)