opencv-24 图像几何变换03-仿射-cv2.warpAffine()

什么是仿射?

仿射变换是指图像可以通过一系列的几何变换来实现平移、旋转等多种操作。该变换能够
保持图像的平直性和平行性。平直性是指图像经过仿射变换后,直线仍然是直线;平行性是指 图像在完成仿射变换后,平行线仍然是平行线。

OpenCV 中的仿射函数为 cv2.warpAffine(),其通过一个变换矩阵(映射矩阵)M 实现变换,
具体为:
dst(𝑥, 𝑦) = src(𝑀11𝑥 + 𝑀12𝑦 + 𝑀13, 𝑀21𝑥 + 𝑀22𝑦 + 𝑀23)
如图 5-2 所示,可以通过一个变换矩阵 M,将原始图像 O 变换为仿射图像 R

在这里插入图片描述
因此,可以采用仿射函数 cv2.warpAffine()实现对图像的旋转,该函数的语法格式如下:

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

式中:
dst 代表仿射后的输出图像,该图像的类型和原始图像的类型相同。

dsize 决定输出图像的实际大小。

src 代表要仿射的原始图像。

M 代表一个 2×3 的变换矩阵。使用不同的变换矩阵,就可以实现不同的仿射变换。

dsize 代表输出图像的尺寸大小。

flags 代表插值方法,默认为 INTER_LINEAR。当该值为 WARP_INVERSE_MAP 时,
意味着 M 是逆变换类型,实现从目标图像 dst 到原始图像 src 的逆变换。
 borderMode 代表边类型, 默认为 BORDER_CONSTANT 。 当 该值为 BORDER_TRANSPARENT 时,意味着目标图像内的值不做改变,这些值对应原始图像内的异常
值。
 borderValue 代表边界值,默认是 0。
通过以上分析可知,在 OpenCV 中使用函数 cv2.warpAffine()实现仿射变换,忽略其可选参数后的语法格式为:

dst = cv2.warpAffine( src , M , dsize )

其通过转换矩阵 M 将原始图像 src 转换为目标图像 dst:

dst(𝑥, 𝑦) = src(𝑀11𝑥 + 𝑀12𝑦 + 𝑀13, 𝑀21𝑥 + 𝑀22𝑦 + 𝑀23)

因此,进行何种形式的仿射变换完全取决于转换矩阵 M。下面分别介绍通过不同的转换矩阵 M 实现的不同的仿射变换。

平移

通过转换矩阵 M 实现将原始图像 src 转换为目标图像 dst:
dst(𝑥, 𝑦) = src(𝑀11𝑥 + 𝑀12𝑦 + 𝑀13, 𝑀21𝑥 + 𝑀22𝑦 + 𝑀23)
将原始图像 src 向右侧移动 100 个像素、向下方移动 200 个像素,则其对应关系为:
dst (x, y) = src (x + 100, y + 200)
将上述表达式补充完整,即:
dst (x, y) = src (1·x + 0·y + 100, 0·x + 1·y + 200)
根据上述表达式,可以确定对应的转换矩阵 M 中各个元素的值为:
 M11=1
 M12=0
 M13=100
 M21=0
 M22=1
 M23=200
将上述值代入转换矩阵 M,得到:

在这里插入图片描述
在已知转换矩阵 M 的情况下,可以直接利用转换矩阵 M 调用函数 cv2.warpAffine() 完成图像的平移。

实验:利用自定义转换矩阵完成图像平移。

import cv2
import numpy as np
img=cv2.imread("lena.png")
height,width=img.shape[:2]
x=100
y=200
M = np.float32([[1, 0, x], [0, 1, y]])
move=cv2.warpAffine(img,M,(width,height))
cv2.imshow("original",img)
cv2.imshow("move",move)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述
其中左图是原始图像,右图是移动结果图像

旋转

在使用函数 cv2.warpAffine()对图像进行旋转时,可以通过函数 cv2.getRotationMatrix2D()
获取转换矩阵。该函数的语法格式为:

retval=cv2.getRotationMatrix2D(center, angle, scale)

式中:
 center 为旋转的中心点。
 angle 为旋转角度,正数表示逆时针旋转,负数表示顺时针旋转。
 scale 为变换尺度(缩放大小)。

利用函数 cv2.getRotationMatrix2D()可以直接生成要使用的转换矩阵 M。

例如,想要以图像中心为圆点,逆时针旋转 45°,并将目标图像缩小为原始图像的 0.6 倍,则在调用函数
cv2.getRotationMatrix2D()生成转换矩阵 M 时所使用的语句为:

M=cv2.getRotationMatrix2D((height/2,width/2),45,0.6)

实验2:完成图像旋转

代码:

import cv2
import numpy as np
img=cv2.imread("lena.png")
height,width=img.shape[:2]
M=cv2.getRotationMatrix2D((width/2,height/2),45,0.6)
rotate=cv2.warpAffine(img,M,(width,height))
cv2.imshow("original",img)
cv2.imshow("rotation",rotate)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
其中左图是原始图像,右图是旋转结果图像

更复杂的仿射变换

对于更复杂仿射变换,OpenCV 提供了
函数 cv2.getAffineTransform()来生成仿射函数 cv2.warpAffine()所使用的转换矩阵 M。该函数的语法格式为:

retval=cv2.getAffineTransform(src, dst)

式中:
 src 代表输入图像的三个点坐标。
 dst 代表输出图像的三个点坐标。
在该函数中,其参数值 src 和 dst 是包含三个二维数组(x, y)点的数组。上述参数通过函数
cv2.getAffineTransform()定义了两个平行四边形。src 和 dst 中的三个点分别对应平行四边形的
左上角、右上角、左下角三个点。函数 cv2.warpAffine()以函数 cv2.getAffineTransform()获取的
转换矩阵 M 为参数,将 src 中的点仿射到 dst 中。函数 cv2.getAffineTransform()
对所指定的点完成映射后,将所有其他点的映射关系按照指定点的关系计算确定。

实验3:完成图像仿射

import cv2
import numpy as np
img=cv2.imread('lena.png')
rows,cols,ch=img.shape
#定义三个点
p1=np.float32([[0,0],[cols-1,0],[0,rows-1]])print(p1)
#定义三个点的变换位置
p2=np.float32([[0,rows*0.33],[cols*0.85,rows*0.25],[cols*0.15,rows*0.7]])
print(p2)
#生成变换矩阵
M=cv2.getAffineTransform(p1,p2)
#进行仿射变换
dst=cv2.warpAffine(img,M,(cols,rows))
cv2.imshow("origianl",img)
cv2.imshow("result",dst)
cv2.waitKey()
cv2.destroyAllWindows()

首先构造了两个三分量的点集合 p1 和 p2,分别用来指代原始图像和目标图像内平行四边形的三个顶点(左上角、右上角、左下角)。
然后使用
M=cv2.getAffineTransform(p1,p2)
获取转换矩阵 M。接下来,
dst=cv2.warpAffine(img,M,(cols,rows))
完成了从原始图像到目标图像的仿射。

运行结果:

其中左图是原始图像,右图是仿射结果图像

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

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

相关文章

SQL注入--题目

联合查询注入: bugku-这是一个神奇的登录框 手工注入: 点吧,输入0’发现还是: 输入0" 发现报错: 确定可以注入,判断字段有多少个 0"order by 1,2,3# 发现: 说明有两列。 输入 0&qu…

【论文阅读22】Label prompt for multi-label text classification

论文相关 论文标题:Label prompt for multi-label text classification(基于提示学习的多标签文本分类) 发表时间:2023 领域:多标签文本分类 发表期刊:Applied Intelligence(SCI二区&#xff0…

SpringBoot整合Elasticsearch

SpringBoot整合Elasticsearch SpringBoot整合Elasticsearch有以下几种方式: 使用官方的Elasticsearch Java客户端进行集成 通过添加Elasticsearch Java客户端的依赖,可以直接在Spring Boot应用中使用原生的Elasticsearch API进行操作。参考文档 使用Sp…

数据库中的事务处理

MySQL的事务处理:只支持 lnnoDB 和BDB数据表类型 1.事务就是将一组SQL语句放在同一批次内去执行 2.如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行 MySQL的事务实现方法一: select autocommit 查询当前事务提交模式 set a…

机器学习深度学习——图像分类数据集

👨‍🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——softmax回归(下) 📚订阅专栏:机器学习&&深度学习…

PHP在线相册--【强撸项目】

强撸项目系列总目录在000集 PHP要怎么学–【思维导图知识范围】 文章目录 本系列校训本项目使用技术 上效果图phpStudy 设置导数据库项目目录如图:代码部分:主页 配套资源作业: 本系列校训 用免费公开视频,卷飞培训班哈人&…

【Matlab】基于粒子群优化算法优化BP神经网络的数据回归预测(Excel可直接替换数据)

【Matlab】基于粒子群优化算法优化 BP 神经网络的数据回归预测(Excel可直接替换数据) 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码5.1 fun.m5.2 main.m 6.完整代码6.1 fun.m6.2 main.m 7.运行结果 1.模型原理 基于粒子群优化算法(…

国标GB28181协议视频平台EasyCVR修改录像计划等待时间较长的原因排查与解决

音视频流媒体视频平台EasyCVR拓展性强,视频能力丰富,具体可实现视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、H.265自动转码H.264、平台级联等。为了便于用户二次开发、调用与集成&…

MTK系统启动流程

MTK系统启动流程 boot rom -> preloader ->lk ->kernel ->Native -> Android 1、Boot rom:系统开机,最先执行的是固化在芯片内部的bootrom,其作用主要有 a.初始化ISRAM和EMMC b.当系统全擦后 ,也会配置USB,用来仿…

CSS 瀑布流效果效果

示例 <!DOCTYPE html> <html lang="cn"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>瀑布流效果</title><style>…

IMU和视觉融合学习笔记

利用纯视觉信息进行位姿估计&#xff0c;对运动物体、光照干扰、场景纹理缺失等情况&#xff0c;定位效果不够鲁棒。当下&#xff0c;视觉与IMU融合(VI-SLAM&#xff09;逐渐成为常见的多传感器融合方式。视觉信息与IMU 数据进行融合&#xff0c;根据融合方式同样可分为基于滤波…

Rust vs Go:常用语法对比(八)

题目来自 Golang vs. Rust: Which Programming Language To Choose in 2023?[1] 141. Iterate in sequence over two lists Iterate in sequence over the elements of the list items1 then items2. For each iteration print the element. 依次迭代两个列表 依次迭代列表项1…

聊天机器人如何增加电子商务销售额

聊天机器人和自动化对企业和客户来说都是福音。自动对话和聊天机器人&#xff08;以下统称为“自动化”&#xff09;通过自动回答问题或分配会话信息来帮助用户浏览品牌网站或电商商店。即时答案对客户来说非常有用&#xff0c;使用自动化也可以让原本与客户聊天的客服员工专注…

MacDroid for Mac:在Mac上访问和传输Android文件的最简单方式

MacDroid for Mac是一款帮助用户在Mac和Android设备之间传输文件的软件。由于Mac OS X本身并不支持MTP协议&#xff0c;所以透过USB将Android设备连接到Mac电脑上是无法识别的&#xff0c;更别说读取里面的文件了。 MacDroid可以帮助您轻松搞定这个问题&#xff0c;您可以将An…

产业大数据应用:洞察企业全维数据,提升企业监、管、服水平

​在数字经济时代&#xff0c;数据已经成为重要的生产要素&#xff0c;数字化改革风生水起&#xff0c;在新一代科技革命、产业革命的背景下&#xff0c;产业大数据服务应运而生&#xff0c;为区域产业发展主导部门提供了企业洞察、监测、评估工具。能够助力区域全面了解企业经…

output delay 约束

output delay 约束 一、output delay约束概述二、output delay约束系统同步三、output delay约束源同步 一、output delay约束概述 特别注意&#xff1a;在源同步接口中&#xff0c;定义接口约束之前&#xff0c;需要用create_generated_clock 先定义送出的随路时钟。 二、out…

【优选算法题练习】day9

文章目录 一、DP35 【模板】二维前缀和1.题目简介2.解题思路3.代码4.运行结果 二、面试题 01.01. 判定字符是否唯一1.题目简介2.解题思路3.代码4.运行结果 三、724. 寻找数组的中心下标1.题目简介2.解题思路3.代码4.运行结果 总结 一、DP35 【模板】二维前缀和 1.题目简介 DP…

百度智能云连拿四年第一,为什么要深耕AI公有云市场

AI是过去几年云计算市场中的最大变量&#xff0c;而大模型的成熟&#xff0c;毫无疑问将指数级增强这个变量。 记得在2022年年底&#xff0c;生成式AI与大模型开始爆火的时候&#xff0c;我们就曾讨论过一个问题&#xff1a;这轮AI浪潮中&#xff0c;最先受到深刻影响的将是云计…

Oracle 多条记录根据某个字段获取相邻两条数据间的间隔天数,小于31天的记录都筛选出来

需求描述&#xff1a;在Oracle中 住院记录记录表为v_hospitalRecords&#xff0c;表中FIHDATE入院时间&#xff0c;FBIHID是住院号&#xff0c; 我想查询出每个患者在他们的所有住院记录中是否在一个月内再次入院(相邻的两条记录进行比较)&#xff0c;并且住院记录大于一的患者…

qsort的使用及模拟实现

qsort函数是C语言库中提供的一种快速排序&#xff0c;头文件是stdlib.h qsort的使用 qsort函数需要四个参数&#xff1a; 1.排序的起始位置的地址&#xff08;数组名&#xff09;: arr 2.排序元素的个数&#xff1a; sizeof&#xff08;arr)/sizeof(arr[0]) 3.排序元素…