《数字图像处理-OpenCV/Python》连载(44)图像的投影变换
《数字图像处理-OpenCV/Python》连载(44)图像的投影变换
本书京东优惠购书链接:https://item.jd.com/14098452.html
本书CSDN独家连载专栏:https://blog.csdn.net/youcans/category_12418787.html

第 6 章 图像的几何变换
几何变换分为等距变换、相似变换、仿射变换和投影变换,是指对图像的位置、大小、形状和投影进行变换,将图像从原始平面投影到新的视平面。OpenCV图像的几何变换,本质上是将一个多维数组通过映射关系转换为另一个多维数组。
本章内容概要
- 介绍仿射变换,学习使用仿射变换矩阵实现图像的仿射变换。
- 学习使用函数实现图像的平移、缩放、旋转、翻转和斜切。
- 介绍投影变换,学习使用投影变换矩阵实现图像的投影变换。
- 介绍图像的重映射,学习使用映射函数实现图像的自定义变换和动态变换。
6.6 图像的投影变换
透视变换(Perspective Transformation)是OpenCV中常用的投影变换,是指将图像投影到一个新的视平面。投影变换的特点是原始图像中的平行关系和比例关系都可以改变,但图像中的直线在投影变换后仍然能保持直线。
投影变换可以通过对三维空间中的物体旋转进行校正,主要用于图像拼接和校正透视投影导致的图像失真。
投影变换的方法是在原始图像上确定不共线的4个点,给定这4个点在变换图像中的位置,就确定了一个投影变换,其变换关系可以由如下的3×3矩阵来描述。
[ x ~ y ~ z ~ ] = M P [ x y z ] , M P = [ M 11 M 12 M 13 M 21 M 22 M 23 M 31 M 32 M 33 ] \begin{bmatrix} \tilde{x}\\ \tilde{y}\\ \tilde{z} \end{bmatrix} = M_P \begin{bmatrix} x\\ y\\ z \end{bmatrix} ,\hspace{1em} M_P= \begin{bmatrix} M_{11} &M_{12} &M_{13}\\ M_{21} &M_{22} &M_{23}\\ M_{31} &M_{32} &M_{33} \end{bmatrix} x~y~z~ =MP xyz ,MP= M11M21M31M12M22M32M13M23M33
仿射变换是在二维平面进行变换的,而投影变换是在三维坐标系进行变换的。仿射变换是3点变换,投影变换是4点变换。比较仿射变换与投影变换的描述公式,仿射变换可以被视为z轴不变的透视变换。
在OpenCV中,先由函数cv.getPerspectiveTransform计算投影变换矩阵 M P M_P MP,再由函数cv.warpPerspective根据投影变换矩阵 M P M_P MP 计算得到投影变换图像。
函数cv.getPerspectiveTransform能根据图像中不共线的4个点在变换前后的对应位置坐标,求解得到投影变换矩阵 M P M_P MP。
函数原型
cv.getPerspectiveTransform(src, dst[,solveMethod]) → MP
参数说明
- src:原始图像中不共线4个点的坐标,是形状为(4,2)的Numpy数组。
- dst:投影变换图像中对应的不共线4个点的坐标,是形状为(4,2)的Numpy数组。
- solveMethod:矩阵分解方法。
- DECOMP_LU:选择最佳轴的高斯消元法,默认方法。
- DECOMP_SVD:奇异值分解(SVD)方法。
- DECOMP_EIG:特征值分解方法,必须与src对称。
- DECOMP_CHOLESKY:Cholesky LLT分解方法。
- DECOMP_QR:正交三角(QR)分解方法。
- DECOMP_NORMAL:使用正则方程,与前述方法联合使用。
- MP:投影变换矩阵,是形状为(3,3)、类型为np.float32的Numpy数组。
注意问题
- (1)虽然参数src、dst通常表示输入、输出图像,但在函数cv.getPerspectiveTransform中是指原始图像与变换图像中不共线的4个点,也被称为四边形的顶点。
- (2) 参数src、dst是形状为(4,2)的Numpy数组,数值是图像中4个顶点的坐标(x,y)。
函数cv.warpPerspective可通过投影变换矩阵计算投影变换图像。
函数原型
cv.warpPerspective (src, M, dsize[, dst, flags, borderMode, borderValue]) → dst
由投影变换矩阵M计算投影变换图像的公式为
参数说明
- src:原始图像,是Numpy数组。
- dst:投影变换输出图像,类型与src相同,图像尺寸由参数dsize确定。
- M:投影变换矩阵,是形状为(3,3)、类型为np.float32的Numpy数组。
- dsize:输出图像大小,格式为元组(w,h)。
- flags:插值方法与逆变换标志,可选项。
- INTER_LINEAR:双线性插值,默认方法。
- INTER_NEAREST:最近邻插值。
- WARP_INVERSE_MAP:逆变换标志。
- borderMode:边界扩充方法,可选项,默认为cv.BORDER_CONSTANT。
- borderValue:边界填充值,可选项,默认值为0,表示黑色填充。
注意问题
- (1) 输出图像大小dsize的格式为(w,h),与OpenCV中图像形状(h,w)的顺序相反。
- (2) 通过函数cv.warpPerspective计算投影变换,投影变换矩阵M的形状为(3,3),数据类型必须是np.float32。
- (3) 当flags设为WARP_INVERSE_MAP时,先由投影变换矩阵计算逆投影变换矩阵,再计算输入图像的逆投影变换图像。
【例程0606】基于投影变换实现图像校正
手机或相机拍摄的照片,通常都存在投影变形。本例程通过投影变换实现图像校正。
先用鼠标在图像中依次选取矩形的4个顶点,获取4个顶点的坐标,再根据长宽比计算4个顶点在投影变换后的坐标,进行投影变换,就可以实现图像校正。
# 【0606】基于投影变换实现图像校正
import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltdef onMouseAction(event, x, y, flags, param): # 鼠标交互 (单击选点,右击完成)setpoint = (x, y)if event == cv.EVENT_LBUTTONDOWN: # 单击pts.append(setpoint) # 选中一个多边形顶点print("选择顶点 {}:{}".format(len(pts), setpoint))if __name__ == '__main__':img = cv.imread("../images/Fig0602.png") # 读取彩色图像(BGR)imgCopy = img.copy()height, width = img.shape[:2]# 鼠标交互从输入图像选择 4 个顶点print("单击左键选择 4 个顶点 (左上-左下-右下-右上):")pts = [] # 初始化 ROI 顶点坐标集合status = True # 进入绘图状态cv.namedWindow('origin') # 创建图像显示窗口cv.setMouseCallback('origin', onMouseAction, status) # 绑定回调函数while True:if len(pts) > 0:cv.circle(imgCopy, pts[-1], 5, (0,0,255), -1) # 绘制最近的一个顶点if len(pts) > 1:cv.line(imgCopy, pts[-1], pts[-2], (255, 0, 0), 2) # 绘制最近的一段线段if len(pts) == 4: # 已有 4个顶点,结束绘制cv.line(imgCopy, pts[0], pts[-1], (255,0,0), 2) # 绘制最后的一段线段cv.imshow('origin', imgCopy)cv.waitKey(1000)breakcv.imshow('origin', imgCopy)cv.waitKey(100)cv.destroyAllWindows() # 释放图像窗口ptsSrc = np.array(pts) # 列表转换为 (4,2),Numpy 数组print(ptsSrc)# 计算投影变换矩阵 MPptsSrc = np.float32(pts) # 列表转换为Numpy数组,图像4个顶点坐标为 (x,y)x1, y1, x2, y2 = int(0.1*width), int(0.1*height), int(0.9*width), int(0.9*height)ptsDst = np.float32([[x1,y1], [x1,y2], [x2,y2], [x2,y1]]) # 投影变换后的 4 个顶点坐标MP = cv.getPerspectiveTransform(ptsSrc, ptsDst)# 投影变换dsize = (450, 400) # 输出图像尺寸为 (w, h)perspect = cv.warpPerspective(img, MP, dsize, borderValue=(255,255,255)) # 投影变换print(img.shape, ptsSrc.shape, ptsDst.shape)plt.figure(figsize=(9, 3.4))plt.subplot(131), plt.axis('off'), plt.title("1.Original")plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))plt.subplot(132), plt.axis('off'), plt.title("2.Selected vertex")plt.imshow(cv.cvtColor(imgCopy, cv.COLOR_BGR2RGB))plt.subplot(133), plt.axis('off'), plt.title("3.Perspective correction")plt.imshow(cv.cvtColor(perspect, cv.COLOR_BGR2RGB))plt.tight_layout()plt.show()
程序说明:
(1) 本例程设置了回调函数,通过鼠标交互从输入图像选择了4个顶点。鼠标交互操作的使用方法详见4.9节。
(2) 投影变换后4个顶点的坐标是用户设定的,可以根据需要修改。
(3) 基于投影变换实现图像校正的运行结果如图6-6所示,图6-6(1)所示为原始图像,图6-6(2)所示为用鼠标在原始图像上选定棋盘的4个顶点,图6-6(3)所示为投影变换后的图像。可以看出,原始图像中透视拍照的倾斜棋盘被校正为矩形。

*图6-6 图像的投影变换
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/134487182)
Copyright 2023 youcans, XUPT
Crated:2023-11-20
欢迎关注本书CSDN独家连载专栏
《数字图像处理-OpenCV/Python》连载: https://blog.csdn.net/youcans/category_12418787.html
相关文章:
《数字图像处理-OpenCV/Python》连载(44)图像的投影变换
《数字图像处理-OpenCV/Python》连载(44)图像的投影变换 本书京东优惠购书链接:https://item.jd.com/14098452.html 本书CSDN独家连载专栏:https://blog.csdn.net/youcans/category_12418787.html 第 6 章 图像的几何变换 几何变…...
AI机器学习 | 基于librosa库和使用scikit-learn库中的分类器进行语音识别
专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https:/…...
Asp.net MVC Api项目搭建
整个解决方案按照分层思想来划分不同功能模块,以提供User服务的Api为需求,各个层次的具体实现如下所示: 1、新建数据库User表 数据库使用SQLExpress版本,表的定义如下所示: CREATE TABLE [dbo].[User] ([Id] …...
C语言中文网 - Shell脚本 - 8
第1章 Shell基础(开胃菜) 8. Linux Shell命令提示符 启动 Linux 桌面环境自带的终端模拟包,或者从 Linux 控制台登录后,便可以看到 Shell 命令提示符。看见命令提示符就意味着可以输入命令了。命令提示符不是命令的一部分&#x…...
性能测试学习——项目环境搭建和Jmete学习二
项目环境搭建、Jmeter学习二 环境的部署虚拟机的安装虚拟机中添加项目操作步骤 使用环境的注意事项Jmeter的安装和简单使用Jemter的使用的进阶Jemter元件 Jmeter属性执行顺序和作用域作用域以自定义用户变量和用户参数(前置处理器)为例如何解决用户变量和线程组同级时ÿ…...
C++标准模板库(STL)-map介绍
C标准库中的map是一种关联容器,它提供了键值对的映射关系。每个键值对中的键都是唯一的,通过键可以访问对应的值。 map基本操作 插入元素: 使用insert函数插入元素,该函数有两种形式: // 插入一个pair<const Ke…...
使用docker部署ELK日志框架-Elasticsearch
一、ELK知识了解 1-ELK组件 工作原理: (1)在所有需要收集日志的服务器上部署Logstash;或者先将日志进行集中化管理在日志服务器上,在日志服务器上部署 Logstash。 (2)Logstash 收集日志&#…...
第7章 模式匹配与正则表达式
目录 1. 不用正则表达式来查找文本模式2. 用正则表达式来查找文本模式2.1 创建正则表达式(Regex)对象2.2 匹配Regex对象 3. 用正则表达式匹配更多模式3.1 利用括号分组3.2 用管道匹配多个分组3.3 用问号实现可选匹配3.4 用星号匹配零次或多次3.5 用加号匹…...
单元测试实战(三)JPA 的测试
为鼓励单元测试,特分门别类示例各种组件的测试代码并进行解说,供开发人员参考。 本文中的测试均基于JUnit5。 单元测试实战(一)Controller 的测试 单元测试实战(二)Service 的测试 单元测试实战&am…...
初刷leetcode题目(3)——数据结构与算法
😶🌫️😶🌫️😶🌫️😶🌫️Take your time ! 😶🌫️😶🌫️😶🌫️😶🌫️…...
76基于matlab的免疫算法求解配送中心选址问题,根据配送地址确定最佳配送中心地址位置。
基于matlab的免疫算法求解配送中心选址问题,根据配送地址确定最佳配送中心地址位置。数据可更换自己的,程序已调通,可直接运行。 76matlab免疫算法配送中心选址 (xiaohongshu.com)...
C++二分查找算法:找到 Alice 和 Bob 可以相遇的建筑
本文涉及的基础知识点 二分查找算法合集 离线查询 题目 给你一个下标从 0 开始的正整数数组 heights ,其中 heights[i] 表示第 i 栋建筑的高度。 如果一个人在建筑 i ,且存在 i < j 的建筑 j 满足 heights[i] < heights[j] ,那么这个…...
建立跨层全栈的区块链安全保障系统-应用层,系统层,设施层
目录 建立跨层全栈的区块链安全保障系统 应用层 系统层 设施层...
程序员告诉你:人工智能是什么?
随着科技的快速发展,人工智能这个词汇已经逐渐融入了我们的日常生活。然而,对于大多数人来说,人工智能仍然是一个相对模糊的概念。 首先,让我们从人工智能的定义开始。人工智能是一种模拟人类智能的技术,它涵盖了多个领…...
飞书开发学习笔记(七)-添加机器人及发送webhook消息
飞书开发学习笔记(七)-添加机器人及发送webhook消息 一.添加飞书机器人 1.1 添加飞书机器人过程 在群的右上角点击折叠按键…选择 设置 群机器人中选择 添加机器人 选择自定义机器人,通过webhook发送消息 弹出的信息中有webhook地址,选择复制。 安…...
C/C++统计数 2021年12月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析
目录 C/C统计数 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 C/C统计数 2021年12月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 给定一个数的序列S,以及一个区间[L, R], 求序列…...
从一到无穷大 #19 TagTree,倒排索引入手是否是优化时序数据库查询的通用方案?
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。 文章目录 文章主旨时序数据库查询的一般流程扫描维度聚合时间聚合管控语句 TagTree整体结构索引…...
程序员带你入门人工智能
随着人工智能技术的飞速发展,越来越多的程序员开始关注并学习人工智能。作为程序员,我们可能会对如何开始了解人工智能感到困惑。今天,我将向大家介绍一些如何通过自学了解人工智能的经验和方法,帮助大家更好地入门这个充满挑战和…...
机器学习笔记 - 了解常见开源文本识别数据集以及了解如何创建用于文本识别的合成数据
一、部分开源数据集 以下是一些英文可用的开源文本识别数据集。 ICDAR 数据集:ICDAR 代表国际文档分析和识别会议。该活动每两年举行一次。他们带来了一系列塑造了研究社区的场景文本数据集。例如, ICDAR-2013和ICDAR-2015数据集。 MJSynth 数据集:该合成词数据集由牛津大…...
openssl开发详解
文章目录 一、openssl 开发环境二、openssl随机数生成三、openssl对称加密3.1 SM43.2 AES3.3 DES3.4 3DES 四、openssl非对称加密4.1 SM24.2 RSA4.3 ECC 五、openssl的hash5.1 SM35.2 md55.3 sha256 五、证书5.1 证书格式 六、openssl网络编程七、openssl调试FIDO流程 一、open…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
