三维错切变换矩阵_图像的仿射变换

目录:

  1. 概述
  2. 图像基本变换
  3. 仿射变换
    1. 原理
    2. python实现

一、概述

图像的几何变换主要包括:平移、缩放、旋转、仿射、透视等等。图像变换是建立在矩阵运算基础上的,通过矩阵运算可以很快的找到不同图像的对应关系。理解变换的原理需要理解变换的构造方法以及矩阵的运算方法。

图像的几何变换主要分为三类:刚性变换、仿射变换和透视变换,如下图:

b4ccf0897d9192b16d7c731bafa3f974.png

仿射变换是从一个二维坐标系变换到另一个二维坐标系,属于线性变换。通过已知3对坐标点可以求得变换矩阵。

透视变换是从一个二维坐标系变换到一个三维坐标系,属于非线性变换。通过已知4对坐标点可以求得变换矩阵。

二、图像基本变换

图像的几何变换包含很多变换,其中有一些基本变换,而仿射变换和透视变换就是对这些基本变换进行组合实现的。

基本变换具体包括:平移(Translation)、缩放(Scale)、旋转(Rotation)、翻转(Flip)和错切(Shear)。

a. 平移

b87e6b80957bf827b02f0a0778bf2ee9.png

84c897b079c54ccbaa6d09a8f495fd08.png

b. 缩放

b4301d563483f14258d1b0b2c232ea22.png

8e81442a9bf989f3406b4065d92e7620.png

c. 旋转

766408a81d986bbdf62b70f5d00a8306.png

a25aa3b949d4ea1afed0a9f15f5b81a9.png

d. 翻转

e0c14e6346a09ebb7405cd5436b5e841.png

9b7471ec6fc16c28470d99b73930aa89.png

e. 错切

错切亦称为剪切或错位变换,包含水平错切和垂直错切,常用于产生弹性物体的变形处理。

2d114d79fc2d9a3aa78908249e344176.png

fcaeeccb70d0a718b80a245e84de5f54.png

3538d798ea2b9d591062f2c21d818e4d.png

下面这张图可能更形象:

1e55537ba13858865644136d5e7dd71c.png

三、仿射变换

3.1、原理

对于二维坐标系的一个坐标点(x,y),可以使用一个2x2矩阵来调整x,y的值,而通过调整x,y可以实现二维形状的线性变换(旋转,缩放),所以整个转换过程就是对(x,y)调整的过程。

仿射变换(Affine Transformation)是指在向量空间中进行一次线性变换(乘以一个矩阵)和一次平移(加上一个向量),变换到另一个向量空间的过程。

仿射变换代表的是两幅图之间的映射关系,仿射变换矩阵为2x3的矩阵,如下图中的矩阵M,其中的B起着 平移 的作用,而A中的对角线决定 缩放,反对角线决定 旋转错切

所以仿射变换可以由一个矩阵A和一个向量B给出:

原像素点坐标(x,y),经过仿射变换后的点的坐标是T,则矩阵仿射变换基本算法原理:

所以仿射变换是一种二维坐标(x, y)到二维坐标(u, v)的线性变换,其数学表达式如下:

其实到这里还没完,我们知道缩放和旋转通过矩阵乘法来实现,而平移是通过矩阵加法来实现的,为了将这几个操作都通过一个矩阵来实现,所以构造出了上面那个 2x3 的矩阵。

但是这个会改变图像的尺寸,比如一个 2x2 的图像,乘以 2x3 的矩阵,会得到 2x3 的图像,所以为了解决这个问题,我们就增加一个维度,也就是构造齐次坐标矩阵。

关于齐次坐标的更多内容可以查看这里,还有这里。

最终得到的齐次坐标矩阵表示形式为:

仿射变换保持了二维图像的“平直性”和“平行性”:

平直性:

  • 直线经仿射变换后还是直线
  • 圆弧经仿射变换后还是圆弧

平行性:

  • 直线之间的相对位置关系保持不变
  • 平行线经仿射变换后依然为平行线
  • 直线上点的位置顺序不会发生变化
  • 向量间夹角可能会发生变化

3.2、python实现

通过仿射变换将图片中的每个像素点按照一定的规律映射到新的位置,仿射变化需要一个转换矩阵,但是由于仿射变换比较复杂,一般很难直接找到这个矩阵,opencv提供了根据源图像和目标图像上三个对应的点来自动创建变换矩阵,矩阵维度为 2x3。

7b9b82329a70212b93104987178a7024.png

两个图像中非共线的三对对应点确定唯一的一个仿射变换。经仿射变换后,图像中的三个关键点依然构成三角形,但三角形形状已经发生变化。

这个函数是 cv2.getAffineTransform(pos1,pos2),其中两个位置就是变换前后的对应位置关系。输出的就是仿射矩阵M,最后这个矩阵会被传给函数 cv2.warpAffine() 来实现仿射变换。

原图为:

4c61bbb1ae5e0d374b31bdc45ac27760.png
import cv2
import numpy as np
img = cv2.imread('image0.jpg', 1)
height, width = img.shape[:2]  # 405x413
# 在原图像和目标图像上各选择三个点
matSrc = np.float32([[0, 0],[0, height-1],[width-1, 0]])
matDst = np.float32([[0, 0],[30, height-30],[width-30, 30]])
# 得到变换矩阵
matAffine = cv2.getAffineTransform(matSrc, matDst)
# 进行仿射变换
dst = cv2.warpAffine(img, matAffine, (width,height))

变换矩阵的数据类型是 np.float32,函数 cv2.warpAffine() 的第三个参数是输出图像的尺寸(宽,高)。

仿射变换后的图:

2aa5142e05da5ef640cebb207192f5e9.png

因为平移和缩放的矩阵的比较简单,我们可以直接手动指定。

# 图像平移
# 移位矩阵,水平方向移动100个像素,竖直方向移动200个像素
matShift = np.float32([[1,0,100],[0,1,200]])  # 2行3列
dst = cv2.warpAffine(img, matShift, (width,height))
# 图像缩放
# 缩放矩阵,长宽各缩放一半
matScale = np.float32([[0.5,0,0],[0,0.5,0]])
dst = cv2.warpAffine(img, matScale, (int(width/2),int(height/2)))

向左下平移:

044112d8b6539b3eea390e5f6e4df8cf.png

缩小50%:

d4b22761c268cc34c1dd9c8c12cbdf17.png

要实现图像旋转,需要通过 cv2.getRotationMatrix2D 来得到二维旋转变换矩阵(2行3列)。

cv2.getRotationMatrix2D 三个参数分别为:1.旋转中心,2.旋转角度,3.缩放比例。角度为正,则图像逆时针旋转,旋转后图像可能会超出边界。

matRotate = cv2.getRotationMatrix2D((width*0.5, height*0.5), 45, 1.0)
dst = cv2.warpAffine(img, matRotate, (width,height))

f581b4fc58ca166090bb31d17ba99de4.png

如果觉得有用,点个赞吧(ง •̀_•́)ง。

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

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

相关文章

app系统服务器出错怎么回事,app连接服务器出错

app连接服务器出错 内容精选换一换接口调用出错将无法获取建立相应隧道连接的必要信息,将无法正常建连云手机设备实例,具体报错示例如下:首先,尝试使用adb connect重新建立连接,依旧报错可通过查看安装目录下的日志adb…

js foreach 跳出循环_VUE.js

Vue.js模板语法vue.js使用了基于HTML的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据,其核心就是一个允许开发者采用简洁的模板语法来将数据渲染进DOM系统。使用各种组件来做成一个项目的话,需要结合单页应用。插值数据绑定最…

2异常处理_异常是什么?什么是常用类?

第一节 异常1. 异常的概念​ 异常(Exception) 即例外,程序没有按自己预想的结果运行出来,出现了非正常情况,即“程序得病了”。怎么让我们写的程序做出合理的处理,不至于崩溃是我们关注的核心。 异常机制就是当程序出现错误&#…

origin三元相图_扩增子图表解读7三元图:三组差异数量和关系

点击上方蓝色「宏基因组」关注我们!专业干货每日推送!背景介绍(Introduction)宏基因组学宏基因组学目前的主要研究方法包括:16S/ITS/18S扩增子、宏基因组、宏转录组和代谢组,其中以扩增子研究最为广泛。目的意义本系列文章将带领大…

写出python字符串三种常用的函数或方法_python中几种常用字符串函数

1、lower()把所有字符换成小写 2、upper()把所有字符换成大写 3、swapcase()大小写互换 4、title()把每个单词首字母大写,他是以所有英文字母的字符来区别是否为一个单词的,eg:s "a是傻b" s2 s.title() 结果为"A傻B",a和b都变成了大写,因为他是根据英文字…

python app开发模块_Python pytkapp包_程序模块 - PyPI - Python中文网

用于开发应用程序的python包 多文档/单文档界面 利用tkinter库和附加tkinter集 小部件。 查看可用演示: pytkapp/demo/run_ptapoptionsdemo.py-为选项的容器运行gui demo(可用的小部件、规则) pytkapp/demo/run_ptamdidemo.py-运行MDI应用程序…

搭建python_Crawlab准备之python+scrapy环境搭建

阅读文本大概需要3分钟。上篇《分布式爬虫管理平台Crawlab开发搭建》把爬虫的管理后台搭建起来了;捣鼓一番发现要真正爬取数据还有下不少的功夫。这篇看看怎么搭建pythonscrapy环境。0x01:安装Python3下载python安装包,具体版本根据自己的系统…

64测试cpu稳定性_SuperPI-圆周率计算与CPU性能与稳定性测试

Super PI是由东京大学Kanada lab出品的一款专用于检测CPU稳定性的软件,目前最新版本是1.9版,更新于2013年了。Super PI软件通过计算预定的圆周率让CPU高负荷运作,从而达到考验CPU计算的能力与稳定的作用。同时也能计算出圆周率来保存到文本文…

传值类型_java中的“传值”与“传址”问题

“用对象来生成对象”“对象作为参数进行传递”“构造方法中的参数为对象”问题本质上是“传值”与“传址”的问题先说结论:1、基本类型(包括String类)作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝&#xff…

两个苹果手机如何同步数据_同步苹果手机和Windows的提醒事项

作为一个学生党,能买得起苹果手机已经是一件很幸福的事情了,拥有苹果电脑只是一个美好的愿望,所以现在常见的搭配就是苹果手机加Window电脑,这样就有一个问题,就是苹果手机和Windows电脑的提醒事项没有办法同步&#x…

低通滤波器算法实现_控制算法手记自抗扰控制的几点思考

写在前面在谈自己的一些思考之前,放上一本简明的教材(只有133页),对自抗扰控制ADRC (Active disturbance rejection control)的起源、基本思路、结构、发展及应用做了阐述,是很好的入门读物。图1. 自抗扰控制入门书籍如果要达到弄懂&#xff…

添加日志_第五章springboot2.0添加aop日志实现记录请求地址

1. 添加spring-boot-starter-aop包<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-aopartifactId><version>2.0.0.RELEASEversion>dependency>2. 新建WebLogAspect类3. 添加Aspect Component注解…

本机连接opc server有部分数据不刷新_实时数据库PI在企业MES系统中的应用

实时数据库是计算机控制系统和上层生产管理系统数据存储和展示的核心。结合河南天冠燃料乙醇有限公司MES系统应用实例&#xff0c;介绍了实时数据库PI的安装部署&#xff0c;建立信号量集和数据导入&#xff0c;以及客户端接口配置&#xff0c;数据库测试等相关主题。通过基于P…

java 数组赋值_自学JAVA每日记录(10)-欢迎指点欢迎共勉

接上一篇编程练习&#xff1a;编写一个JAVA程序&#xff0c;创建指定长度的 int 型数组&#xff0c;并生成 100 以内随机数为数组中的每个元素赋值&#xff0c;然后输出数组要求&#xff1a;1、 要求通过定义带参带返回值的方法来实现2、 通过参数传入数组的长度&#xff08;例…

java异常处理机制_Java编程中的异常机制

本文旨在以初学者的角度来学习Java异常的知识&#xff0c;尽量简单&#xff0c;一些细枝末节的知识不会讲述&#xff0c;但不影响对知识的掌握。&#xff08;比如try-catch可以嵌套&#xff0c;不太会这么用&#xff09;1.什么是异常我们先举个例子int 在IDE里输入这样一个stat…

数组字典_VBA数组与字典解决方案第34讲:数组的传递

大家好&#xff0c;今日我们继续讲解VBA数组与字典解决方案&#xff0c;今日讲解的是第34讲&#xff1a;数组的传递。在应用数组的时候&#xff0c;我们往往需要要把数组的值由一个数组传递给另外一个数组&#xff0c;就如同变量的传递一样&#xff1a;AB 把B值赋给ACA 把A值赋…

为什么代码正确却没有爬虫的信息_为什么敷面膜没有效果?原来这才是敷面膜的正确步骤...

七夕泥萌都去哪浪了&#xff1f;是不是化个美美的妆&#xff0c;然后出门吃吃吃逛逛逛&#xff1f;说到出门前化妆&#xff0c;很多小仙女会在化妆前敷面膜&#xff0c;让皮肤保持一个好状态&#xff0c;壹知肤护肤研究中心贺老师&#xff08;sunny老师&#xff09;提到其实这是…

合并 多个dataframe_什么是Pandas的DataFrame?

1. 什么是DataFrameDataFrame是一个表格型的数据结构&#xff0c;它含有一组有序的列&#xff0c;每列可以是不同的值类型&#xff08;数值、字符串、布尔值等&#xff09;。DataFrame既有行索引也有列索引&#xff0c;它可以被看做由series组成的字典&#xff08;共用同一个索…

web td不对齐_珍稀干货!阿里 Web 音视频开发趟坑指南

作者 | 阿里文娱前端技术专家 归影责编 | 夕颜出品 | CSDN(ID:CSDNnews)这不是一篇基于MSE开发Web播放器的入门文章&#xff0c;而是围绕Web播放器开发遇到的常见问题与解决方案&#xff0c;毕竟入门文章常有而趟坑干货不常有。如果您有Web播放开发经验和音视频技术基础&#x…

subscribe error不执行_你不知道的redis:第三方jar无封装命令我们该怎么执行?

redis的基本操作指令就不多说了&#xff0c;今天对redis的进阶操作给大家介绍一下&#xff0c;以及对于jedis和redisTemplate等工具包没有封装的命令我们该如何使用&#xff1f;相信大家读了本篇对redis的整体会有更深的认知。一、Pipelin模式介绍1、redis的通常使用方式大多数…