OpenCV总结之图像几何变换
创始人
2025-05-31 16:36:30
0

1. 图像缩放

对图像进行放大或缩小,使用API:

cv2.resize(src, dsize, fx=0, fy=0, interpolation=cv2.INTER_LINEAR)

参数:

src:输入图像

dsize:绝对尺寸,直接指定调整之后图像的大小

fx, fy:相对尺寸,将dsize设置为None,然后将fx和fy设置为比例因子即可

interpolation:插值方法:

插值含义
cv2.INTER_LINEAR双线性插值法
cv2.INTER_NEAREST最近邻插值
cv2.INTER_AREA像素区域重采用
cv2.INTER_CUBIC双三次插值

示例:

import cv2 as cv#读取图片
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")#图像缩放
#绝对尺寸
rows,cols = img1.shape[:2]
res = cv.resize(img1, (2*cols, 2*rows), interpolation=cv.INTER_CUBIC)#相对尺寸
res1 = cv.resize(img1, None, fx=0.5, fy=0.5)#图像显示
cv.imshow("orignal", img1)
cv.imshow("enlarge", res)
cv.imshow("shrink", res1)
cv.waitKey(0)

运行结果:

2. 图像平移

指定平移矩阵后,调用cv.warpAffine()平移图像

cv.warpAffine(img, M, dsize)

参数:

img: 输入图像

M:2*3移动矩阵

要把(x, y)处的像素点移动到(x+t_{x}, y+t_{y})处,M矩阵应设置为:

M=\begin{Bmatrix} 1 & 0 & t_{x} \\ 0 & 1 & t_{y} \end{Bmatrix}

注意:将M设置为np.float32类型的Numpy数组

dsize:输出图像的大小

注意:输出图像的大小,它应该是(宽度,高度)的形式,请记住,width=列数,height=行数。

示例:

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt#读取图像
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")#图像平移,所有像素点移动(50,100)
rows,cols = img1.shape[:2]
M = np.float32([[1,0,50],[0,1,100]]) #平移矩阵
dst = cv.warpAffine(img1, M, [cols+50, rows+100])#图像展示
fig,axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("translation")
plt.show()

输出结果:

3.图像旋转

在opencv中图像旋转首先根据旋转中心和旋转角度获得旋转矩阵,然后根据旋转矩阵进行变换,也就是调用cv.getRotationMatrix2D()获取旋转矩阵,然后调用cv.warpAffine()进行旋转。

cv2.getRotationMatrix2D(center, angle, scale)

参数:

center:旋转中心

angle:旋转角度

scale:缩放比例

示例:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np#读取图像
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")#获取图像size
rows, cols = img1.shape[:2]
#获取旋转矩阵
M = cv.getRotationMatrix2D((rows/2, cols/2), 30, 1)#计算变换后图像的显示size
cos = np.abs(M[0, 0])
sin = np.abs(M[0, 1])
cols1 = rows * sin + cols * cos
rows1 = rows * cos + cols * sin
cols1 = int(np.round(cols1))
rows1 = int(np.round(rows1))
M[0,2] += (cols1 - cols) * 0.5
M[1,2] += (rows1 - rows) * 0.5
#图像旋转
dst = cv.warpAffine(img1, M, [cols1,rows1])
# print("M: ", M)#图像显示
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("rotation")
plt.show()

输出结果:

4.仿射变换

仿射变换是对图像的缩放、旋转、翻转和平移等操作的组合。如图所示,图1一中的点1、2、3与图二中的三个点一一映射,仍然形成三角形,但是大小和相对距离等已经改变。通过这样两组感兴趣点(至少三个不共线的点)可以求出放射变换矩阵,然后把变换矩阵应用到图像中所有点,就完成了图像的仿射变换。

调用cv.getAffineTransform()将创建变换矩阵,最后该矩阵将传递给cv.warpAffine()进行变换

cv2.getAffineTransform(src, dst)

参数:

src: 原始图像中三个感兴趣点的坐标

dst: 目标图像中对应的三个感兴趣点的坐标

需要注意的是,原始图像中所有平行线经过仿射变换后仍然平行。

示例:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np#读取图像
img1 = cv.imread('E:\\loaddown\\opencv_test\\1.jpg')#获取仿射变换矩阵
rows, cols = img1.shape[:2]
pts1 = np.float32([[50,50], [200,50], [50,200]])
pts2 = np.float32([[100,100], [200,50], [100,250]])
M = cv.getAffineTransform(pts1, pts2)#进行仿射变换
dst = cv.warpAffine(img1, M, (cols, rows))#图像显示
fig,axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("affine")
plt.show()

输出结果:

5. 透射变换

透射变换的本质是将图像投射到一个新的平面,其通用变换公式为:

\left [ \begin{matrix} x' & y' & z' \end{matrix} \right ] = \left [ \begin{matrix} u & v & w \end{matrix} \right ] T = \left [ \begin{matrix} u & v & w \end{matrix} \right ] \left [ \begin{matrix} T_{1} & T_{2} \\ T_{3} & a_{22} \end{matrix} \right ] = \left [ \begin{matrix} u & v & w \end{matrix} \right ]\left [ \begin{matrix} a_{00} & a_{01} & a_{02} \\ a_{10} & a_{11} & a_{12}\\ a_{20} & a_{21} & a_{22} \end{matrix} \right ]

其中,\left ( u,v \right )是原始的图像像素坐标,w取值为1,(x=\frac{x'}{z'}, y=\frac{y'}{z'})是透射变换后的结果,T矩阵是透射变换矩阵,可以分成三部分:T_1表示对图像进行线性变换,T_2对图像进行平移,T_3表示对图像进行投射变换,a_{22}一般设为1。

在opencv中,需要找到四个点(其中任意三个不共线)来计算获取变换矩阵T,再进行透射变换。通过函数cv.getPerspectiveTransform()找到变换矩阵,将cv.warpPerspective()进行投射变换。

示例:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np#读取图像
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")#获取透射变换矩阵
rows,cols = img1.shape[:2]
pts1 = np.float32([[56,65], [168,52], [28,187], [189,190]])
pts2 = np.float32([[100, 145], [200, 100], [80,190], [210,200]])T = cv.getPerspectiveTransform(pts1, pts2)
#透射变换
dst = cv.warpPerspective(img1, T, (cols, rows))
#图像显示
fig,axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("perspective")
plt.show()

输出结果:

 

6.图像金字塔

图像金字塔是图像多尺度表达的一种,最主要用于图像分割,是一种以多分辨率来解决图形的有效且概念简单的结构。图像金字塔用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率递减且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。

金字塔的底部是高分辨率的待处理图像表示,顶部是低分辨率的图像,层级越高,图像越小,分辨率越低。

图像金字塔是图像多尺度表达的一种,使用API:

cv.pyrUp(image)  #向上采样cv.pyrDown(image)  #向下采样

示例:

mport cv2 as cv
import matplotlib.pyplot as plt
import numpy as np#读取图像
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")#进行图像采样
up_img = cv.pyrUp(img1) #上采样操作
down_img = cv.pyrDown(img1) #下采样操作#图像显示
fig,axes = plt.subplots(nrows=1, ncols=3, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(up_img[:,:,::-1])
axes[1].set_title("up_img")
axes[2].imshow(down_img[:,:,::-1])
axes[2].set_title("down_img")
plt.show()

输出结果:

 

相关内容

热门资讯

A股玻尿酸巨头出手!2700字... 医美龙头巨子生物“成分争议”风波持续发酵。日前,美妆博主大嘴博士(香港大学化学博士郝宇)发文,质疑巨...
计算机组成原理实验1---运算...     本实验为哈尔滨工业大学计算机组成原理实验,实验内容均为个人完成,...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
前端-session、jwt 目录:   (1)session (2&#x...
前端学习第三阶段-第4章 jQ... 4-1 jQuery介绍及常用API导读 01-jQuery入门导读 02-JavaScri...
EL表达式JSTL标签库 EL表达式     EL:Expression Language 表达式语言     ...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
【内网安全】 隧道搭建穿透上线... 文章目录内网穿透-Ngrok-入门-上线1、服务端配置:2、客户端连接服务端ÿ...
【Spring Cloud A... 文章目录前言Metadata元数据ClassMetadataSpring中常见的一些元注解Nacos...
React篇-关于React的... 一.简介1.介绍用于构建用户界面的 JavaScript 库2.创建项目(1)手动创建Documen...
win7 Pro 英文版添加中... win7pro x64英文版添加中文语言包1、下载语言包,并解压成lp.cab,复制到...
Android开发-Andro... 01  Android UI 1.1  UI 用户界面(User Interface,...
基于springboot教师人... 基于springboot教师人事档案管理系统【源码+论文】 开发语言:Jav...
编写软件界面的方式 本文重点解决如下问题:编写软件的界面有哪几种方式?通常情形下࿰...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
GO语言小锤硬磕十三、数组与切... 数组用来保存一组相同类型的数据,go语言数组也分一维数组和多维数组。 直接上代码看一下...
三级数据库备考--数据库应用系... 1.数据库应用系统设计包括概念设计、逻辑设计、物理设计3个步骤,每个步骤的设计活动按照...
prometheus数据持久化... https://segmentfault.com/a/1190000015710814 promet...
孩子用什么样的灯对眼睛没有伤害... 现代社会高速发展,越来越多的人开始重视身体健康,尤其是很多家长ÿ...
微软Bing GPT支持AI绘... 我想要一张图片:大象、珊瑚、火山、云朵我想要一张图片:亚特兰蒂斯...