2.4 OpenCV随手简记(五)

一、图像翻转
第一个图像翻转,这个可是制作表情包的利器。
图像翻转在 OpenCV 中调用函数 flip() 实现,原函数如下:
flip(src, flipCode, dst=None)
  • src:原始图像。
  • flipCode:翻转方向,
  • 如果 flipCode 0 ,则以 X 轴为对称轴翻转,
  • 如果 fliipCode > 0 则以 Y 轴为对称轴翻转,
  • 如果 flipCode < 0 则在 X 轴、 Y 轴方向同时翻转。
示例如下:
import cv2 as cv
import matplotlib.pyplot as plt
# 读取图片 由 GBR 转 RGB
img = cv.imread('maliao.jpg')
src = cv.cvtColor(img, cv.COLOR_BGR2RGB)
# 图像翻转
# flipCode 为 0 ,则以 X 轴为对称轴翻转,如果 fliipCode > 0 则以 Y 轴为对称轴翻转,如果
flipCode < 0 则在 X 轴、 Y 轴方向同时翻转。
img1 = cv.flip(src, 0)
img2 = cv.flip(src, 1)
img3 = cv.flip(src, -1)
# plt 显示图形
titles = ['Source', 'Ima1', 'Ima2', 'Ima3']
images = [src, img1, img2, img3]
for i in range(4):
plt.subplot(2, 2, i + 1)
plt.imshow(images[i])
plt.title(titles[i])
plt.xticks([])
plt.yticks([])
plt.show()

二、放射变换
1.图像平移
图像平移是通过仿射函数 warpAffine() 来实现的,原函数如下:
warpAffine(src, M, dsize, dst=None, flags=None, borderMode=None,
borderValue=None)
在图像平移中我们会用到前三个参数:
1. 需要变换的原始图像
2. 移动矩阵 M
3. 变换的图像大小(如果这个大小不和原始图像大小相同,那么函数会自动通过插值来调整像素间的关系)。
图像的平移是沿着 x 方向移动 tx 距离, y 方向移动 ty 距离,那么需要构造移动矩阵 :
M = [ [1,0,tx], [0,1,ty]]
M 2x3 矩阵, M 矩阵必须是 float 类型的。
创建 M 矩阵有如下两种方法:
(1) M = np.zeros(2,3,np.float32)
M[0] = [1,0,tx]
M[1] = [0,1,ty]
(2) M = np.float32([1,0,tx], [0,1,ty])
我们通过 Numpy 来产生 M 矩阵(必须是 float 类型的),并将其赋值给仿射函数 warpAffine() ,下
面来看个示例:
import cv2 as cv
import numpy as np
#读取图片
src = cv.imread('maliao.jpg')
rows, cols = src.shape[:2]
# 定义移动距离
tx = 50
ty = 100
# 生成 M 矩阵
M = np.float32([[1, 0, tx], [0, 1, ty]])
# 平移
dst = cv.warpAffine(src, M, (cols, rows))
# 显示图像
cv.imshow('src', src)
cv.imshow("dst", dst)
# 等待显示
cv.waitKey(0)
cv.destroyAllWindows()

注意: warpAffine 函数的第三个参数是输出图像的大小, 这里设置的大小是原图片的大小,所
以结果会有部分遮挡。
2.平移的动态演示
import cv2 as cv
import numpy as np
import time
#读取图片
src = cv.imread('beauty5.jpeg')
rows, cols = src.shape[:2]
# 定义移动距离
tx = 50
ty = 100
i = 0
while cv.waitKey(1) == -1: #等待1毫秒后,用户按下任意键
# 生成 M 矩阵
M = np.float32([[1, 0, tx+i], [0, 1, ty]])
# 平移
dst = cv.warpAffine(src, M, (cols, rows))
# 显示图像
cv.imshow("dst", dst)
time.sleep(1/190)
i = i+1
cv.destroyWindow("dst")# 斜下方移动,移出后又返回
import cv2 as cv
import numpy as np
import time
#读取图片
src = cv.imread('beauty5.jpeg')
rows, cols = src.shape[:2]
# 定义移动距离
tx = 0
ty = 0
i = 0
while cv.waitKey(1) == -1: #等待1毫秒后,用户按下任意键
# 生成 M 矩阵
if tx+i>src.shape[1]: # 移出后又返回
i = 0
Tx = tx+i
Ty = ty+i
M = np.float32([[1, 0, Tx], [0, 1, Ty]])
# 平移
dst = cv.warpAffine(src, M, (cols, rows))
# 显示图像
cv.imshow("dst", dst)
time.sleep(1/190)
i = i+1
cv.destroyWindow("dst")

3.图像旋转

图像旋转主要调用 getRotationMatrix2D() 函数和 warpAffine() 函数实现,绕图像的某一个中心
点旋转,具体如下:
M = cv2.getRotationMatrix2D((cols/2, rows/2), 30, 1)
参数分别为:旋转中心、旋转度数、 scale
rotated = cv2.warpAffine(src, M, (cols, rows))
参数分别为:原始图像、旋转参数、原始图像宽高
图像旋转:设( x0 , y0 )是旋转后的坐标,( x , y )是旋转前的坐标, ( m , n ) 是旋转中心, a 是旋转 的角度( 顺时针 ) ( left , top ) 是旋转后图像的左上角坐标,则公式如下 :
import cv2 as cv
#读取图片src = cv.imread('maliao.jpg')
# 原图的高、宽
rows, cols = src.shape[:2]
# 绕图像的中心旋转
# 参数:旋转中心 旋转度数 scale
M = cv.getRotationMatrix2D((cols/2, rows/2), 90, 1)
#
dst = cv.warpAffine(src, M, (cols, rows))
# 显示图像
cv.imshow("src", src)
cv.imshow("dst", dst)
# 等待显示
cv.waitKey()
cv.destroyAllWindows()

4.图片动态旋转效果
# 固定大小旋转
import cv2 as cv
import time
#读取图片
src = cv.imread('beauty5.jpeg')
# 原图的高、宽
5.4 图像倾斜
rows, cols = src.shape[:2]
i = 1
while cv.waitKey(1) == -1: #等待1毫秒后,用户按下任意键
# 生成 M 矩阵
M = cv.getRotationMatrix2D((cols/2, rows/2), 0+i*30, 0.5) # 0-i*30 反转
# 绕图像的中心旋转
# 参数:旋转中心 旋转度数 scale
dst = cv.warpAffine(src, M, (cols, rows))
i = i+1
# 显示图像
cv.imshow("dst", dst)
time.sleep(1/10) # 时间越短,现象越有趣
cv.destroyWindow("dst")
# 由小到大旋转
import cv2 as cv
import time
#读取图片
src = cv.imread('beauty5.jpeg')
# 原图的高、宽
rows, cols = src.shape[:2]
i = 1
while cv.waitKey(1) == -1: #等待1毫秒后,用户按下任意键
# 生成 M 矩阵
M = cv.getRotationMatrix2D((cols/2, rows/2), 0+i*20, 0.01*i)
# 绕图像的中心旋转
# 参数:旋转中心 旋转度数 scale
dst = cv.warpAffine(src, M, (cols, rows))
i = i+1
if i == 100:
i = 1
time.sleep(3)
# 显示图像
cv.imshow("dst", dst)
time.sleep(1/30)
cv.destroyWindow("dst")
5.图像倾斜
import cv2
import numpy as np
img = cv2.imread("demo.png") # 读取图像
rows = len(img) # 图像像素行数
cols = len(img[0]) # 图像像素列数
p1 = np.zeros((3, 2), np.float32) # 32位浮点型空列表,原图三个点
p1[0] = [0, 0] # 左上角点坐标
p1[1] = [cols - 1, 0] # 右上角点坐标
p1[2] = [0, rows - 1] # 左下角点坐标
p2 = np.zeros((3, 2), np.float32) # 32位浮点型空列表,倾斜图三个点
p2[0] = [50, 0] # 左上角点坐标,向右挪50像素
p2[1] = [cols - 1, 0] # 右上角点坐标,位置不变
p2[2] = [0, rows - 1] # 左下角点坐标,位置不变
M = cv2.getAffineTransform(p1, p2) # 根据三个点的变化轨迹计算出M矩阵
dst = cv2.warpAffine(img, M, (cols, rows)) # 按照M进行仿射
cv2.imshow('img', img) # 显示原图
cv2.imshow('dst', dst) # 显示仿射变换效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体

6.透视变换

摄像机斜视拍摄一物体后,形成的图像会发生变形,如果将图像映射到拍摄物体平面上,相当于将相机垂直于拍摄平面,这样就会得到图像的真实形状,由于这种映射相当于将原图重新 透视 到另一个平面,这种称之为“ 重投影
  上述仿射变换可以将矩形映射成任意平行四边形, 各边仍保持平行 ;而透视变换可以将矩形映射为 任意四边形 直线仍保持直线 由于不再是平行四边形,需提供四个顶点。
透视变换通过函数 cv2.warpPerspective() 实现,语法为 :
warpPerspective(src, M, dsize, dst=None, flags=None, borderMode=None,
borderValue=None)
'''
dst:透视后的输出图像,dsize决定输出图像大小
src:输入图像
M:3*3变换矩阵
flags:插值方法,默认为INTER_LINEAR
borderMode:边类型,默认为BORDER_CONSTANT
borderValue:边界值,默认为0
'''
透视变换通过函数 cv2.getPerspectiveTransform() 来生成转换矩阵,需输入输入图像和输出图像的
四个顶点的坐标。
cv2.getPerspectiveTransform(p1,p2)
# p1,p2分别为原图像4点坐标和新图像4点坐标
手动获取图像顶点的直接透视变换
1 、获取图像四个顶点(通过 photoshop 等软件手动获取,或用 python-opencv 程序手动获取)
2 、形成变换矩阵
3 、透视变换
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('C:/Users/df/Desktop/pp.png')
H_rows, W_cols= img.shape[:2]
print(H_rows, W_cols)
# 原图中书本的四个角点(左上、右上、左下、右下),获取方法见《鼠标点击图片显示点击点及坐标》
pts1 = np.float32([[124,62], [457,100], [53,576], [559,539]])
#变换后矩阵位置
pts2 = np.float32([[0, 0],[W_cols,0],[0, H_rows],[H_rows,W_cols],])
# 生成透视变换矩阵;进行透视变换
M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(img, M, (668, 634))
cv2.imshow("original_img",img)
cv2.imshow("result",dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
img = cv2.imread("pp.png")
print("the shape of the imag is: ",img.shape)
def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
print (xy)
cv2.circle(img, (x, y), 1, (255, 0, 0), thickness = -1)
cv2.putText(img, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (0,0,0), thickness = 1)
cv2.imshow("image", img)
cv2.namedWindow("image")
cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)
cv2.imshow("image", img)
while(True):
try:
cv2.waitKey(100)
if cv2.getWindowProperty('img',cv2.WND_PROP_VISIBLE) <= 0:
break # 防止直接关闭窗口后的“阻塞”
except Exception:
cv2.destroyWindow("image")
break
cv2.waitKey(0)
#cv2.destroyAllWindow()
  通过创建一个鼠标回调函数,当鼠标事件发生时执行该函数。鼠标事件可以是任何与鼠标相关的事 件,如左键向下、左键向上、左键双击等。 它为我们提供了每个鼠标事件的坐标( x y )。

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

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

相关文章

[Redis]List类型

列表类型来存储多个有序的字符串&#xff0c;a、b、c、d、e 五个元素从左到右组成了一个有序的列表&#xff0c;列表中的每个字符串称为元素&#xff0c;一个列表最多可以存储个元素。在 Redis 中&#xff0c;可以对列表两端插入&#xff08;push&#xff09;和弹出&#xff08…

【动手学深度学习】多层感知机之权重衰减研究详情

目录 &#x1f30a;1. 研究目的 &#x1f30a;2. 研究准备 &#x1f30a;3. 研究内容 &#x1f30d;3.1 多层感知机权重衰减 &#x1f30d;3.2 基础练习 &#x1f30a;4. 研究体会 &#x1f30a;1. 研究目的 防止过拟合&#xff1a;权重衰减和暂退法都是用来控制模型的复…

北大、腾讯强推!DynamiCrafter WebUI 在线教程,无需逐帧记录即可图片变视频

从史前时期开始&#xff0c;人类的祖先就曾以石为笔&#xff0c;在洞穴的石壁描绘出一系列野牛奔跑的分析图&#xff0c;壁画上的动物被叠加了多条腿&#xff0c;用来表现连贯的动作&#xff0c;这或许便是动态视频的最早雏形。 被焚之城的山羊陶碗 时光流转&#xff0c;最初&…

sqli-labs 靶场闯关基础准备、学习步骤、SQL注入类型,常用基本函数、获取数据库元数据

Sqli-labs的主要作用是帮助用户学习如何识别和利用不同类型的SQL注入漏洞&#xff0c;并了解如何修复和防范这些漏洞。 它提供了多个不同的漏洞场景&#xff0c;每个场景都代表了一个特定类型的SQL注入漏洞。 用户可以通过攻击这些场景来学习和实践漏洞利用技术&#xff0c;以及…

【数据结构】二叉树-堆

目录 一.树概念及性质 二.二叉树的概念与实现 三.堆的概念和结构 四.堆的实现 1.向下调整算法 2. 堆的创建 3.向上调整算法 4.堆的删除 五.堆排序 六.堆-源码 一.树概念及性质 树是一种非线性的数据结构&#xff0c;它是由数个节点组成的具有层次关系的集合。之所以叫…

干货 | SDR RFSoC技术框图大放送(附资源)

软件无线电(SDR) 本文参考《Software Defined Radio with Zynq UltraScale RFSoc》&#xff0c;全文共744页。需要的可以给公众号 迪普微科技 发送“SDR”。

【力扣】矩阵中的最长递增路径

一、题目描述 二、解题思路 1、先求出以矩阵中的每个单元格为起点的最长递增路径 题目中说&#xff0c;对于每个单元格&#xff0c;你可以往上&#xff0c;下&#xff0c;左&#xff0c;右四个方向移动。那么以一个单元格为起点的最长递增路径就是&#xff1a;从该单元格往上…

SpringBoot项目启动后访问网页显示“Please sign in“

SpringBoot启动类代码如下 SpringBoot项目启动后访问网页显示"Please sign in"&#xff0c;如图 这是一个安全拦截页面&#xff0c;即SpringSecurity认证授权页面&#xff0c;因为SecurityAutoConfiguration是Spring Boot提供的安全自动配置类&#xff0c;也就是说它…

城规跨考地信:你需要知道的几件事

24考研结束&#xff0c;25地信考研的小伙伴也开始准备。 在这期间发现一个现象&#xff0c;城规跨考GIS的讨论度非常高。 对这一点&#xff0c;我并不感到意外&#xff0c;因为随着地产行业的节节败退&#xff0c;很多单位不需要那么多规划人和建筑人&#xff0c;乃至土木人。…

SpringCloud 微服务中网关如何记录请求响应日志?

在基于SpringCloud开发的微服务中&#xff0c;我们一般会选择在网关层记录请求和响应日志&#xff0c;并将其收集到ELK中用作查询和分析。 今天我们就来看看如何实现此功能。 日志实体类 首先我们在网关中定义一个日志实体&#xff0c;用于组装日志对象 Data public class …

使用Java apache commons包五分钟搞定NCR解析(内附源码)

在网上看到很多关于解析NCR(Numeric Character Reference)字符串的java实现&#xff0c;核心都是通过自定义正则表达式来解析&#xff0c;其实org.apache.commons 已经为我们提供了jar包 解决该问题&#xff0c;非常的方便&#xff01;在这里我就来简单分享一下具体实现方法&am…

这就是英伟达 CEO 黄仁勋所说的人工智能“下一波浪潮”|TodayAI

在台湾一年一度的科技展 COMPUTEX 开幕前的周日&#xff0c;英伟达&#xff08;Nvidia&#xff09;首席执行官黄仁勋&#xff08;Jensen Huang&#xff09;表示&#xff0c;机器人和“理解物理定律的 AI”将成为下一波技术浪潮。他指出&#xff0c;英伟达目前正在推动生成式人工…

MyBatis核心对象

MyBatis核心类对象主要有俩个&#xff1a; 1&#xff1a;对相关配置文件信息进行封装的Configuration对象 2&#xff1a;用来执行数据库操作的Executor对象。 核心对象----存储类对象Configuration Configuration对象主要有三个作用&#xff1a; 1&#xff1a;封装MyBatis…

Pulsar 社区周报 | No.2024-05-30 | BIGO 百页小册《Apache Pulsar 调优指南》

“ 各位热爱 Pulsar 的小伙伴们&#xff0c;Pulsar 社区周报更新啦&#xff01;这里将记录 Pulsar 社区每周的重要更新&#xff0c;每周发布。 ” BIGO 百页小册《Apache Pulsar 调优指南》 Hi&#xff0c;Apache Pulsar 社区的小伙伴们&#xff0c;社区 2024 上半年度的有奖问…

AIGC和ChatGPT有什么区别?

AIGC和ChatGPT有什么区别? 首先先解释一下它们各自的概念 什么是AIGC AIGC&#xff0c;全称为Artificial Intelligence Generated Content&#xff0c;中文译为人工智能生成内容。这是一种利用人工智能技术自动生成内容的生产方式。例如&#xff0c;它可以创作出各种形式的内…

基于PHP+MySQL组合开发的同城便民小程序源码系统 房产出租+求职招聘+相亲交友 带完整的安装代码包以及搭建教程

系统概述 在当今信息化高速发展的时代&#xff0c;同城便民小程序已成为城市居民日常生活中不可或缺的一部分。为了满足广大用户的需求&#xff0c;小编给大家分享一款基于PHPMySQL组合开发的同城便民小程序源码系统。该系统集房产出租、求职招聘、相亲交友等多功能于一体&…

微信小程序使用echarts

思路 五个tab公用一个柱状图组件切换tab以及切换时间改变数据&#xff0c;传入子组件&#xff0c;子组件监听数据重新更新点击柱状图显示具体数值每个时间点有两个柱子&#xff08;高压和低压&#xff09;&#xff0c;柱状图显示高压的最大值到最小值的范围除了血压其余只有一…

Python采集数据处理:利用Pandas进行组排序和筛选

概述 在现代数据处理和分析中&#xff0c;网络爬虫技术变得越来越重要。通过网络爬虫&#xff0c;我们可以自动化地从网页上收集大量的数据。然而&#xff0c;如何高效地处理和筛选这些数据是一个关键问题。本文将介绍如何使用Python的Pandas库对采集到的数据进行组排序和筛选…

基于SpringBoot+Vue研究生志愿填报辅助系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝1W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还…

mp公共字段自动注入

目录 一 什么是公共字段自动注入 二 使用mp实现公共字段自动注入 1.实现步骤 ①导入mp相关依赖 ② 在实体类上给相关字段加上 TableField()注解 ③自定义元数据对象处理器 2.实现原理 一 什么是公共字段自动注入 我们平时在执行更新或者是插入数据功能的时候&#xff0c;…