【youcans 的图像处理学习课】5. 图像的几何变换

专栏地址:『youcans 的图像处理学习课』
文章目录:『youcans 的图像处理学习课 - 总目录』


【youcans 的图像处理学习课】5. 图像的几何变换


文章目录

  • 【youcans 的图像处理学习课】5. 图像的几何变换
    • 1. 几何变换简介
      • 1.1 仿射变换
      • 基本例程:1.33 图像的仿射变换
      • 1.2 投影变换
      • 1.3 极坐标变换
    • 2. 图像的平移
      • 基本例程:1.34 图像的平移
    • 3. 图像的旋转
      • 基本例程:1.35 图像的旋转(以原点为中心旋转)
      • 基本例程:1.36 图像的旋转(任意旋转中心)
      • 扩展例程:1.37 图像的直角旋转
    • 4. 图像的翻转(镜像)
      • 基本例程:1.38 图像的翻转(镜像)
    • 5. 图像的缩放
      • 基本例程:1.39 图像的缩放变换
      • 扩展例程:1.40 图像金字塔
    • 6. 图像的扭变(错切)
      • 基本例程:1.41 图像的错切
    • 7. 图像的复合变换
      • 基本例程:1.42 图像的复合变换
    • 8. 投影变换
      • 基本例程:1.43 图像的投影变换
      • 基本例程:1.44 图像的投影变换
    • 9. 直角坐标与极坐标的转换
      • 基本例程:1.45 直角坐标转换为极坐标
      • 扩展例程:1.46 极坐标系中的圆形图像修正


1. 几何变换简介

几何变换是指对对图像的位置、大小、形状、投影进行变换,是将图像从原始平面投影到新的视平面。OpenCV 中的图像以多维数组描述,几何变换本质上是将一个多维数组通过映射关系求得另一个多维数组。

几何变换可以分为等距变换、相似变换、仿射变换和投影变换。在很多书籍中把等距变换、相似变换都称为仿射变换,常见的仿射变换包括平移、旋转、缩放、翻转、斜切等方法。

  • 等距变换:图像中的长度、面积不变,典型的等距变换是 平移、旋转
  • 相似变换:图像中的长度比、夹角、虚圆点不变,相似变换是在等距变换的基础上进行了缩放,典型的相似变换是 缩放
  • 仿射变换:图像中的平行关系、面积比、共线线段或平行线段的长度比、矢量的线性组合不变,仿射变换是旋转和非均匀缩放的复合,典型的仿射变换是 斜切
  • 投影变换:图像中的共点、共线、相交、相切、拐点的关系不变,,投影变换是在仿射变换基础上进行的非线性缩放,典型的投影变换是 透视

在这里插入图片描述

1.1 仿射变换

仿射变换(affine)的特点是原始图像中的平行关系和线段长度比例关系保持不变。

OpenCV 中的图像以多维数组描述,通过仿射变换变换为另一个多维数组(转换图像)。

仿射变换中的校正图像在二维空间中完成,在几何上定义为一个线性变换接一个平移变换。

仿射变换由以下公式描述:
[x~y~1]=MA[xy1],MA=[a11a12a13a21a22a23001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_A \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_A= \begin{bmatrix} a_{11} &a_{12} &a_{13}\\ a_{21} &a_{22} &a_{23}\\ 0 &0 &1 \end{bmatrix} x~y~1=MAxy1,MA=a11a210a12a220a13a231

OpenCV 提供了 cv2.warpAffine 函数实现仿射变换的操作。

仿射变换矩阵 MA 中有 6 个未知参数,cv2.getAffineTransform 根据图像中不共线的 3 个点在变换前后的对应位置坐标,构造 6元一次方程组即可求出仿射变换矩阵 MA。cv2.warpAffine 再用变换矩阵 MA 计算得到变换后的图像。

基本例程:1.33 图像的仿射变换

    # 1.33 仿射变换: 平移、镜像、旋转 (cv2.warpAffine)img = cv2.imread("../images/imgB2.jpg")  # 读取彩色图像(BGR)rows, cols, ch = img.shapepts1 = np.float32([[50, 50], [200, 50], [50, 200]])  # 初始位置pts2 = np.float32([[50, 100], [200, 50], [100, 250]])  # 终止位置MA = cv2.getAffineTransform(pts1, pts2)  # 计算 2x3 变换矩阵 MAdst = cv2.warpAffine(img, MA, (cols, rows))  # 实现仿射变换plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original")plt.subplot(122), plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)), plt.title("warpAffine")plt.show()

在这里插入图片描述


1.2 投影变换

投影变换(Projective mapping)也称透视变换(Perspective transformation),其特点是:原始图像中的平行关系、比例关系在转换后可以改变,但直线在转换后仍然保持直线。

投影变换将图片投影到一个新的视平面(Viewing plane),可以对三维空间中的物体旋转进行校正,主要用于图像拼接和校正透视投影导致的图像失真 。

在这里插入图片描述
投影变换由以下公式描述:
[x~y~z~]=M[xyz],M=[a11a12a13a21a22a23a31a32a33]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ \tilde{z} \end{bmatrix} = M \begin{bmatrix} x\\ y\\ z \end{bmatrix} ,\hspace{1em} M= \begin{bmatrix} a_{11} &a_{12} &a_{13}\\ a_{21} &a_{22} &a_{23}\\ a_{31} &a_{32} &a_{33} \end{bmatrix} x~y~z~=Mxyz,M=a11a21a31a12a22a32a13a23a33

OpenCV 提供了 cv2.warpPerspective 函数实现投影变换的操作。cv2.getPerspectiveTransform 根据图像中不共线的 4 个点在变换前后的对应位置求得 (3x3) 变换矩阵,cv2.warpPerspective 使用该 (3x3) 变换矩阵即可求出变换后的图像。

1.3 极坐标变换

极坐标变换可以校正图像中的圆形物体和圆环中所包含的物体。

极坐标变换由以下公式描述:

r=(x−xˉ)2+(y−yˉ)2)θ={2π+arctan[2(y−yˉ,x−xˉ)],y−yˉ≤0arctan[2(y−yˉ,x−xˉ)],y−yˉ>0\begin{align*} r &= \sqrt{(x-\bar{x})^2+(y-\bar{y})^2)}\\ \theta &= \begin{cases} 2 \pi +arctan [2(y-\bar{y},x-\bar{x})]&, y-\bar{y} \leq 0\\ arctan [2(y-\bar{y},x-\bar{x})]&, y-\bar{y}>0 \end{cases} \end{align*} rθ=(xxˉ)2+(yyˉ)2)={2π+arctan[2(yyˉ,xxˉ)]arctan[2(yyˉ,xxˉ)],yyˉ0,yyˉ>0

OpenCV 提供了 cv2.cartToPolar 函数和 cv2.ploarToCart 函数实现笛卡尔坐标与极坐标的相互转换。



2. 图像的平移

平移是物体位置在水平和垂直方向的移动。

像素点 (x,y) 沿 x 轴平移 dx、沿 y 轴平移 dy,可以由以下公式描述:
[x~y~1]=MAT[xy1],MAT=[10dx01dy001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AT} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_{AT} = \begin{bmatrix} 1 &0 &d_x\\ 0 &1 &d_y\\ 0 &0 &1 \end{bmatrix} x~y~1=MATxy1,MAT=100010dxdy1

由偏移量 (Tx, Ty) 按上式构造平移变换矩阵 MAT,由函数 cv2.warpAffine 可以计算变换后的平移图像。

函数说明:

cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst

函数 cv2.warpAffine() 通过变换矩阵 M 对图像 src 进行仿射变换。

参数说明:

  • scr:变换操作的输入图像
  • M:仿射变换矩阵,2行3列
  • dsize: 输出图像的大小,二元元组 (width, height)
  • dst:变换操作的输出图像,可选项
  • flags:插值方法,整型(int),可选项
    • cv2.INTER_LINEAR:线性插值,默认选项
    • cv2.INTER_NEAREST:最近邻插值
    • cv2.INTER_AREA:区域插值
    • cv2.INTER_CUBIC:三次样条插值
    • cv2.INTER_LANCZOS4:Lanczos 插值
  • borderMode:边界像素方法,整型(int),可选项,默认值为 cv2.BORDER_REFLECT
  • borderValue:边界填充值,可选项,默认值为 0(黑色填充)
  • 返回值:dst,变换操作的输出图像,ndarray 多维数组

注意事项:

  1. 变换前后的图像 src、dst 都是 ndarray 二维数组。
  2. 变换矩阵 M 反映平移或旋转的关系,是 np.float32 类型 ndarray 二维数组(2行*3列)。
  3. 平移变换矩阵 M = [(1,0,dx), (0,1,dy)],Tx 表示向右(负值向左)移动像素点数,Ty 表示向下(负值向上)移动像素点数。
  4. 输出图像的大小 dsize 的格式为元组 (width,height)。

基本例程:1.34 图像的平移

    # 1.34 图像平移 (Translation transform)img = cv2.imread("../images/imgLena.tif")  # 读取彩色图像(BGR)rows, cols, ch = img.shapedx, dy = 100, 50  # dx=100 向右偏移量, dy=50 向下偏移量MAT = np.float32([[1, 0, dx], [0, 1, dy]])  # 构造平移变换矩阵   # dst = cv2.warpAffine(img, MAT, (cols, rows))  # 默认为黑色填充dst = cv2.warpAffine(img, MAT, (cols, rows), borderValue=(255,255,255))  # 设置白色填充plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original")plt.subplot(122), plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)), plt.title("Translational")plt.show()

在这里插入图片描述



3. 图像的旋转

  • 图像以原点 (0, 0) 为中心、顺时针旋转角度 θ 进行旋转操作,可以由以下公式描述:

[x~y~1]=MAR[xy1],MAR=[cosθ−sinθ0sinθcosθ0001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AR} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} , M_{AR} = \begin{bmatrix} cos \theta &-sin \theta &0\\ sin \theta &cos \theta &0\\ 0 &0 &1 \end{bmatrix} x~y~1=MARxy1,MAR=cosθsinθ0sinθcosθ0001

按上式构造旋转变换矩阵 MAR,由函数 cv2.warpAffine 可以计算变换后的绕原点旋转图像。

  • 图像以任意点 (x0, y0) 为旋转中心、顺时针旋转角度 θ 的旋转操作,可以先将原点平移到旋转中心 (x0, y0) ,然后按照原点旋转,最后再平移回坐标原点,可以由以下公式描述:

[x~y~1]=[10x001y0001][cosθ−sinθ0sinθcosθ0001][10−x001−y0001][xy1]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix}= \begin{bmatrix} 1 &0 &x_0\\ 0 &1 &y_0\\ 0 &0 &1 \end{bmatrix} \begin{bmatrix} cos \theta &-sin \theta &0\\ sin \theta &cos \theta &0\\ 0 &0 &1 \end{bmatrix} \begin{bmatrix} 1 &0 &-x_0\\ 0 &1 &-y_0\\ 0 &0 &1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} x~y~1=100010x0y01cosθsinθ0sinθcosθ0001100010x0y01xy1

  • 简便地,OpenCV 提供了 cv2.getRotationMatrix2D 函数, 根据旋转角度和位移计算旋转变换矩阵 MAR。

函数说明:

cv2.getRotationMatrix2D(center, angle, scale) → M

函数 getRotationMatrix2D 根据旋转参数计算旋转变换矩阵 MAR。

参数说明:

  • center:旋转中心坐标,二元元组 (x0, y0)
  • angle:旋转角度,单位为角度,逆时针为正数,顺时针为负数
  • scale: 缩放因子
  • 返回值:M, 旋转变换矩阵,2行3列

注意事项:

  1. 求出旋转变换矩阵 MAR,由函数 cv2.warpAffine 可以实现任意角度和任意中心的旋转效果。
  2. 以图像中心作为旋转中心时,可以用 img.shape 获得图像的宽度和高度值,除以 2 就是图像中心点坐标。
  3. 旋转角度为 90,180,270 度时,可以用 cv2.rotate(src, rotateCode) 函数实现,该方法实际上是通过矩阵转置实现的,因此速度很快。

基本例程:1.35 图像的旋转(以原点为中心旋转)

    # 1.35 图像旋转 (以原点 (0,0) 为中心旋转)img = cv2.imread("../images/imgLena.tif")  # 读取彩色图像(BGR)rows, cols, ch = img.shapetheta = np.pi / 8.0  # 顺时针旋转角度cosTheta = np.cos(theta)sinTheta = np.sin(theta)MAT = np.float32([[cosTheta, -sinTheta, 0], [sinTheta, cosTheta, 0]])  # 构造旋转变换矩阵# dst = cv2.warpAffine(img, MAT, (cols, rows))  # 默认为黑色填充dst = cv2.warpAffine(img, MAT, (cols, rows), borderValue=(255,255,255))  # 设置白色填充plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Origin")plt.subplot(122), plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)), plt.title("Rotation")plt.show()

在这里插入图片描述

基本例程:1.36 图像的旋转(任意旋转中心)

    # 1.36 图像旋转 (以任意点 (x0,y0) 为中心旋转)img = cv2.imread("../images/imgGaia.tif")  # 读取彩色图像(BGR)height, width = img.shape[:2]  # 图片的高度和宽度theta1, theta2 = 30, 45  # 顺时针旋转角度,单位为角度x0, y0 = width//2, height//2  # 以图像中心作为旋转中心MAR1 = cv2.getRotationMatrix2D((x0,y0), theta1, 1.0)MAR2 = cv2.getRotationMatrix2D((x0,y0), theta2, 1.0)imgR1 = cv2.warpAffine(img, MAR1, (width, height))  # 旋转变换,默认为黑色填充imgR2 = cv2.warpAffine(img, MAR2, (width, height), borderValue=(255,255,255))  # 设置白色填充plt.figure(figsize=(10,6))plt.subplot(131), plt.axis('off'), plt.title(r"$Origin$")plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))plt.subplot(132), plt.axis('off'), plt.title(r"$Rotation {}^o$".format(theta1))plt.imshow(cv2.cvtColor(imgR1, cv2.COLOR_BGR2RGB))plt.subplot(133), plt.axis('off'), plt.title(r"$Rotation {}^o$".format(theta2))plt.imshow(cv2.cvtColor(imgR2, cv2.COLOR_BGR2RGB))plt.show()

在这里插入图片描述

扩展例程:1.37 图像的直角旋转

当旋转角度为 90,180,270 度时,可以用图像旋转函数 cv2.rotate(src, rotateCode) 实现,该方法通过矩阵转置实现,速度很快。此外,numpy 中也提供了旋转矩阵的方法 np.rot90 可以按 90 度的整数倍进行旋转。

    # 1.37 图像的直角旋转 (90, 180, 270)# cv2.rotate(src, rotateCode)# rotateCode: cv2.ROTATE_90_CLOCKWISE, 顺时针旋转90度#             cv2.ROTATE_180, 顺时针旋转180度#             cv2.ROTATE_90_COUNTERCLOCKWISE, 顺时针旋转270度img = cv2.imread("../images/imgLena.tif")  # 读取彩色图像(BGR)imgR90 = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)imgR180 = cv2.rotate(img, cv2.ROTATE_180)imgR270 = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)# imgR90 = np.rot90(img, 1)  # numpy 矩阵旋转 90*1=90 度# imgR180 = np.rot90(img, 2)  # numpy 矩阵旋转 90*2=180 度# imgR270 = np.rot90(img, 3)  # numpy 矩阵旋转 90*3=270 度plt.figure(figsize=(9,7))plt.subplot(221), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title(r"$Origin$")plt.subplot(222), plt.imshow(cv2.cvtColor(imgR90, cv2.COLOR_BGR2RGB)), plt.title(r"$Rotation 90^{o}$")plt.subplot(223), plt.imshow(cv2.cvtColor(imgR180, cv2.COLOR_BGR2RGB)), plt.title(r"$Rotation 180^{o}$")plt.subplot(224), plt.imshow(cv2.cvtColor(imgR270, cv2.COLOR_BGR2RGB)), plt.title(r"$Rotation 270^{o}$")plt.show()

在这里插入图片描述



4. 图像的翻转(镜像)

翻转也称镜像,是指将图像沿轴线进行轴对称变换。水平镜像是将图像沿垂直中轴线进行左右翻转,垂直镜像是将图像沿水平中轴线进行上下翻转,水平垂直镜像是水平镜像和垂直镜像的叠加。

以水平镜像为例,图像宽度为 fw,像素点 (x,y) 以垂直中轴线为中心进行左右对换,可以由以下公式描述:
[x~y~1]=MAF[xy1],MAF=[−10fw010001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AF} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_{AF} = \begin{bmatrix} -1 &0 &f_w\\ 0 &1 &0\\ 0 &0 &1 \end{bmatrix} x~y~1=MAFxy1,MAF=100010fw01

由上式构造镜像变换矩阵 MAF,由函数 cv2.warpAffine 可以计算变换后的镜像图像。

简便地,OpenCV 提供了 cv2.flip 函数,可以将图像沿水平方向、垂直方向、或水平/垂直方向同时进行翻转。

函数说明:

cv2.flip(src, flipCode[, dst]) -> dst

参数说明:

  • scr:变换操作的输入图像
  • flipCode:控制参数,整型(int),flipCode>0 水平翻转,flipCode=0 垂直翻转,flipCode<0 水平和垂直翻转
  • dst:变换操作的输出图像,可选项

基本例程:1.38 图像的翻转(镜像)

    # 1.38 图像的翻转 (镜像)img = cv2.imread("../images/Fractal03.png")  # 读取彩色图像(BGR)imgFlip1 = cv2.flip(img, 0)  # 垂直翻转imgFlip2 = cv2.flip(img, 1)  # 水平翻转imgFlip3 = cv2.flip(img, -1)  # 水平和垂直翻转plt.figure(figsize=(9, 6))plt.subplot(221), plt.axis('off'), plt.title("Original")plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))  # 原始图像plt.subplot(222), plt.axis('off'), plt.title("Flipped Horizontally")plt.imshow(cv2.cvtColor(imgFlip2, cv2.COLOR_BGR2RGB))  # 水平翻转plt.subplot(223), plt.axis('off'), plt.title("Flipped Vertically")plt.imshow(cv2.cvtColor(imgFlip1, cv2.COLOR_BGR2RGB))  # 垂直翻转plt.subplot(224), plt.axis('off'), plt.title("Flipped Horizontally & Vertically")plt.imshow(cv2.cvtColor(imgFlip3, cv2.COLOR_BGR2RGB))  # 水平垂直翻转plt.show()

在这里插入图片描述



5. 图像的缩放

缩放只是调整图像的大小。

OpenCV 提供了 cv2.resize 函数,实现图像的缩放和大小变换 。

函数说明:

cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) → dst

参数说明:

  • scr:变换操作的输入图像
  • dsize: 输出图像的大小,二元元组 (width, height)
  • dst:变换操作的输出图像,可选项
  • fx, fy:x 轴、y 轴上的缩放比例,实型,可选项
  • interpolation:插值方法,整型,可选项
    • cv2.INTER_LINEAR:双线性插值(默认方法)
    • cv2.INTER_AREA:使用像素区域关系重采样,缩小图像时可以避免波纹出现
    • cv2.INTER_NEAREST:最近邻插值
    • cv2.INTER_CUBIC:4x4 像素邻域的双三次插值
    • cv2.INTER_LANCZOS4:8x8 像素邻域的Lanczos插值
  • 返回值:dst,变换操作的输出图像,ndarray 多维数组

注意事项:

  1. 图像缩放可以通过 dsize 直接设定输出图像的大小,也可以通过 dx, dy 设置图像缩放的比例(dsize 设为 None)。

  2. 也可以通过构造缩放变换矩阵 MAZ,由函数 cv2.warpAffine 计算变换后的缩放平移图像。缩放变换矩阵 MAZ 由以下公式描述:

[x~y~1]=MAZ[xy1],MAZ=[fx000fy0001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AZ} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_{AZ} = \begin{bmatrix} f_x &0 &0\\ 0 &f_y &0\\ 0 &0 &1 \end{bmatrix} x~y~1=MAZxy1,MAZ=fx000fy0001

由偏移量 (Tx, Ty) 按上式构造平移变换矩阵 MAT,由函数 cv2.warpAffine 可以计算变换后的平移图像。


基本例程:1.39 图像的缩放变换

    # 1.39 图像的缩放img = cv2.imread("../images/Fractal08.png")  # 读取彩色图像(BGR)height, width = img.shape[:2]  # 图片的高度和宽度imgZoom1 = cv2.resize(img, (int(0.75*width), int(height)))imgZoom2 = cv2.resize(img, None, fx=0.75, fy=1.0, interpolation=cv2.INTER_AREA)plt.figure(figsize=(8,6))plt.subplot(121), plt.axis('off'), plt.title("Zoom: 0.75*W,1.0*H")plt.imshow(cv2.cvtColor(imgZoom1, cv2.COLOR_BGR2RGB))plt.subplot(122), plt.axis('off'), plt.title("Zoom: fx=0.75,fy=1.0")plt.imshow(cv2.cvtColor(imgZoom2, cv2.COLOR_BGR2RGB))plt.show()

在这里插入图片描述


扩展例程:1.40 图像金字塔

图像金字塔是一种以多分辨率来解释图像的结构,常用于图像分割、图像压缩和机器视觉。

在需要处理同一图像的不同分辨率的子图时,需要创建一组具有不同分辨率的原始图像。把最大的图像放在底部,最小的放在顶部,看起来就像一座金字塔,称为图像金字塔。

图像金字塔是一系列来源于同一张原始图像、以金字塔形状排列的分辨率逐步降低的图像集合。
金字塔的底部是原始图像的高分辨率的表示,顶部是低分辨率的近似。

OpenCV 为向下采样和向上采样提供了两个函数:cv2.pyrDowncv2.pyrUp

函数说明:

cv2.pyrDown(src, dst=None, dstsize=None, borderType=None) → dst  # 向下采样
cv2.pyrUp(src, dst=None, dstsize=None, borderType=None) → dst  # 向上采样

函数 cv2.pyrDown 是从高分辨率的大尺寸图像逐次向下采样得到一系列图像,构建一个金字塔,称为高斯金字塔(Gaussian pyramid),实际上是一个重复高斯平滑并重新对图像采样的过程。拉普拉斯金字塔每次向下采样后将再次向上采样,并记录残差信息,可以对图像进行最大程度的还原。

# 1.40 图像金字塔def GussianPyramid(image): # 高斯金字塔level = 2  # 金字塔的层数imgCopy = image.copy()pyramidImages = []  # 创建图像 Listfor i in range(level):dst = cv2.pyrDown(imgCopy)  # 下采样pyramidImages.append(dst)  # 添加到图像 Listcv2.imshow("pyramid down "+str(i), dst)imgCopy = dst.copy()return pyramidImagesimg = cv2.imread("../images/imgLena.tif")  # 读取彩色图像(BGR)
cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
cv2.imshow("input image", img)
GussianPyramid(img)  # 高斯图像金字塔
# LapalianPyramid(img)  # 拉普拉斯图像金字塔
cv2.waitKey(0)

在这里插入图片描述



6. 图像的扭变(错切)

图像的错切变换也称斜切,是指平面景物在投影平面上的非垂直投影,使图像中的图形在水平方向或垂直方向产生扭变。

以水平扭变为例,像素点 (x,y) 在水平方向发生扭变变成斜边,而在垂直方向的边不变,可以由以下公式描述:
[x~y~1]=MAS[xy1],MAS=[1tanθ0010001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AS} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_{AS} = \begin{bmatrix} 1 &tan \theta &0\\ 0 &1 &0\\ 0 &0 &1 \end{bmatrix} x~y~1=MASxy1,MAS=100tanθ10001

由扭变角度 θ上式构造错切变换矩阵 MAS,由函数 cv2.warpAffine 可以计算变换后的扭变图像。


基本例程:1.41 图像的错切

    # 1.41 图像的错切img = cv2.imread("../images/imgB2.jpg")  # 读取彩色图像(BGR)height, width = img.shape[:2]  # 图片的高度和宽度MAS = np.float32([[1, 0.2, 0], [0, 1, 0]])  # 构造错切变换矩阵imgShear = cv2.warpAffine(img, MAS, (width, height))plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("imgOrigin")plt.subplot(122), plt.imshow(cv2.cvtColor(imgShear, cv2.COLOR_BGR2RGB)), plt.title("imgShear")plt.show()

在这里插入图片描述



7. 图像的复合变换

图像的复合变换是指对给定的图像连续进行多次上述的平移、旋转、翻转、缩放、错切等基本变换,也称为级联变换。

对给定图像按一定顺序执行若干次基本变换,其变换矩阵仍然可以用 3x3 阶变换矩阵表示。进一步地,对图像依次执行基本变换 F1、F2、…Fn 的变换矩阵分别为 M1、M2、…Mn,可以证明,以图像中心点为中心进行比例、旋转进行变换,则复合变换的变换矩阵 M 等于各基本变换矩阵依次相乘所得到的组合矩阵:
M=M1×M2×⋯×MnM = M_1 \times M_2 \times \dots \times M_n M=M1×M2××Mn

缩放:
MAZ=[fx000fy0001]M_{AZ} = \begin{bmatrix} fx &0 &0\\ 0 &f_y &0\\ 0 &0 &1 \end{bmatrix} MAZ=fx000fy0001

旋转:
MAR=[cosθ−sinθ0sinθcosθ0001]M_{AR} = \begin{bmatrix} cos \theta &-sin \theta &0\\ sin \theta &cos \theta &0\\ 0 &0 &1 \end{bmatrix} MAR=cosθsinθ0sinθcosθ0001

平移:
MAT=[10dx01dy001]M_{AT} = \begin{bmatrix} 1 &0 &d_x\\ 0 &1 &d_y\\ 0 &0 &1 \end{bmatrix} MAT=100010dxdy1

扭变:
MAS=[1tanθ0010001]M_{AS} = \begin{bmatrix} 1 &tan \theta &0\\ 0 &1 &0\\ 0 &0 &1 \end{bmatrix} MAS=100tanθ10001

镜像:
MAF=[−10fw010001]M_{AF} = \begin{bmatrix} -1 &0 &f_w\\ 0 &1 &0\\ 0 &0 &1 \end{bmatrix} MAF=100010fw01


基本例程:1.42 图像的复合变换

    # 1.42 图像的复合变换img = cv2.imread("../images/imgLena.tif")  # 读取彩色图像(BGR)height, width = img.shape[:2]  # 图片的高度和宽度# (1) 缩放fx, fy = 0.6, 0.6MAZ = np.float32([[fx, 0, 0], [0, fy, 0]])  # 构造缩放变换矩阵imgT1 = cv2.warpAffine(img, MAZ, (width, height))  # 仿射变换, 黑色填充# (2) 平移dx, dy = 50, 200  # dx=100 向右偏移量, dy=50 向下偏移量MAT = np.float32([[1, 0, dx], [0, 1, dy]])  # 构造平移变换矩阵imgT2 = cv2.warpAffine(imgT1, MAT, (width, height), borderValue=(0,255,255))  # 实现仿射变换# (3) 旋转theta = -30 * np.pi / 180  # 逆时针旋转 30°cosTheta = np.cos(theta)sinTheta = np.sin(theta)MAR = np.float32([[cosTheta, -sinTheta, 0], [sinTheta, cosTheta, 0]])  # 构造旋转变换矩阵imgT3 = cv2.warpAffine(imgT2, MAR, (width, height), borderValue=(255,255,0))  # 实现仿射变换# (4) 扭曲theta = -30 * np.pi / 180  # 逆时针扭变 30°MAS = np.float32([[1, np.tan(theta), 0], [0, 1, 0]])  # 构造扭变变换矩阵imgT4 = cv2.warpAffine(imgT3, MAS, (width, height), borderValue=(255,0,255))  # 实现仿射变换plt.figure(figsize=(9,6))plt.subplot(221), plt.axis('off'), plt.title("T1:Zoom")plt.imshow(cv2.cvtColor(imgT1, cv2.COLOR_BGR2RGB)),plt.subplot(222), plt.axis('off'), plt.title("T2:Translation")plt.imshow(cv2.cvtColor(imgT2, cv2.COLOR_BGR2RGB))plt.subplot(223), plt.axis('off'), plt.title("T3:Rotation")plt.imshow(cv2.cvtColor(imgT3, cv2.COLOR_BGR2RGB))plt.subplot(224), plt.axis('off'), plt.title("T4:Shear")plt.imshow(cv2.cvtColor(imgT4, cv2.COLOR_BGR2RGB))plt.show()

在这里插入图片描述



8. 投影变换

投影变换(Projective mapping)也称透视变换(Perspective transformation)是建立两平面场之间的对应关系, 将图片投影到一个新的视平面(Viewing plane)。

OpenCV 提供了 cv2.warpPerspective 函数实现投影变换的操作。

函数说明:

cv2.getPerspectiveTransform(src, dst[,solveMethod]) → MP
cv2.warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst

函数cv2.getPerspectiveTransform 根据图像中不共线的 4 个点在变换前后的对应位置求得 (3x3) 变换矩阵,cv2.warpPerspective 使用该 (3x3) 变换矩阵即可求出变换后的图像。标量进行加法运算。

参数说明:

  • src:变换前图像四边形顶点坐标
  • dst:变换后图像四边形顶点坐标
  • solveMethod:矩阵分解方法,传递给 cv2.solve 求解变换矩阵 MP
    • cv2.DECOMP_LU:选择最优轴的高斯消去法,默认方法
    • cv2.DECOMP_SVD:奇异值分解(SVD)方法
    • cv2.DECOMP_EIG:特征值分解方法,src 必须对称
    • cv2.DECOMP_QR:QR(正交三角)分解
    • cv2.DECOMP_CHOLESKY:Cholesky LLT 分解
  • MP:透视变换矩阵,3行3列
  • dsize: 输出图像的大小,二元元组 (width, height)
  • dst:变换操作的输出图像,可选项
  • flags:插值方法,整型(int),可选项
    • cv2.INTER_LINEAR:线性插值,默认选项
    • cv2.INTER_NEAREST:最近邻插值
    • cv2.INTER_AREA:区域插值
    • cv2.INTER_CUBIC:三次样条插值
    • cv2.INTER_LANCZOS4:Lanczos 插值
  • borderMode:边界像素方法,整型(int),可选项,默认值为 cv2.BORDER_REFLECT
  • borderValue:边界填充模式,可选项,默认值为 0(黑色填充)
  • 返回值:dst,透视变换操作的输出图像,ndarray 多维数组

基本例程:1.43 图像的投影变换

    # 1.43 投影变换 (Projective mapping)img = cv2.imread("../images/imgB2.jpg")  # 读取彩色图像(BGR)h, w = img.shape[:2]  # 图片的高度和宽度pointSrc = np.float32([[0,0], [w-1,0], [0,h-100], [w-1, h-100]])  # 原始图像中 4点坐标pointDst = np.float32([[180,50], [w-180,50], [0,h-100], [w-1, h-100]])  # 变换图像中 4点坐标MP = cv2.getPerspectiveTransform(pointSrc, pointDst)  # 计算投影变换矩阵 MimgP = cv2.warpPerspective(img, MP, (512, 512))  # 用变换矩阵 M 进行投影变换plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original")plt.subplot(122), plt.imshow(cv2.cvtColor(imgP, cv2.COLOR_BGR2RGB)), plt.title("Projective")plt.show()

在这里插入图片描述


基本例程:1.44 图像的投影变换

    # 1.44 图像的投影变换img = cv2.imread("../images/imgC2.jpg")  # 读取彩色图像(BGR)h, w = img.shape[:2]  # 图片的高度和宽度pointSrc = np.float32([[0,0], [w,0], [0,h], [w,h]])  # 原始图像中 4点坐标pointDst = np.float32([[int(w/3), int(h/3)], [int(w*2/3), int(h/3)], [0,h], [w,h]])  # 变换图像中 4点坐标MP = cv2.getPerspectiveTransform(pointSrc, pointDst)  # 计算投影变换矩阵 MimgP = cv2.warpPerspective(img, MP, (w,h), flags=cv2.INTER_AREA, borderMode=cv2.BORDER_WRAP)plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original"), plt.axis('off')plt.subplot(122), plt.imshow(cv2.cvtColor(imgP, cv2.COLOR_BGR2RGB)), plt.title("Projective"), plt.axis('off')plt.show()

在这里插入图片描述



9. 直角坐标与极坐标的转换

函数 cv2.cartToPolar 用于将直角坐标(笛卡尔坐标)转换为极坐标,函数 cv2.polarToCart 用于将极坐标转换为直角坐标(笛卡尔坐标)。

圆形图案边缘上的文字经过及坐标变换后可以垂直的排列在新图像的边缘,便于对文字的识别和检测。

函数说明:

cv2.cartToPolar(x, y[, magnitude[, angle[, angleInDegrees]]]) → magnitude, angle
cv2.polarToCart(magnitude, angle[, x[, y[, angleInDegrees]]]) → x, y

函数 cv2.cartToPolar 实现将原点移动到变换中心后的直角坐标向极坐标的转换,输入参数为直角坐标系的横坐标、纵坐标,输出为极坐标系的向量值、角度值。

函数 cv2.polarToCart 实现将原点移动到变换中心后的极坐标向直角坐标的转换,输入参数为极坐标系的向量值、角度值,输出为直角坐标系的横坐标、纵坐标。

参数说明:

  • x, y:直角坐标系的横坐标、纵坐标,ndarray 多维数组,浮点型
  • magnitude, angle:极坐标系的向量值、角度值,ndarray 多维数组
  • angleInDegrees:弧度制/角度值选项,默认值 0 选择弧度制,1 选择角度制([0,360] )
  • 返回值 magnitude, angle:极坐标系的向量值、角度值,ndarray 多维数组,与输入的 x, y 具有相同的尺寸和数据类型
  • 返回值 x, y:直角坐标系的横坐标、纵坐标,ndarray 多维数组,与输入的 magnitude, angle 具有相同的尺寸和数据类型

注意事项:

  1. 极坐标与直角坐标的变换在数学上是可逆的,但实际变换时存在误差,角度计算精度约为 0.3度,坐标计算精度约为 1e-6。
  2. 直角坐标系以变换中心为圆心的同一个圆上的点,在极坐标系中显示为一条直线。因此,用极坐标变换可以实现圆形物体的图像修正。
  3. cv2.cartToPolar 中的可选项 magnitude, angle 可以用于指定变换中心的坐标,cv2.polarToCart 中的可选项 x, y 可以用于指定变换中心的坐标。

基本例程:1.45 直角坐标转换为极坐标

    # 1.45 直角坐标转换为极坐标x = np.float32([0,1,2, 0,1,2, 0,1,2]) -1y = np.float32([0,0,0, 1,1,1, 2,2,2]) -1n = np.arange(9)r, theta = cv2.cartToPolar(x, y, angleInDegrees=True)xr,yr = cv2.polarToCart(r, theta, angleInDegrees=1)print(xr,yr)plt.figure(figsize=(9,5))plt.subplot(121), plt.title("Cartesian coordinate"), plt.plot(x, y, 'o')for i, txt in enumerate(n):plt.annotate(txt, (x[i], y[i]))plt.subplot(122), plt.title("Polar coordinate"), plt.plot(r, theta, 'o')for i, txt in enumerate(n):plt.annotate(txt, (r[i], theta[i]))plt.show()


扩展例程:1.46 极坐标系中的圆形图像修正

    # 1.46 极坐标系中的圆形图像修正img = cv2.imread("../images/imgC3.jpg")  # 读取彩色图像(BGR)h, w = img.shape[:2]  # 图片的高度和宽度cx, cy = int(w/2), int(h/2)  # 以图像中心点作为变换中心maxR = max(cx, cy)  # 最大变换半径imgPolar = cv2.linearPolar(img, (cx,cy), maxR, cv2.INTER_LINEAR)imgPR = cv2.rotate(imgPolar, cv2.ROTATE_90_COUNTERCLOCKWISE)plt.figure(figsize=(10,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original"), plt.axis('off')plt.subplot(122), plt.imshow(cv2.cvtColor(imgPR, cv2.COLOR_BGR2RGB)), plt.title("PolarTrans"), plt.axis('off')plt.show()

通过极坐标和直角坐标的对应关系,将圆环图像转换为矩形图像,可以对圆形图像进行修正。

在这里插入图片描述


【本节完】


版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/120995650)
Copyright 2022 youcans, XUPT

专栏地址:『youcans 的图像处理学习课』
文章目录:『youcans 的图像处理学习课 - 总目录』

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/566016.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

键盘中按键对应的键码值

最近很多人想知道键盘中的按键对应的按键值 下面给大家分享一些键码值 键盘各种按键对应的ASII码如下&#xff1a; keycode 8 BackSpace BackSpace keycode 9 Tab Tab keycode 12 Clear keycode 13 Enter keycode 16 Shift_L keycode 17 Control_L keycode 18 Alt_L k…

python科学计算

1 软件包的安装和介绍 1.1 安装软件包 1.1.1 安装 和Matlab不同&#xff0c;Python的科学软件包由众多的社区维护和发布&#xff0c;因此要一一将其收集齐安装到你的电脑里是一件很费时间的事情。幸好这些工作已经有人帮我们整理好了。只需要下载一个文件&#xff0c;一次安…

【OpenCV 例程200篇】29. 图像的翻转(cv2.flip)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】29. 图像的翻转&#xff08;cv2.flip&#xff09; 欢迎关注 『Python小白的OpenCV学习课』 系列&#xff0c;持续更新中 翻转也称镜像&#xff0c;是指将图像沿轴线进行轴对称变换。水平镜像是将图像…

【OpenCV 例程200篇】30. 图像的缩放(cv2.resize)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】30. 图像的缩放&#xff08;cv2.resize&#xff09; 缩放只是调整图像的大小。 OpenCV 提供了 cv2.resize 函数&#xff0c;实现图像的缩放和大小变换 。 函数说明&#xff1a; cv2.resize(src, d…

JAVA50道经典编程题

加强对基础知识的巩固提升&#xff0c;拓展逻辑思维。 JAVA50道经典编程题&#xff1a; 【程序1】 题目&#xff1a;古典问题&#xff1a;有一对兔子&#xff0c;从出生后第3个月起每个月都生一对兔子&#xff0c;小兔子长到第三个月后每个月又生一对兔子&#xff0c;假如兔子…

【OpenCV 例程200篇】31. 图像金字塔(cv2.pyrDown)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】31. 图像金字塔&#xff08;cv2.pyrDown&#xff09; 扩展例程&#xff1a;1.40 图像金字塔 图像金字塔是一种以多分辨率来解释图像的结构&#xff0c;常用于图像分割、图像压缩和机器视觉。 在需要…

JQuery警报灯

利用鼠标点击改变背景颜色制作一个警报器&#xff0c;供大家参考&#xff01; 请先看一下效果图&#xff1a;&#xff08;警报器是蓝色的和点击之后警报器是红色的&#xff09; 程序解说&#xff1a;首先要有一个警报器的样式和两个分别为打开警报器和关闭警报器的按钮&…

python里面的tuple与list对比

python里面的tuple与list对比 tuple 另一种有序列表叫元组&#xff1a;tuple。tuple和list非常类似&#xff0c;但是tuple一旦初始化就不能修改&#xff0c;比如同样是列出同学的名字&#xff1a; >>> classmates (Michael, Bob, Tracy)现在&#xff0c;classmates…

【OpenCV 例程200篇】32. 图像的扭变(错切)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】32. 图像的扭变&#xff08;错切&#xff09; 图像的错切变换也称斜切&#xff0c;是指平面景物在投影平面上的非垂直投影&#xff0c;使图像中的图形在水平方向或垂直方向产生扭变。 以水平扭变为例…

【OpenCV 例程200篇】33. 图像的复合变换

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】33. 图像的复合变换 图像的复合变换是指对给定的图像连续进行多次上述的平移、旋转、翻转、缩放、错切等基本变换&#xff0c;也称为级联变换。 对给定图像按一定顺序执行若干次基本变换&#xff0c…

表格生成器

能自动生成表格的小程序 当你在相应的输入框内输入表格的行高&#xff0c;列宽&#xff0c;多少行&#xff0c;多少列的数字后&#xff0c;点击创建表格就会自动生成你想要的表格。 未输入数据之前&#xff1a; 输入要生成表格数据之后点击创建表格&#xff1a;&#xff08;为…

开心农场

仿照qq农场实现了一个简易的开心农场&#xff0c;使我们在开心快乐中学习 在农场里我们可以进行基本的操作播种&#xff0c;生长&#xff0c;开花和结果。 先看一下效果图 生长 结果 一番欣赏之后是不是感觉很有趣很好玩~~~~ **程序解读&#xff1a;**准备好相关的图片和…

基于ssm企业人事管理系统设计与实现论文

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统企业人事信息管理难度大&#xff0c;容错率低&#xff0c…

【OpenCV 例程200篇】34. 图像的投影变换(cv2.getPerspectiveTransform)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】34. 图像的投影变换 投影变换&#xff08;Projective mapping&#xff09;也称透视变换&#xff08;Perspective transformation&#xff09;是建立两平面场之间的对应关系&#xff0c; 将图片投影到…

python里面的dict和set

python里面的dict和set dict Python内置了字典&#xff1a;dict的支持&#xff0c;dict全称dictionary&#xff0c;在其他语言中也称为map&#xff0c;使用键-值&#xff08;key-value&#xff09;存储&#xff0c;具有极快的查找速度。 举个例子&#xff0c;假设要根据同学的名…

Ajax实现登陆

用Ajax前后端分离实现一个简单的用户登录页面 先看一下页面效果图 账号和密码格式错误 格式正确但是用户名或密码错误&#xff08;清空密码框内容&#xff0c;选中账号框全部内容&#xff09; 程序详解&#xff1a; &#xff1a; 对输入的账号和密码用正则表达式验证格式 &…

【OpenCV 例程200篇】35. 图像的投影变换(边界填充)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】35. 图像的投影变换&#xff08;边界填充&#xff09; 投影变换&#xff08;Projective mapping&#xff09;也称透视变换&#xff08;Perspective transformation&#xff09;是建立两平面场之间的对…

点击修改表格背景色

使用Jquery事件实现点击修改表格的背景颜色 每列表格之前都有一个多选按钮&#xff0c;当你点击按钮时&#xff0c;这一行所有内容的背景色会发生改变&#xff0c;当你再次点击该多选按钮的时候&#xff0c;取消背景色。 未点击之前的样式 点击时候的样式 程序解读&#xff…

【OpenCV 例程200篇】36. 直角坐标与极坐标转换(cv2.polarToCart)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】36. 直角坐标与极坐标的转换 函数 cv2.cartToPolar 用于将直角坐标&#xff08;笛卡尔坐标&#xff09;转换为极坐标&#xff0c;函数 cv2.polarToCart 用于将极坐标转换为直角坐标&#xff08;笛卡尔…

【youcans 的图像处理学习课】6. 灰度变换与直方图处理

专栏地址&#xff1a;『youcans 的图像处理学习课』 文章目录&#xff1a;『youcans 的图像处理学习课 - 总目录』 【youcans 的图像处理学习课】6. 灰度变换与直方图处理 文章目录【youcans 的图像处理学习课】6. 灰度变换与直方图处理1. 图像增强技术2. 图像的灰度化处理和二…