OpenCV学习(4.2) 图像的几何变换

1.目标

  • 学习将不同的几何变换应用到图像上,如平移、旋转、仿射变换等。
  • 你会看到这些函数: cv.getPerspectiveTransform

2.缩放

缩放是调整图片的大小。 OpenCV 使用 cv.resize() 函数进行调整。可以手动指定图像的大小,也可以指定比例因子。可以使用不同的插值方法。对于下采样(图像上缩小),最合适的插值方法是 cv.INTER_AREA 对于上采样(放大),最好的方法是 cv.INTER_CUBIC (速度较慢)和 cv.INTER_LINEAR (速度较快)。默认情况下,所使用的插值方法都是 cv.INTER_AREA 。你可以使用如下方法调整输入图片大小:

代码:

import cv2image = r'D:\study\EmotionDetection_RealTime-master\data\data\te\03.jpg'
image = cv2.imread(image)#图像几何变换
import numpy as npres11 = cv2.resize(image,None,fx=2, fy=2, interpolation = cv2.INTER_AREA)
res12 = cv2.resize(image,None,fx=2, fy=2, interpolation = cv2.INTER_LINEAR)
res13 = cv2.resize(image,None,fx=2, fy=2, interpolation = cv2.INTER_CUBIC)
#OR
height, width = image.shape[:2]
res2 = cv2.resize(image,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)cv2.imshow('res11',res11)
cv2.imshow('res12',res12)
cv2.imshow('res13',res13)
cv2.imshow('res2',res2)
cv2.waitKey(0)
cv2.destroyAllWindows()

在OpenCV中,cv2.resize() 函数用于改变图像的大小。您提供的代码行演示了如何将输入图像 image 放大到原来的两倍。

这里是代码行的详细解释:

  • res11 = cv2.resize(image, None, fx=2, fy=2, interpolation = cv2.INTER_AREA):这行代码执行了图像放大的操作。
    • image 是您想要调整大小的图像。
    • None 表示输出图像的大小会根据 fx 和 fy 参数自动计算。如果您想显式指定输出图像的大小,可以传递一个元组 (width, height)
    • fx=2 和 fy=2 表示图像在 x 轴和 y 轴方向上放大两倍。
    • interpolation=cv2.INTER_AREA 是插值方法,用于在放大或缩小图像时确定新像素值。cv2.INTER_AREA 是一种适合缩小图像的插值方法,但如果您是在放大图像,通常使用 cv2.INTER_LINEAR 或 cv2.INTER_CUBIC 会得到更好的结果,因为它们可以提供更平滑的边缘和更少的锯齿效果。

如果您的目的是放大图像,通常建议使用 cv2.INTER_LINEAR 或 cv2.INTER_CUBIC 作为插值方法。

 

输出结果: 

3.平移变换

平移变换是物体位置的移动。如果知道 (x,y) 方向的偏移量,假设为 (t_x,t_y)**,则可以创建如下转换矩阵 **M

您可以将变换矩阵存为 np.float32 类型的 numpy 数组,并将其作为 cv.warpAffine 的第二个参数。请参见以下转换(100,50)的示例:

import numpy as np
import cv2 as cvimg = r'D:\study\EmotionDetection_RealTime-master\data\data\te\03.jpg'
img = cv.imread(img)
cv.imshow('img',img)
print(img.shape)
rows,cols = img.shape[0],img.shape[1]
M1 = np.float32([[1,0,100],[0,1,50]])
M2 = np.float32([[1,0,50],[0,1,100]])
M3 = np.float32([[1,0,-100],[0,1,-50]])
M4 = np.float32([[1,0,-50],[0,1,-100]])
dst1 = cv.warpAffine(img,M1,(cols,rows))
dst2 = cv.warpAffine(img,M2,(cols,rows))
dst3 = cv.warpAffine(img,M3,(cols,rows))
dst4 = cv.warpAffine(img,M4,(cols,rows))
cv.imshow('img1',dst1)
cv.imshow('img2',dst2)
cv.imshow('img3',dst3)
cv.imshow('img4',dst4)
cv.waitKey(0)
cv.destroyAllWindows()

dst1 = cv.warpAffine(img,M1,(cols,rows))

在OpenCV中,cv.warpAffine() 函数用于对图像进行仿射变换。这个函数可以将图像按照给定的变换矩阵进行旋转、平移、缩放等变换。

以下是代码行的详细解释:

  • dst1 = cv.warpAffine(img, M1, (cols, rows))
    • img 是您想要进行仿射变换的输入图像。
    • M1 是一个2x3的变换矩阵,它定义了如何变换图像。这个矩阵通常是通过计算得到的,它包含了图像的旋转、平移和缩放信息。
    • (cols, rows) 是输出图像的大小,cols 是输出图像的列数,rows 是输出图像的行数。这个参数确定了变换后图像的大小。

例如,如果您想要将图像绕其中心旋转30度,您可以首先计算旋转矩阵 M1,然后使用 cv.warpAffine() 函数进行变换

 

cv.warpAffine 函数的第三个参数是输出图像的大小,其形式应为(宽度、高度)。记住宽度=列数,高度=行数。 

输入:

输出:

4.旋转 

以 \theta角度旋转图片的转换矩阵形式为:

但 Opencv 提供了可变旋转中心的比例变换,所以你可以在任意位置旋转图片,修改后的转换矩阵为:

其中:

为了找到这个转换矩阵,opencv 提供了一个函数, cv.getRotationMatrix2D 。请查看下面的示例,它将图像相对于中心旋转 90 度,而不进行任何缩放。

import cv2 as cvimg = r'D:\study\EmotionDetection_RealTime-master\data\data\te\03.jpg'
img = cv.imread(img)
cv.imshow('img',img)rows,cols = img.shape[0],img.shape[1]
# cols-1 and rows-1 are the coordinate limits.
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst = cv.warpAffine(img,M,(cols,rows))
cv.imshow('dst',dst)cv.waitKey(0)
cv.destroyAllWindows()

cv.getRotationMatrix2D 是 OpenCV 库中的一个函数,用于计算二维旋转的变换矩阵。这个变换矩阵可以随后用于 cv.warpAffine 函数中,以实现对图像的旋转。

函数原型如下:

cv.getRotationMatrix2D(center, angle, scale)

参数说明:

  • center:旋转的中心点,通常是一个二元组 (x, y),表示图像中的旋转中心。
  • angle:旋转角度,正值表示逆时针旋转。
  • scale:缩放因子,用于在旋转的同时对图像进行缩放。

返回值是一个 2x3 的浮点型 NumPy 数组,表示旋转变换矩阵。

 

5.仿射变换

仿射变换是一种二维变换,它在平面内将一个图形变换成另一个图形,同时保持原图形中所有点之间的相对位置关系(即直线经过变换后仍然是直线,且平行线经过变换后仍然平行)。在仿射变换中,直线段保持直线且比例不变,但直线段可能会变短或变长。

仿射变换可以由以下几种基本变换组合而成:

  1. 平移(Translation):在平面上沿着某个方向移动所有点。
  2. 旋转(Rotation):围绕某个点旋转所有点。
  3. 缩放(Scaling):放大或缩小所有点,可以有不同的缩放比例沿 x 轴和 y 轴。
  4. 剪切(Shear):使平面上的点沿某个方向移动,移动的距离与点到某条参考线的距离成正比。

在数学上,仿射变换通常表示为一个矩阵和一个向量的组合,形式如下:

                                                               T(x)=Ax+b

其中,A 是一个 2x2 的矩阵,表示旋转、缩放和剪切,b 是一个 2 元素的向量,表示平移,x 是原始点的坐标,T(x) 是变换后点的坐标。

在图像处理中,仿射变换常用于校正图像的视角、校正由于相机镜头造成的畸变、或者将图像中的对象进行几何变换。在 OpenCV 中,可以使用 cv.getAffineTransform 来计算仿射变换矩阵,然后使用 cv.warpAffine 来应用这个变换到图像上。

在仿射变换中,原始图像中的所有平行线在输出图像中仍然是平行的。为了找到变换矩阵,我们需要从输入图像中取三个点及其在输出图像中的对应位置。然后 cv.getAffineTransform 将创建一个 2x3 矩阵,该矩阵将传递给 cv.warpAffine 。

查看下面的示例,并注意我选择的点(用绿色标记):

import numpy as np
import cv2 as cv
from matplotlib import pyplot as pltimg = r'D:\study\EmotionDetection_RealTime-master\data\data\te\03.jpg'
img = cv.imread(img)
cv.imshow('img',img)rows,cols = img.shape[0],img.shape[1]
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv.getAffineTransform(pts1,pts2)
dst = cv.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()cv.waitKey(0)
cv.destroyAllWindows()

6.透视变换 

透视变换(Perspective Transformation)是一种更加一般的变换,它可以将一个平面上的图像映射到另一个平面上,同时保持直线的直线性质,但不保持平行线的平行性。这意味着,透视变换可以改变物体的视角,使得原本平行的线在变换后的图像中会相交,产生一种深度感或透视效果

透视变换在图像处理中的应用非常广泛,比如在图像校正、三维重建、虚拟现实和增强现实等领域。它允许我们从一个特定的视角观察一个物体,就像我们通过窗户看外面的世界,窗户的框架会提供一个不同的视角,即使窗户外的物体是平面的。

在数学上,透视变换通常通过一个3x3的变换矩阵来表示,这个矩阵可以将一个二维坐标系中的点映射到另一个二维坐标系中的点。透视变换矩阵的构造通常需要四个对应的点对,即原始图像中的四个点及其在目标图像中的对应位置。

在OpenCV中,可以使用cv.getPerspectiveTransform函数来计算透视变换矩阵,然后使用cv.warpPerspective函数来应用这个变换到图像上

对透视转换,你需要一个 3x3 变换矩阵。即使在转换之后,直线也将保持直线。要找到这个变换矩阵,需要输入图像上的 4 个点和输出图像上的相应点。在这四点中,任意三点不应该共线。然后通过 cv.getPerspectiveTransform 找到变换矩阵。然后对这个 3x3 变换矩阵使用 **cv.warpPerspective**。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as pltimg = r'D:\study\EmotionDetection_RealTime-master\data\data\te\01.jpg'
img = cv.imread(img)
cv.imshow('img',img)rows,cols = img.shape[0],img.shape[1]
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv.getPerspectiveTransform(pts1,pts2)
dst = cv.warpPerspective(img,M,(rows,cols))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()cv.waitKey(0)
cv.destroyAllWindows()

cv.getPerspectiveTransform 是 OpenCV 库中的一个函数,用于计算透视变换矩阵。透视变换是一种投影变换,它可以将一个平面上的图像映射到另一个平面上,同时保持直线的直线性质,但不保持平行线的平行性。这种变换通常用于校正图像中的透视畸变,例如将照片中的矩形对象(如建筑物的立面)转换为正视图像。

函数原型如下:

cv.getPerspectiveTransform(src, dst)

参数说明:

  • src:一个包含四个源点的 numpy 数组,这些点代表原始图像中的四个角点。
  • dst:一个包含四个目标点的 numpy 数组,这些点代表变换后图像中对应角点的期望位置。

返回值是一个 3x3 的浮点型 NumPy 数组,表示透视变换矩阵。

 

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

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

相关文章

【Vue】小黑记事本

文章目录 一、需求说明二、思路分析三、代码实现 一、需求说明 拆分基础组件渲染待办任务添加任务删除任务底部合计 和 清空功能持久化存储 二、思路分析 拆分基础组件 咱们可以把小黑记事本原有的结构拆成三部分内容:头部(TodoHeader)、列…

基于semantic_kernel的ChatMD系统

问答系统需求文档 一、项目概述 本项目旨在开发一个能够上传 MD 文件,并基于 MD内容进行问答互动的系统。用户可以上传 MD文件,系统将解析 MD内容,并允许用户通过对话框进行问答互动,获取有关 MD文件内容的信息。 二、功能需求…

FreeRTOS学习笔记-基于stm32(8)信号量总结(二值信号量、计数型信号量、互斥信号量、优先级翻转、优先级继承)

一、什么是信号量 信号量是一种队列,用于任务间同步和资源管理的机制,主要用来传递状态。就像是一种特殊的“旗子”或“钥匙”,用来在不同的任务之间进行沟通和协调,确保它们能够正确地配合工作,不会互相干扰。 二、二…

保研面试408复习 8——计算机网络(浏览器http)、离散数学(平面图)、操作系统、数据结构

文章目录 一、计算机网络1、从在浏览器输入网址到页面显示的过程1. 输入网址2. DNS 解析3. 建立TCP连接4. 发送HTTP请求5. 服务器处理请求并响应6. 浏览器处理响应7. 页面渲染 二、离散数学一、平面图1、平面图性质2、Kuratowski定理 三、操作系统四、数据结构 一、计算机网络 …

IDCF五周年专场—【研发效能·创享大会】圆满落幕!

2024 年5 月25 日,【研发效能创享大会】—IDCF五周年专场在北京希尔顿欢朋酒店(大红门)成功举办!本次大会旨在为社区成员提供一个学习与交流的平台,分享技术经验,交流行业见解,促进技术合作与创…

Java模板模式及代码

意图 在父类中定义了算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤,这种类型的设计模式属于行为型模式。 主要解决的问题 解决在多个子类中重复实现相同的方法的问…

北京海淀区永丰产业基地地块出让,海开控股79.17亿元竞得

据悉,位于北京海淀区西北旺镇的永丰产业基地地块正式出让,引起了业界的广泛关注。经过激烈的竞争,最终由海开控股以79.17亿元的价格成功竞得该地块,成交楼面价达到35588元/平方米,溢价率为1.5%。此次出让的地块不仅吸引…

【Java基础】线程的五大状态

新建状态 使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。 就绪状态 当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中&#xff…

景深技术在AI绘画中的魔法:为数字艺术注入新维度

引言: 在人工智能(AI)的浪潮中,绘画艺术领域迎来了革命性的变革。AI绘画不仅改变了创作过程,还为艺术家和设计师提供了前所未有的工具。其中,景深技术作为一种重要的视觉处理手段,在AI绘画中的应…

error:nullptr was not declared in this scope

nullptr是c11的内容,在Qt5.5.0中使用时需要在.pro添加 QMAKE_CXXFLAGS -stdc11

告别繁琐,Xinstall一键解决App代理结算难题!

在移动互联网的浪潮中,App的推广和运营成为了众多企业和开发者关注的焦点。然而,随着App市场的日益竞争,代理结算的复杂性和繁琐性成为了许多推广者头疼的问题。为了解决这个问题,Xinstall凭借其专业的技术和丰富的服务经验&#…

在ros中获取话题的发布节点名称(C++)

文章目录 概要CMakeLists.txt主要代码效果概要 在ROS中,直接从订阅回调函数中获取发布该话题的节点信息并不直接支持。ROS设计的发布-订阅机制并没有直接提供在回调函数中获取发布节点的接口。发布节点的信息主要通过rosgraph等工具来获取。 不过,可以通过以下几种方式间接…

Modebus通信协议 温控器示例

目录 1 指令解释 2 获取动态的CRC 3 crc在线验证 4 16进制正负温度互转 4.2 16进制转温度 4.2 温度转16进制 5 完整工具类 最近安卓工作接了很多硬件,其他的都是发个固定指令,比较有代表性就是温控器和打印机自定义内容所以这个记录接入示例&…

为什么没有输出九九乘法表?

下面的程序本来想输出九九乘法表到屏幕上&#xff0c;为什么没有输出呢&#xff1f;怎样修改&#xff1f; <!DOCTYPE html> <html> <head> <meta charset"utf-8" /> <title>我的HTML练习</title> …

从零开始教你RuoYi-Cloud项目阿里云部署

这里写自定义目录标题 准备需要的文件文件下载运程工具(按需下载)文件上传一、安装Docker环境二、应用部署2.1、Nacos2.2、Nginx2.3、Mysql2.4、Redis2.5、JDK2.6、Docker Compose三、项目部署四、ERROR无法访问云服务器上部署的Docker容器端口冲突或端口占用Linux修改jar包中…

qemu虚拟机安装麒麟v10 arm版系统

截止目前&#xff0c;安装v10 sp1版本系统&#xff0c;&#xff0c;v10 sp3系统无法安装。 1.// 创建虚拟机 最好大于65G qemu-img create -f qcow2 D:\Kylin\Kylindisk.qcow2 70G2.// 使用qemu-system-aarch64.exe命令安装麒麟操作系统&#xff1a; qemu-system-aarch64.exe …

go语言进阶 包

package 包&#xff1a; go 语言使用包&#xff08;package&#xff09;这种语法元素来组织管理源码&#xff0c;所有语法可见性均定义在 package 这个级别 与 Java python 相似 1. main 包&#xff1a; go 语言的程序入口 main() 函数所在的包 (package) 叫做 main包 , mian…

linux内核下rapidio(TSI721)相关笔记汇总

1 驱动的安装 和 主要功能(doorbell, DMA, rionet)的简单测试 linux5.4 下使用rapidio(tsi721)的笔记记录_kernel-rapidio-CSDN博客 2 机理分析 linux内核下&#xff0c;rapidio网络系统建立的过程(枚举 和 发现)_linux rapidio-CSDN博客 linux内核下&#xff0c;(rapidio)T…

新火种AI|倒反天罡!美国名校斯坦福AI团队抄袭中国大模型

作者&#xff1a;一号 编辑&#xff1a;美美 中国大模型被抄袭&#xff0c;怎么不算是某种层面上的国际认可呢&#xff1f; 5月29日&#xff0c;斯坦福大学的一个AI研究团队发布了一个名为「Llama3V」的模型&#xff0c;号称只要 500 美元就能训练出一个 SOTA 多模态模型&am…

Python库之pandas的简介、安装、使用方法详细攻略

Python库之pandas的简介、安装、使用方法详细攻略 简介 pandas 是 Python 中用于数据分析和操作的一个强大库&#xff0c;它提供了快速、灵活和表达力强的数据结构&#xff0c;旨在使数据清洗和分析工作变得更加简单易行。pandas 适用于处理表格数据&#xff08;例如CSV文件、…