我在Vscode学OpenCV 几何变换(缩放、翻转、仿射变换、透视、重映射)

几何变换指的是将一幅图像映射到另一幅图像内的操作。

  1. cv2.warpAffine:使用仿射变换矩阵对图像进行变换,可以实现平移、缩放和旋转等操作。
  2. cv2.warpPerspective:使用透视变换矩阵对图像进行透视变换,可以实现镜头校正、图像纠偏等操作。
  3. cv2.getAffineTransform:计算仿射变换矩阵,根据输入的三个点对之间的关系来生成一个2x3的矩阵。
  4. cv2.getPerspectiveTransform:计算透视变换矩阵,根据输入的四个点对之间的关系来生成一个3x3的矩阵。
  5. cv2.resize:调整图像的大小,可以根据指定的尺寸或比例因子来进行缩放操作。
  6. cv2.flip:对图像进行翻转操作,可以在水平、垂直或两者方向上进行翻转。
  7. cv2.rotate:对图像进行旋转操作,可以按照指定的角度对图像进行顺时针或逆时针旋转。

这些函数可以在OpenCV中灵活使用,以实现各种图像的几何变换。通过调整参数和变换矩阵,可以达到所需的图像效果和变换结果。

CV 几何变换

  • 一、缩放
    • 1.1 写法
    • 1.1 改变图像的参数dsize的值
    • 1.2通过参数 fx 和 fy 指定
    • 1.3什么是插值
      • 部分介绍
  • 二、翻转
    • 2.1 语句 y=cv2.flip(img,1) 会使图像绕着 y 轴进行翻转。
    • 2.2 语句 xy=cv2.flip(img,-1) 会使图像同时绕着 x 轴和 y 轴进行翻转。
    • 2.3 语句 x=cv2.flip(img,0) 会使图像绕着 x 轴进行翻转。
  • 三、仿射变换
    • 3.1 平移
      • 3.1.1 代码及效果
      • 3.1.2 平移再缩放
    • 3.2 旋转
      • 3.2.1 代码及效果
    • 3.3 cv2.getAffineTransform:计算仿射变换矩阵
      • 3.3.1 代码
  • 四、透视
      • 4.1 `cv2.getPerspectiveTransform()` 转换矩阵
      • 4.2 代码及效果
  • 五、重映射
    • 5.1 复制
    • 5.2 翻转
      • 5.2.1 绕着x轴
      • 5.2.2 绕y轴翻转
      • 5.2.3 绕x轴、y轴翻转
      • 5.2.4 x轴、y轴互换
    • 5.3 图像缩放

一、缩放

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

 dst 代表输出的目标图像,该图像的类型与 src 相同,其大小为 dsize(当该值非零时),或者可以通过 src.size()fx、fy 计算得到。

 src 代表需要缩放的原始图像。

 dsize 代表输出图像大小。

 fx 代表水平方向的缩放比例。

 fy 代表垂直方向的缩放比例。

 interpolation 代表插值方式

1.1 写法

# 指定目标尺寸
resized_image = cv2.resize(image, (new_width, new_height))# 指定缩放比例因子
resized_image = cv2.resize(image, None, fx=scale_factor, fy=scale_factor)# 指定目标尺寸和插值方法
resized_image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_NEAREST)

原图:
在这里插入图片描述

1.1 改变图像的参数dsize的值

无论有fx,fy,都是由于dszie决定目标图像的大小,colws,rows

fx=(double)dsize.width/src.cols
fy=(double)dsize.height/src.rows```

在这里插入图片描述

1.2通过参数 fx 和 fy 指定

dsize的值为None,通过目标的参数fx,fy来实现的。
dsize(round(fx*src.cols),round(fy*src.rows))

在这里插入图片描述

1.3什么是插值

几何变换(如调整大小)期间确定无法直接映射的像素点值的必要性。当你放大图像时,会引入一些在原始图像中没有相应值的新像素。插值方法用于估算这些新像素的值。

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img1=cv.imread("./Pic/test_img.jpg")
rows,cols=img1.shape[:2]
print(rows)
print(cols)

部分介绍

  • 最近邻插值:最近邻插值方法会选择最接近目标像素位置的原始像素的值作为新像素的值。这种方法计算简单,但可能会导致图像的锯齿状边缘和失真。

  • 双线性插值:双线性插值方法会根据目标像素位置周围的四个最近原始像素的值进行加权平均,以计算新像素的值。这种方法可以产生较平滑的图像,但可能会导致细节的模糊。

  • 双三次插值:双三次插值方法会根据目标像素位置周围的16个最近原始像素的值进行加权平均,以计算新像素的值。这种方法可以产生更平滑的图像,但计算复杂度较高。

选择哪种插值方法取决于应用的需求。如果需要保留图像的细节和边缘,可以选择双线性或双三次插值。如果需要快速计算并可以容忍一些失真,可以选择最近邻插值。

总之,插值方法在图像缩放中起着重要的作用,可以影响图像质量和计算效率。根据具体需求选择适当的插值方法是很重要的。

二、翻转

在图像处理中,旋转和翻转是两种不同的操作。
·
旋转 意味着围绕图像的中心或其他指定点按某个角度旋转图像。这会导致图像内容的重组,但不会改变内容本身的方向。在 OpenCV 中,你可以使用 cv2.rotate 函数来旋转图像。
·
翻转 意味着以水平或垂直轴为对称轴来颠倒图像内容。水平翻转会使图像左右颠倒,而垂直翻转则会使图像上下颠倒。在 OpenCV 中,你可以使用 cv2.flip 函数来实现图像的翻转。
·
总结来说,旋转是根据一个角度来调整图像的方向,而翻转是基于图像的对称轴来颠倒图像内容。

dst = cv2.flip( src, flipCode )

#src 代表了原始像素点(源像素),dst 代表了目标像素点(目标像素)

dst 代表和原始图像具有同样大小、类型的目标图像。

src 代表要处理的原始图像。

flipCode 翻转的方式(水平翻转、垂直翻转或同时进行水平和垂直翻转)
在这里插入图片描述

2.1 语句 y=cv2.flip(img,1) 会使图像绕着 y 轴进行翻转。

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
imgx=cv.imread("./Pic/test_img.jpg")
dst=cv.flip(imgx,1)
plt.imshow(dst[:,:,::-1])

在这里插入图片描述

2.2 语句 xy=cv2.flip(img,-1) 会使图像同时绕着 x 轴和 y 轴进行翻转。

dst=cv.flip(imgx,-1)
plt.imshow(dst[:,:,::-1])

在这里插入图片描述

2.3 语句 x=cv2.flip(img,0) 会使图像绕着 x 轴进行翻转。

dst=cv.flip(imgx,0)
plt.imshow(dst[:,:,::-1])

在这里插入图片描述

三、仿射变换

仿射变换是一种线性变换,可以通过矩阵的乘法来描述。这种变换在保持图像中的平行性和直线性方面非常强大,因此在图像处理和计算机视觉领域得到广泛应用。它能够实现平移、旋转、缩放和剪切等操作,并且在变换后仍然能够保持空间关系的几何特性。

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

  • src: 输入图像,即需要进行仿射变换的图像。
  • M: 变换矩阵,描述了平移、旋转和缩放等操作。
  • dsize: 输出图像的大小,即变换后的图像的尺寸。
  • flags: 插值方法的标志。用于指定在变换过程中如何对像素进行插值。这是可选参数。
  • borderMode: 边界模式,指定了当像素越界时的处理方式(例如镜像、填充等)。这也是一个可选参数。
  • borderValue: 当使用常量边界模式时,指定边界填充的数值。这同样是一个可选参数。

在运用中就简化成
dst = cv2.warpAffine( src , M , dsize )

3.1 平移

平移是一种基本的仿射变换操作,它将图像沿着给定的方向进行移动。
【图像平移将图像按照指定方向和距离,移动到相应的位置】

M = | 1 0 tx || 0 1 ty |

在这里,tx 和 ty 分别表示沿 x 和 y 方向的平移量。当应用这个平移矩阵时,图像中的每个像素将按照指定的偏移量进行移动。

只需提供适当的变换矩阵,可以很容易地实现图像的平移操作
dst = cv2.warpAffine( src , M , dsize )

img:输入图像
M: 2*3移动矩阵(注意:将M设置为np.float32类型的Numpy数组。)

dsize:输出图像的大小注意:输出图像的大小,它应该是(宽度,高度)的形式。请记住,width=列数, height=行数。

3.1.1 代码及效果

import numpy as np
import cv2 as cv
import matplotlib.pyplot as pltimg1 = cv.imread('./Pic/test_img.jpg')# 平移
rows, cols = img1.shape[:2]
M = np.float32([[1, 0, 100], [0, 1, 50]])
dst = cv.warpAffine(img1, M, (cols, rows))# 显示
fig, axes = plt.subplots(1, 2, figsize=(12, 6))axes[0].imshow(cv.cvtColor(img1, cv.COLOR_BGR2RGB))
axes[0].set_title("Original")axes[1].imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
axes[1].set_title("Change")
plt.show()

在这里插入图片描述

3.1.2 平移再缩放

更改dsize的大小
在这里插入图片描述

3.2 旋转

retval=cv2.getRotationMatrix2D(center, angle, scale)
在这里,cv2.getRotationMatrix2D()函数用于生成一个旋转矩阵,其参数的含义如下:

  • center:旋转的中心点坐标,通常以元组 (x, y) 的形式表示。在图像处理中,(0, 0) 通常代表图像的左上角。

  • angle:旋转角度,以度为单位。正数表示逆时针旋转,负数表示顺时针旋转。

  • scale:可选的缩放因子。如果不需要对图像进行缩放,可以将其设置为1。如果想要按比例缩放图像,可以提供缩放因子。

该函数返回一个2x3的变换矩阵,将它应用到原始图像上可以实现指定中心点、角度和缩放比例的旋转。

3.2.1 代码及效果

import numpy as np
import cv2 as cv
import matplotlib.pyplot as pltimg = cv.imread('./Pic/test_img.jpg')# 获取图像尺寸
rows, cols = img.shape[:2]# 旋转角度为90度
theta = 90
theta_rad = np.deg2rad(theta)# 构造旋转矩阵
M = cv.getRotationMatrix2D((cols / 2, rows / 2), theta, 1)# 进行图像旋转
dst = cv.warpAffine(img, M, (cols, rows))# 显示图像
fig, axes = plt.subplots(1, 2, figsize=(12, 6))
axes[0].imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
axes[0].set_title("Original")axes[1].imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
axes[1].set_title("Rotated")
plt.show()

在这里插入图片描述

M = cv.getRotationMatrix2D((cols/ 2, rows / 2), 45, 0.5)

在这里插入图片描述

3.3 cv2.getAffineTransform:计算仿射变换矩阵

retval=cv2.getAffineTransform(src, dst)

 src 代表输入图像的三个点坐标。
 dst 代表输出图像的三个点坐标。

3.3.1 代码

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
x1, y1 = 100, 100
x2, y2 = 200, 300
x3, y3 = 100, 200u1, v1 = 150, 150
u2, v2 = 250, 150
u3, v3 = 150, 250img = cv.imread('./Pic/test_img.jpg')# 获取图像尺寸
rows, cols = img.shape[:2]# 定义原始图像上的三个点和目标图像上的三个对应点
pts_original = np.float32([[x1, y1], [x2, y2], [x3, y3]])
pts_target = np.float32([[u1, v1], [u2, v2], [u3, v3]])# 获取仿射变换矩阵
M = cv.getAffineTransform(pts_original, pts_target)# 进行仿射变换
dst = cv.warpAffine(img, M, (cols, rows))# 显示图像
fig, axes = plt.subplots(1, 2, figsize=(12, 6))
axes[0].imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
axes[0].set_title("Original")axes[1].imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
axes[1].set_title("Transformed")
plt.show()

在这里插入图片描述

四、透视

dst = cv2.warpPerspective( src, M, dsize[, flags[, borderMode[, borderValue]]] )
cv2.warpPerspective()函数用于执行透视变换,它接受以下参数:

  1. src: 输入图像。这是要进行透视变换的原始图像。

  2. M: 变换矩阵。这是通过cv2.getPerspectiveTransform()或其他类似函数计算得到的透视变换矩阵。

  3. dsize: 输出图像的大小,表示为 (width, height)

  4. flags(可选参数): 这是一个插值方法的标志,用于指定如何在变换过程中对图像进行插值。默认情况下为cv2.INTER_LINEAR,这意味着使用线性插值。其他可能的值包括cv2.INTER_NEAREST(最近邻插值)、cv2.INTER_CUBIC(立方插值)等。

  5. borderMode(可选参数): 用于定义边界像素的模式。默认为cv2.BORDER_CONSTANT,表示将边界填充为常数值。其他可能的值包括cv2.BORDER_REFLECT(边界像素的镜像反射)和cv2.BORDER_WRAP(边界像素的重复等)。

  6. borderValue(可选参数): 当borderModecv2.BORDER_CONSTANT时,可以指定边界填充的常数值。默认为0。

4.1 cv2.getPerspectiveTransform() 转换矩阵

可以使用函数 cv2.getPerspectiveTransform() 生成适用于 cv2.warpPerspective() 的转换矩阵。该函数的语法格式为:

retval = cv2.getPerspectiveTransform(src, dst)

其中,参数含义如下:

  • src:代表输入图像的四个顶点的坐标。

  • dst:代表输出图像的四个顶点的坐标。

需要注意的是,src 参数和 dst 参数都是包含四个点的数组,与仿射变换函数 cv2.getAffineTransform() 中的三个点是不同的。在实际使用中,我们可以根据需求控制 src 中的四个点映射到 dst 中的四个点。

4.2 代码及效果

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt# 定义原始图像上的四个点和目标图像上的四个对应点
src_points = np.float32([[100, 100], [200, 300], [100, 200], [300, 150]])
dst_points = np.float32([[150, 150], [250, 150], [150, 250], [300, 200]])img = cv.imread('./Pic/test_img.jpg')# 获取透视变换矩阵
M = cv.getPerspectiveTransform(src_points, dst_points)# 进行透视变换
dst = cv.warpPerspective(img, M, (img.shape[1], img.shape[0]))# 显示图像
fig, axes = plt.subplots(1, 2, figsize=(12, 6))
axes[0].imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
axes[0].set_title("Original")axes[1].imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB))
axes[1].set_title("Transformed")
plt.show()

在这里插入图片描述

五、重映射

重映射是指将图像中的像素从一个位置映射到另一个位置的过程。在计算机视觉和图像处理中,重映射通常用于图像几何变换(如旋转、缩放、仿射变换、透视变换等)以及校正畸变等操作。

在重映射过程中,我们需要定义一个映射关系,将输入图像中的每个像素映射到输出图像中的相应位置。这个映射关系可以通过变换矩阵(如仿射变换矩阵或透视变换矩阵)来实现,也可以通过自定义的像素级映射函数来完成。一旦建立了映射关系,就可以根据该关系对图像进行重映射,从而实现所需的变换效果。

在OpenCV中,重映射通常涉及到两个主要函数:cv2.remap()cv2.warpAffine()cv2.warpPerspective()。前者允许用户提供自定义的映射关系,而后者则使用预定义的变换矩阵来执行重映射。

5.1 复制

当使用 cv2.remap() 函数来实现图像复制时,我们可以通过以下步骤进行处理:

  1. 创建网格:首先,我们需要创建一个与原始图像大小相同的网格。这个网格将用于映射坐标值。
height, width = img.shape[:2]
map_x, map_y = np.meshgrid(np.arange(width), np.arange(height))
  1. 设置 map1 和 map2 的值:接下来,我们将 map1 的值设定为对应位置上的 x 轴坐标值,将 map2 的值设定为对应位置上的 y 轴坐标值。
map1 = map_x
map2 = map_y
  1. 使用 remap 函数实现图像复制:将处理后的 map1 和 map2 参数传递给 cv2.remap() 函数,同时指定插值方法(如 cv2.INTER_LINEAR)。
remapped_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR)
  1. 显示复制后的图像:最后,我们可以通过显示函数来展示复制后的图像,以便观察结果。
cv2.imshow("Remapped Image", remapped_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

通过以上步骤,我们可以利用重映射函数 cv2.remap() 来实现图像的复制。这种方法允许我们更灵活地控制图像的映射过程,以实现各种类型的图像处理效果。

5.2 翻转

5.2.1 绕着x轴

在OpenCV中,要实现图像绕x轴翻转,需要进行以下映射过程:

  1. x坐标轴的值保持不变。
  2. y坐标轴的值以x轴为对称轴进行交换。

这反映在两个映射数组(map1和map2)上的变化如下:

  • 对于map1,其值保持不变。
  • 对于map2,需要将其值调整为“总行数-1-当前行号”。

需要注意的是,在OpenCV中,行号的下标是从0开始的。因此,在对称关系中存在一个规律:“当前行号+对称行号=总行数-1”。据此,在绕着x轴翻转时,map2中当前行的行号应调整为“总行数-1-当前行号”。

5.2.2 绕y轴翻转

要实现图像绕y轴翻转,需要进行以下映射过程:

  1. y坐标轴的值保持不变。
  2. x坐标轴的值以y轴为对称轴进行交换。

这反映在两个映射数组(map1和map2)上的变化如下:

  • 对于map2,其值保持不变。
  • 对于map1,需要将其值调整为“总列数-1-当前列号”。

需要注意的是,在OpenCV中,列号的下标是从0开始的。因此,在对称关系中存在一个规律:“当前列号+对称列号=总列数-1”。据此,在绕着y轴翻转时,map1中当前列的列号应调整为“总列数-1-当前列号”。

5.2.3 绕x轴、y轴翻转

要实现图像绕x轴、y轴翻转,需要进行以下映射过程:

  1. x坐标轴的值以y轴为对称轴进行交换。
  2. y坐标轴的值以x轴为对称轴进行交换。

这反映在两个映射数组(map1和map2)上的变化如下:

  • 对于map1,需要将其值调整为“总列数-1-当前列号”。
  • 对于map2,需要将其值调整为“总行数-1-当前行号”。

5.2.4 x轴、y轴互换

要实现图像的x轴、y轴互换,需要进行以下映射过程:

对于任意一点,都需要将其x轴、y轴坐标互换。这反映在两个映射数组(mapx和mapy)上的变化如下:

  • 对于mapx,其值调整为所在行的行号。
  • 对于mapy,其值调整为所在列的列号。

需要注意的是,如果行数和列数不一致,上述运算可能存在值无法映射的情况。默认情况下,无法完成映射的值会被处理为0。

5.3 图像缩放

上述介绍的映射都是直接完成的整数映射,处理起来比较方便。在处理更复杂的问题时,
就需要对行、列值进行比较复杂的运算来实现。

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

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

相关文章

元素的点击操作

元素的点击操作 .click 语法 // 单击某个元素 .click()// 带参数的单击 .click(options)// 在某个位置点击 .click(position)// 在某个位置点击,且带参数 .click(position, options)// 根据页面坐标点击 .click(x, y)// 根据页面坐标点击,且带参数 .c…

区间第k小数 (可持久化线段树、主席树)

题意:多次询问,每次询问某区间的第k小数。 可持久化线段树: 掺杂了一点前缀和的思想,对于每一个1 ~ i 的区间都建一个树,每个节点存的都是一个线段树,值存的是当前区间中初始数组按大小排序后[l, r]之间的…

前缀和的动态维护——树状数组[C/C++]

文章目录 前言lowbitlowbit的定义lowbit的计算 树状数组的思想树状数组的操作单点修改 update前缀查询 query树状数组的建立 build 前言 树状数组巧妙了利用位运算和树形结构实现了允许单点修改的情况下,动态维护前缀和,并且实现单点修改和前缀和查询的效…

如何用CHAT分析网络流行语的构成特点及趋势?

问CHAT:请分析下网络流行语的构成特点及趋势 CHAT回复: 网络流行语的构成特点: 1. 新颖性:网络流行语象征着新潮的概念、思想和观点,它们新颖独特且易于传播。 2. 深入人心的设定:网络流行语通常是由大众…

四川思维跳动商务信息咨询有限公司引领电商服务的先锋

在当今数字化时代,抖音电商作为新型的电子商务模式,已经深入到各个领域。在这个大背景下,四川思维跳动商务信息咨询有限公司以其独特的思维模式和卓越的技术实力,引领着抖音电商服务的发展。 四川思维跳动商务信息咨询有限公司以…

ADManager Plus:全能Active Directory管理的得力助手

一、简介 ADManager Plus是一款功能强大的Active Directory(AD)管理工具,为企业提供了全面、高效的AD管理解决方案。它不仅简化了AD管理的复杂性,还提高了管理员的工作效率。作为一款综合性的工具,ADManager Plus涵盖…

nohup 实现远程运行不关机操作

nohup 实现远程运行不宕机操作 python nohup 实现远程运行不宕机操作 - python教程网 远程运行最怕断电,训练了几个小时的数据说没就没,或者停止运行。 用nohup 记录代码的输出,还可以不受断电的影响。 方法 1. 用nohup 运行一个python文…

公众号gif图怎么制作?一招三步就能解决

在公众号中添加gif动图可以增加文章的气氛,提高阅读者的兴趣。那么,公众号里的gif动图是怎么制作的呢?给大家分享一款gif动图制作(https://www.gif.cn/)工具。无需下载软件,上传两张及以上的jpg、png格式图…

飞书多维表格【单选】的排序规则

飞书多维表格的排序竟然不是根据拼音排的,而是根据单选的先后顺序进行排序的。

Python requests请求响应以流stream的方式打印输出

如果你使用的请求库是requests,那么你必须了解的大模型里的请求怎么响应式的接收并打印出来的。 这里给大家写一下正式的书写方式: import requestsurl "http://localhost:8080/stream"payload {} headers {}response requests.request("GET&q…

Linux:进度条(小程序)以及git三板斧

Linux小程序&#xff1a;进度条 在实现小程序前我们要弄清楚&#xff1a; 1.缓冲区&#xff1b; 2.回车与换行。 缓冲区&#xff1a; 分别用gcc来编译下面两个程序&#xff1a; 程序一&#xff1a; #include <stdio.h> int main() { printf("hello Makefil…