OpenCV实现常见的四种图像几何变换


Posted in Python onApril 01, 2022

准备图片

选择一张shape为(500,500,3)的梵高的《星月夜》以便示例。

OpenCV实现常见的四种图像几何变换

1. 缩放 cv2.resize()方法

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

src 原图(的数组)

dsize: 输出图像的大小 格式:(a,b)。

设定dsize后就无需再设置fx和fy

fx 可选参数 水平方向缩放比

fy 可选参数 垂直方向缩放比

fx和fy不同于dsize,fx和fy是各是一个比值,如设为2,则表示放大2倍,设为1/2则表示缩小到原来的1/2

import cv2
img = cv2.imread("The_Starry_Night.jpg")

dst1 = cv2.resize(img, (200, 200))
dst2 = cv2.resize(img, (900, 900))
cv2.imshow("img", img)
cv2.imshow("dst1", dst1)
cv2.imshow("dst2", dst2)
cv2.waitKey()
cv2.destroyAllWindows()

执行结果如图所示,相比原图,图像得到了指定大小的缩小与放大。

OpenCV实现常见的四种图像几何变换

使用fx和fy参数,则需要手动把dsize设为None。

import cv2
img = cv2.imread("The_Starry_Night.jpg")  
# 将宽缩小到原来的1/3、高缩小到原来的1/2
dst3 = cv2.resize(img, None, fx=1 / 3, fy=1 / 2) 
# 将宽高扩大2倍
dst4 = cv2.resize(img, None, fx=2, fy=2)  
cv2.imshow("img", img)
cv2.imshow("dst3", dst3) 
cv2.imshow("dst4", dst4) 
cv2.waitKey() 
cv2.destroyAllWindows()

结果呈现:

OpenCV实现常见的四种图像几何变换

2. 翻转 cv2.flip()方法

flip(src, flipCode, dst=None)

src 图像(数组)

flipCode 翻转代码。可以是0,正数,负数。0表示沿X轴(水平方向的轴)翻转。1表示沿Y轴(竖直方向的轴)翻转。

负数表示同时沿X轴和Y轴翻转。

讲原图经过着三种翻转后,与原图拼在一块,呈现出了这种奇观:

import cv2
img = cv2.imread("The_Starry_Night.jpg")
dst1 = cv2.flip(img, 0)
dst2 = cv2.flip(img, 1)
dst3 = cv2.flip(img, -1)
cv2.imshow("img", img)
cv2.imshow("dst1", dst1)
cv2.imshow("dst2", dst2)
cv2.imshow("dst3", dst3)
cv2.waitKey()
cv2.destroyAllWindows()

OpenCV实现常见的四种图像几何变换

将翻转结果放在同一张画布中

import cv2
import numpy as np
img = cv2.imread("The_Starry_Night.jpg")
dst1 = cv2.flip(img, 0)
dst2 = cv2.flip(img, 1)
dst3 = cv2.flip(img, -1)
a, b, c = img.shape
canvas = np.ones((2 * a, 2 * b, c), np.uint8) * 255
canvas[0:b, 0:a] = img
canvas[b:2*b, 0:a] = dst1
canvas[0:b, a:2*a] = dst2
canvas[b:2*b, a:2*a] = dst3
cv2.imshow("pic", canvas)
cv2.waitKey()
cv2.destroyAllWindows()
# 保存图片
# cv2.imwrite("final_pic", canvas)

结果呈现:

OpenCV实现常见的四种图像几何变换

3. 仿射变换 warpAffine()方法

常见的仿射变换有平移,旋转和倾斜变换。

仿射变换使用cv2.warpAffine()方法完成

warpAffine(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)

src 原图

M 是一个二行三列的矩阵,也称仿射矩阵。warpAffine方法根据此矩阵的值来变换像素的位置。

M = [[a, b, c], [d, e, f]],则像素的变换公式为:

X = x × a + y × b + c

Y = x × d + y × e + f

其中x,y指原像素的x、y轴坐标。X,Y指变换后的X,Y坐标。

dsize 输出图像的尺寸。(不带放缩,增大的部分用黑色色素(0)填充)

这三个参数是常用的参数。其余参数建议使用默认值。

flags表示插入方式,borderMode是边界类型,borderValue表示边界值(默认0)。dst表示反射变换后输出的图像。

3.1 平移

以将《星月夜》向左平移50个像素,向下平移100个像素为例。

则M数组应写为[[1, 0, 50], [0, 1, 100]]:

import cv2
import numpy as np
img = cv2.imread("The_Starry_Night.jpg")
rows = len(img)
cols = len(img[0])
M = np.float32([[1, 0, 50],
                [0, 1, 100]]) 
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow("img", img) 
cv2.imshow("dst", dst) 
cv2.waitKey() 
cv2.destroyAllWindows()

OpenCV实现常见的四种图像几何变换

如图所示,图像按照我们的预期成功被平移。

只是这样得到的图像有色素损失,我们丢失了超出画布之外的数据。

为了避免损失,可以取设置dsize参数来控制输出图像的大小。

修改后的代码如下:

import cv2
import numpy as np
img = cv2.imread("The_Starry_Night.jpg")
rows = len(img)
cols = len(img[0])
M = np.float32([[1, 0, 50],
                [0, 1, 100]])
dst = cv2.warpAffine(img, M, (cols+200, rows+200))
cv2.imshow("img", img)
cv2.imshow("dst", dst)
cv2.waitKey()
cv2.destroyAllWindows()

优化后的程序执行效果:

OpenCV实现常见的四种图像几何变换

3.2 旋转

旋转也是通过M矩阵来实现的,这个矩阵的运算较复杂,

OpenCV提供了getRotationMatrix2D()方法来计算旋转操作的M矩阵

getRotationMatrix2D(center, angle, scale)

center 指旋转中心的坐标

angle指旋转的角度

scale值缩放的比例。(旋转过程支持缩放)

import cv2
img = cv2.imread("The_Starry_Night.jpg")
rows = len(img) 
cols = len(img[0]) 
center = (rows / 2, cols / 2) 
M = cv2.getRotationMatrix2D(center, 30, 0.8) 
dst = cv2.warpAffine(img, M, (cols, rows)) 
cv2.imshow("img", img) 
cv2.imshow("dst", dst) 
cv2.waitKey() 
cv2.destroyAllWindows()

旋转效果如图所示:

OpenCV实现常见的四种图像几何变换

3.3 倾斜

OpenCV需要定位到图像的三个点的位置来计算倾斜效果,即左上角,右上角和左下角。

图像的倾斜也是根据M矩阵实现,得出矩阵的运算较复杂,通过getAffineTransform 方法实现。

语法

getAffineTransform(src, dst)

src是原图像的左上角,右上角和左下角三个点的坐标。三维数组格式,形如[[a, b], [c, d], [e, f]]。

dst是倾斜后这三个点预期的坐标。格式同上。

要保持左上,右下,左下三个点的顺序不能乱。

以将《星月夜》保持左下角和右上角坐标不变,左上角((0,0)处)向右移动150个像素长度。

代码如下:

import cv2
import numpy as np
img = cv2.imread("The_Starry_Night.jpg")
rows = len(img)
cols = len(img[0])
p1 = np.array([[0, 0], [cols - 1, 0], [0, rows - 1]], dtype=np.float32)
p2 = np.array([[150, 0], [cols - 1, 0], [0, rows - 1]], dtype=np.float32)
M = cv2.getAffineTransform(p1, p2)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

程序执行效果如下:

OpenCV实现常见的四种图像几何变换

4. 透视

透视的实现使用的是warpPerspective()方法,而不再是用于平移、旋转、倾斜的warpAffine()方法。

使用warpPerspective()方法也需要通过M矩阵来计算透视效果,计算透视的M矩阵可以使用getPerspectiveTransform()方法。

getPerspectiveTransform(src, dst, solveMethod=None)

该方法常用的参数有两个,分别为原图的四个点的坐标(scr) 和 透视后四个点的坐标(dst)。Opcv需要通过定位图像的这四个点来计算透视效果。四个点依次为左上,右上,左下,右下。

坐标格式为二维数组格式,形如[[a, b],[c, d],[e, f],[g, h]]。

示例代码如下:

import cv2
import numpy as np
img = cv2.imread("The_Starry_Night.jpg")
rows = len(img)
cols = len(img[0])
# 原图的四点坐标
p1 = np.zeros((4, 2), np.float32)
p1[0] = [0, 0]
p1[1] = [cols - 1, 0]
p1[2] = [0, rows - 1]
p1[3] = [cols - 1, rows - 1]
# 透视后的四点坐标
p2 = np.zeros((4, 2), np.float32)
p2[0] = [150, 0]
p2[1] = [cols - 150, 0]
p2[2] = [0, rows - 1]  # 不变
p2[3] = [cols - 1, rows - 1]  # 不变
M = cv2.getPerspectiveTransform(p1, p2)
dst = cv2.warpPerspective(img, M, (cols, rows))
cv2.imshow('The_Starry_Night', img)
cv2.imshow('The_Starry_Night2', dst)
cv2.waitKey()
cv2.destroyAllWindows()

展示原图和透视后的图像效果:

OpenCV实现常见的四种图像几何变换

到此这篇关于OpenCV实现常见的四种图像几何变换的文章就介绍到这了,更多相关OpenCV图像几何变换内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
使用python分析git log日志示例
Feb 27 Python
跟老齐学Python之使用Python查询更新数据库
Nov 25 Python
理解Python中的With语句
Feb 02 Python
python2与python3中关于对NaN类型数据的判断和转换方法
Oct 30 Python
Flask模板引擎之Jinja2语法介绍
Jun 26 Python
python之mock模块基本使用方法详解
Jun 27 Python
Django框架model模型对象验证实现方法分析
Oct 02 Python
numpy ndarray 取出满足特定条件的某些行实例
Dec 05 Python
pytorch实现查看当前学习率
Jun 24 Python
Tensorflow中批量读取数据的案列分析及TFRecord文件的打包与读取
Jun 30 Python
python代码实现猜拳小游戏
Nov 30 Python
python中pdb模块实例用法
Jan 15 Python
关于Python使用turtle库画任意图的问题
Apr 01 #Python
python套接字socket通信
python文件与路径操作神器 pathlib
Python下载商品数据并连接数据库且保存数据
Python turtle编写简单的球类小游戏
Pandas实现DataFrame的简单运算、统计与排序
Mar 31 #Python
Pandas数据结构之Series的使用
Mar 31 #Python
You might like
目录,文件操作详谈―PHP
2006/11/25 PHP
php类中的各种拦截器用法分析
2014/11/03 PHP
PHP用mb_string函数库处理与windows相关中文字符及Win环境下开启PHP Mb_String方法
2015/11/11 PHP
PHP单例模式与工厂模式详解
2017/08/29 PHP
网页自动刷新,不产生嗒嗒声的一个解决方法
2007/03/27 Javascript
为JavaScript提供睡眠功能(sleep) 自编译JS引擎
2010/08/16 Javascript
通过Javascript创建一个选择文件的对话框代码
2012/06/16 Javascript
Javascript基础知识(二)事件
2014/09/29 Javascript
chrome调试javascript详解
2015/10/21 Javascript
JavaScript判断用户名和密码不能为空的实现代码
2016/05/16 Javascript
JS 获取HTML标签内的子节点的方法
2016/09/21 Javascript
js return返回多个值,通过对象的属性访问方法
2017/02/21 Javascript
2种简单的js倒计时方式
2017/10/20 Javascript
webpack多入口文件页面打包配置详解
2018/01/09 Javascript
Vue-不允许嵌套式的渲染方法
2018/09/13 Javascript
详解使用JWT实现单点登录(完全跨域方案)
2019/08/02 Javascript
[02:50]【扭转乾坤,只此一招】DOTA2全新版本永雾林渊开启新篇章
2020/12/24 DOTA
自动化Nginx服务器的反向代理的配置方法
2015/06/28 Python
Python 40行代码实现人脸识别功能
2017/04/02 Python
python微信跳一跳系列之自动计算跳一跳距离
2018/02/26 Python
python线程池threadpool实现篇
2018/04/27 Python
实例详解Python装饰器与闭包
2019/07/29 Python
Python generator生成器和yield表达式详解
2019/08/08 Python
pytorch 加载(.pth)格式的模型实例
2019/08/20 Python
使用python去除图片白色像素的实例
2019/12/12 Python
python中get和post有什么区别
2020/06/19 Python
Django-Scrapy生成后端json接口的方法示例
2020/10/06 Python
苏格兰领先的多渠道鞋店:Begg Shoes
2019/10/22 全球购物
设备动力科岗位职责范本
2014/02/23 职场文书
幼儿教师培训感言
2014/03/08 职场文书
高一新生军训方案
2014/05/12 职场文书
2014年党的群众路线教育实践活动整改措施(个人版)
2014/09/25 职场文书
正风肃纪剖析材料范文
2014/10/10 职场文书
兵马俑导游词
2015/02/02 职场文书
机关单位2016年法制宣传日活动总结
2016/04/01 职场文书
JVM入门之类加载与字节码技术(类加载与类的加载器)
2021/06/15 Java/Android