【OpenCV3】图像的翻转、图像的旋转、仿射变换之图像平移、仿射变换之获取变换矩阵、透视变换
1 图像的放大与缩小
2 图像的翻转
3 图像的旋转
4 仿射变换之图像平移
5 仿射变换之获取变换矩阵
6 透视变换
1 图像的放大与缩小
-
resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
- src: 要缩放的图片
- dsize: 缩放之后的图片大小, 元组和列表表示均可.
- dst: 可选参数, 缩放之后的输出图片
- fx, fy: x轴和y轴的缩放比, 即宽度和高度的缩放比.
- interpolation: 插值算法, 主要有以下几种:
- INTER_NEAREST, 邻近插值, 速度快, 效果差.
- INTER_LINEAR, 双线性插值, 使用原图中的4个点进行插值. 默认.
- INTER_CUBIC, 三次插值, 原图中的16个点.
- INTER_AREA, 区域插值, 效果最好, 计算时间最长.
import cv2 # 导入OpenCV库,用于图像处理
import numpy as np # 导入NumPy库,用于处理数组操作# 读取图片文件,将它们分别加载到变量dog和cat中
dog = cv2.imread('./dog.jpeg') # 加载狗的图像
cat = cv2.imread('./cat.jpeg') # 加载猫的图像# 打印图像的形状,确保正确加载图像,并了解它们的尺寸
print(dog.shape) # 输出:狗的图像尺寸 (360, 499, 3) - 3代表RGB通道
print(cat.shape) # 输出:猫的图像尺寸 (480, 640, 3) - 3代表RGB通道# 将猫的图像调整为与狗的图像相同的大小
new_cat = cv2.resize(cat, (499, 360)) # 将猫的图像大小缩放至 (499, 360)# 使用不同的插值方法将狗的图像缩放到800x800像素
# # 1. 最近邻插值(INTER_NEAREST):这是最简单的插值方法,直接选择最近的像素。通常会导致图像有较大的像素块感。
# new_dog1 = cv2.resize(dog, (800, 800), interpolation=cv2.INTER_NEAREST)# # 2. 双线性插值(INTER_LINEAR):常用的插值方法,考虑周围的像素并计算加权平均值。缩放效果较平滑,适用于图像放大。
# new_dog2 = cv2.resize(dog, (800, 800), interpolation=cv2.INTER_LINEAR)# # 3. 三次插值(INTER_CUBIC):相比于双线性插值更复杂的插值算法,使用16个周围的像素来计算新的像素值,图像放大时更平滑,但速度较慢。
# new_dog3 = cv2.resize(dog, (800, 800), interpolation=cv2.INTER_CUBIC)# # 4. 像素区域关系重采样(INTER_AREA):通常用于缩小图像,通过考虑像素区域的平均值来生成新的像素,适合于图像缩小时使用。
# new_dog4 = cv2.resize(dog, (800, 800), interpolation=cv2.INTER_AREA)# 打印缩放后的猫图像的数据(可以删除此行,除非需要调试)
# print(new_cat) # 这会输出图像的像素矩阵值# 将狗和猫的图像水平拼接在一起并显示
cv2.imshow('new_cat', np.hstack((dog, new_cat))) # np.hstack水平拼接两个图像
cv2.waitKey(0) # 等待用户按任意键后继续(以显示窗口)
cv2.destroyAllWindows() # 关闭所有打开的窗口
2 图像的翻转
- flip(src, flipCode)
- flipCode =0 表示上下翻转
- flipCode >0 表示左右翻转
- flipCode <0 上下 + 左右
# 翻转
import cv2
import numpy as np#导入图片
dog = cv2.imread('./dog.jpeg')new_dog = cv2.flip(dog, flipCode=-1)
cv2.imshow('dog', new_dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
3 图像的旋转
- rotate(img, rotateCode)
- ROTATE_90_CLOCKWISE 90度顺时针
- ROTATE_180 180度
- ROTATE_90_COUNTERCLOCKWISE 90度逆时针
# 旋转
import cv2
import numpy as np#导入图片
dog = cv2.imread('./dog.jpeg')new_dog = cv2.rotate(dog, rotateCode=cv2.cv2.ROTATE_90_COUNTERCLOCKWISE)
cv2.imshow('dog', new_dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
4 仿射变换之图像平移
-
仿射变换是图像旋转, 缩放, 平移的总称.具体的做法是通过一个矩阵和和原图片坐标进行计算, 得到新的坐标, 完成变换. 所以关键就是这个矩阵.
-
warpAffine(src, M, dsize, flags, mode, value)
-
M:变换矩阵
-
dsize: 输出图片大小
-
flag: 与resize中的插值算法一致
-
mode: 边界外推法标志
-
value: 填充边界值
-
平移矩阵
- 矩阵中的每个像素由(x,y)组成,(x, y)表示这个像素的坐标. 假设沿x轴平移 t x t_x tx, 沿y轴平移 t y t_y ty, 那么最后得到的坐标为 ( x ^ , y ^ ) = ( x + t x , y + t y ) (\hat x, \hat y) = (x + t_x, y + t_y) (x^,y^)=(x+tx,y+ty), 用矩阵表示就是:
# 仿射变换之平移
import cv2
import numpy as np#导入图片
dog = cv2.imread('./dog.jpeg')h, w, ch = dog.shape
M = np.float32([[1, 0, 100], [0, 1, 0]])
# 注意opencv中是先宽度, 再高度
new = cv2.warpAffine(dog, M, (w, h))cv2.imshow('new', new)
cv2.waitKey(0)
cv2.destroyAllWindows()
5 仿射变换之获取变换矩阵
仿射变换的难点就是计算变换矩阵, OpenCV提供了计算变换矩阵的API
- getRotationMatrix2D(center, angle, scale)
- center 中心点 , 以图片的哪个点作为旋转时的中心点.
- angle 角度: 旋转的角度, 按照逆时针旋转.
- scale 缩放比例: 想把图片进行什么样的缩放.
# 仿射变换之平移
import cv2
import numpy as np#导入图片
dog = cv2.imread('./dog.jpeg')h, w, ch = dog.shape
# M = np.float32([[1, 0, 100], [0, 1, 0]])# 注意旋转的角度为逆时针.
# M = cv2.getRotationMatrix2D((100, 100), 15, 1.0)
# 以图像中心点旋转
M = cv2.getRotationMatrix2D((w/2, h/2), 15, 1.0)
# 注意opencv中是先宽度, 再高度
new = cv2.warpAffine(dog, M, (w, h))cv2.imshow('new', new)
cv2.waitKey(0)
cv2.destroyAllWindows()
-
getAffineTransform(src[], dst[]) 通过三点可以确定变换后的位置, 相当于解方程, 3个点对应三个方程, 能解出偏移的参数和旋转的角度.
-
src原目标的三个点
-
dst对应变换后的三个点
-
import cv2
import numpy as np# 导入图片
dog = cv2.imread('./dog.jpeg') # 使用cv2.imread读取图片# 获取图片的高度(h),宽度(w),以及通道数(ch)
h, w, ch = dog.shape# 定义原始图片中用于仿射变换的三个顶点坐标
# 这三个点是仿射变换之前的点,指定用于计算仿射变换矩阵
src = np.float32([[20, 10], [30, 10], [20, 30]])# 定义变换后目标图片中对应的三个顶点坐标
# 这些点是原始图片中的三个点在仿射变换后的位置
dst = np.float32([[10, 15], [36, 20], [28, 10]])# 计算仿射变换矩阵
# cv2.getAffineTransform会根据src和dst的点计算出2x3的仿射变换矩阵M
M = cv2.getAffineTransform(src, dst)# 对原图像进行仿射变换
# cv2.warpAffine使用仿射变换矩阵M对图片进行仿射变换,输出图片大小为原图的宽(w)和高(h)
new_dog = cv2.warpAffine(dog, M, (w, h))# 显示仿射变换后的图片
cv2.imshow('new_dog', new_dog)# 等待键盘事件
cv2.waitKey(0) # 等待按键事件,0表示无限等待
cv2.destroyAllWindows() # 关闭所有窗口
6 透视变换
透视变换就是将一种坐标系变换成另一种坐标系. 简单来说可以把一张"斜"的图变"正".
-
warpPerspective(img, M, dsize,…)
-
对于透视变换来说, M是一个3 * 3 的矩阵.
-
getPerspectiveTransform(src, dst) 获取透视变换的变换矩阵, 需要4个点, 即图片的4个角.
import cv2
import numpy as np# 导入图片
img = cv2.imread('./123.png') # 使用cv2.imread读取图片
print(img.shape) # 打印图片的尺寸信息,返回的是(高, 宽, 通道数)# 定义源图像的四个顶点坐标
# 这些坐标是在原图像中的四个点,用于透视变换
src = np.float32([[100, 1100], [2100, 1100], [0, 4000], [2500, 3900]])# 定义目标图像的四个顶点坐标
# 这些坐标是透视变换后图像中对应的四个点
dst = np.float32([[0, 0], [2300, 0], [0, 3000], [2300, 3000]])# 计算透视变换矩阵
# 这个矩阵将源图像的四个点映射到目标图像的四个点
M = cv2.getPerspectiveTransform(src, dst)# 使用计算得到的透视变换矩阵进行图像变换
# cv2.warpPerspective将原图像按照透视矩阵M进行变换,输出尺寸为(2300, 3000)
new = cv2.warpPerspective(img, M, (2300, 3000))# 创建用于显示原图的窗口,并调整窗口大小
cv2.namedWindow('img', cv2.WINDOW_NORMAL) # 创建窗口 'img'
cv2.resizeWindow('img', 640, 480) # 将窗口 'img' 调整为640x480# 创建用于显示透视变换后的图像窗口,并调整窗口大小
cv2.namedWindow('new', cv2.WINDOW_NORMAL) # 创建窗口 'new'
cv2.resizeWindow('new', 640, 480) # 将窗口 'new' 调整为640x480# 显示原图和透视变换后的图像
cv2.imshow('img', img) # 显示原图
cv2.imshow('new', new) # 显示透视变换后的图像# 等待键盘事件
cv2.waitKey(0) # 无限等待按键输入,0表示无限等待
cv2.destroyAllWindows() # 关闭所有窗口
设计logo
- 1.引入图片
- 2.设计一个logo图片
- 3.规划一个自己的logo,看看放哪里合适,在添加的位置变成黑色
- 4.利用add方法,把logo和图片叠加在一起
import cv2
import numpy as npdog = cv2.imread('./dog.jpeg')# 创建logo
logo = np.zeros((200, 200, 3), np.uint8)# 绘制logo
logo[20: 120, 20: 120] = [0, 0, 255]
logo[80: 180, 80: 180] = [0, 255, 0]# 掩码
mask = np.zeros((200, 200), np.uint8)
mask[20: 120, 20: 120] = 255
mask[80: 180, 80: 180] = 255# cv2.imshow('mask', mask)
m = cv2.bitwise_not(mask)
# cv2.imshow('m', m)# 选择dog添加logo的位置
roi = dog[0: 200, 0: 200]# roi与m进行与操作, mask先roi,roi做与运算
tmp = cv2.bitwise_and(roi, roi, mask=m)
# cv2.imshow('tmp', tmp)dst = cv2.add(tmp, logo)
# cv2.imshow('dst', dst)# 在dog上还原
dog[: 200, : 200] = dst# cv2.imshow('logo', logo)
cv2.imshow('dog', dog)cv2.waitKey(0)
cv2.destroyAllWindows()
相关文章:

【OpenCV3】图像的翻转、图像的旋转、仿射变换之图像平移、仿射变换之获取变换矩阵、透视变换
1 图像的放大与缩小 2 图像的翻转 3 图像的旋转 4 仿射变换之图像平移 5 仿射变换之获取变换矩阵 6 透视变换 1 图像的放大与缩小 resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) src: 要缩放的图片dsize: 缩放之后的图片大小, 元组和列表表示均可.dst: 可选参数, 缩…...

不要认为996是开玩笑
996 预防针 随着秋招进程的不断推进,有部分同学已经 OC,有部分同学还在苦苦挣扎,并不断降低自己的预期,包括在和 HR 沟通过程中,主动说出自己愿意接受加班,愿意接受 996,以此来博得企业方面的加…...

精益工程师资格证书:2024年CLMP报名指南
随着全球对精益管理的需求日益增长,精益管理专业人士资格认证(CLMP)正成为越来越多精益工程师和精益管理人员提升职业竞争力的首选。作为一种注重管理而非生产的认证,CLMP不仅适用于制造业的专业人士,也吸引了各行业的…...

【Unity基础】如何选择脚本编译方式Mono和IL2CPP?
Edit -> Project Settings -> Player 在 Unity 中,Scripting Backend 决定了项目的脚本编译方式,即如何将 C# 代码转换为可执行代码。Unity 提供了两种主要的 Scripting Backend 选项:Mono 和 IL2CPP。它们之间的区别影响了项目的性能、…...

写在OceanBase开源三周年
我收获的深刻感触get 感触1:解决问题才有生存价值 [产品力] 感触2:永无止境的“易用性” [易用性] 感触3:立下“双赢”的flag 感触4:社区建设离不开用户和开发者参与 感触5:从易用到用户自助 [自助能力] 当时想法很简…...

【笔记】408刷题笔记
文章目录 三对角三叉树求最小带权路径UDP报文首部和TCP报文首部IP报文首部TCP报文首部UDP报文首部 刷新和再生的区别地址译码 为了区分队空队满,可以使用三种处理方式 1)牺牲一个单元 队头指针在队尾指针的下一位置作为队满的标志 队满条件:(…...

GitHub Star 数量前 13 的自托管项目清单
一个多月前,我们撰写并发布了这篇文章《终极自托管解决方案指南》。在那篇文章里我们深入探讨了云端服务与自托管方案的对比、自托管的潜在挑战、如何选择适合自托管解决方案,并深入介绍了五款涵盖不同场景的优秀自托管产品。 关于自托管的优势…...

js实现生成随机数值的数组
生成随机数值的数组 方法一:使用while循环和Set // min 开始数值, max 结束数值, count 数组内填充几个数值 function generateUniqueRandomNumbers(min, max, count) { let result new Set(); while (result.size < count) { let n…...

视频怎么转换成mp3格式?分享5种便捷的转换方法
在日常生活中,我们经常会遇到需要将视频文件中的音频提取出来,转换成MP3格式的情况,以便在手机、MP3播放器或其他设备上播放。今天,我将为大家介绍5种视频转MP3的方法,非常简单便捷,一起来学习下吧。 方法一…...

Reflection 70B如何革新语言模型的准确性与推理能力
在开源人工智能模型领域,HyperWrite 公司开发的 Reflection 70B 模型以其创新的“反射”机制成为新的重量级竞争者。这一模型旨在解决大型语言模型常见的“幻觉”问题,即生成不准确或虚构的信息。Reflection 70B 通过在提供最终响应之前评估和纠正自己的…...

覆盖索引是什么意思?
文章目录 Q1:覆盖索引是什么意思?覆盖索引的工作原理覆盖索引的优势覆盖索引的示例覆盖索引的使用场景覆盖索引的限制总结 Q2:为什么查询所涉及的所有字段都在索引中存在,那么数据库就无需回表?1. **索引本身存储了字段…...

最大间距问题
LeetCode164 最大间距 基数排序 #include <iostream> #include <vector> using namespace std;class Solution { public:int maximumGap(vector<int>& nums) {int nnums.size();if(n<2) return 0;int exp1;int Maxnums[0];vector<int> buf(n)…...

【Hadoop|MapReduce篇】Hadoop序列化概述
1. 什么是序列化 序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储到磁盘(持久化)和网络传输。 反序列化就是将收到的字节序列(或其他数据传输协议)或者磁盘的持久化数…...

【Elasticsearch系列】Elasticsearch中的分页
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

NLTK:一个强大的自然语言处理处理Python库
我是东哥,一名热爱技术的自媒体创作者。今天,我将为大家介绍一个非常有趣且强大的Python库——NLTK。无论你是刚刚接触Python的小白,还是对自然语言处理(NLP)有些许了解的朋友,NLTK都是一个值得学习的工具。…...

NUUO网络视频录像机 css_parser.php 任意文件读取漏洞复现
0x01 产品简介 NUUO网络视频录像机(Network Video Recorder,简称NVR)是NUUO Inc.生产的一种专业视频监控设备,它广泛应用于零售、交通、教育、政府和银行等多个领域。能够同时管理多个IP摄像头,实现视频录制、存储、回放及远程监控等功能。它采用先进的视频处理技术,提供…...

【支付】Stripe支付通道Java对接(产品 价格 支付 查询 退款 回调)
Stripe是一家美国科技公司,成立于2010年,由爱尔兰兄弟Patrick Collison和John Collison共同创立。该公司致力于提供高效、简洁的互联网支付收款服务,为开发者或商家提供支付API接口或代码,使商家的网站、移动APP支持信用卡付款。S…...

Unity3D 小案例 像素贪吃蛇 01 蛇的移动
Unity3D 小案例 像素贪吃蛇 第一期 蛇的移动 像素贪吃蛇 今天来简单制作一个小案例,经典的像素贪吃蛇。 准备 首先调整一下相机的设置,这里使用灰色的纯色背景,正交视图。 接着,创建一个正方形,保存为预制体&#…...

【STM32 MCU】stm32MCUs 32-bit Arm Cortex-M
stm32MCUs 32-bit Arm Cortex-M...

html+css网页设计 旅游 雪花旅行社5个页面
htmlcss网页设计 旅游 雪花旅行社5个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1&#…...

vue3中的实例
实例类型 Vue2:每个Vue应用都是new Vue创建的一个新实例,创建的时候将data作为property添加到响应式系统中 vue3:createApp创建一个Application Instance、应用实例用来注册全局内容,大多数方法支持链式调用,返回实例…...

9.测试计划(包含笔试/面试题)
一、软件测试计划介绍 1.测试计划就是一份测试文档,一份描述测试工作计划的文档,对测试计划进行统筹安排。 2.测试计划的编写者就是测试组长,测试主管。 3.测试计划的查阅者:测试人员,测试主管,产品&#x…...

这 7 款AI应用将让你全新的iPhone 16成为电影制作的强大工具
苹果公司在周一的Glowtime发布会上揭晓了新款的iPhone 16 Pro系列。除了新加入的苹果智能功能和令人印象深刻的硬件升级外,它还获得了一套视频制作工具,让用户能够在一个几乎可以放进口袋的设备上制作整部电影。 这些升级中有一个48MP融合相机。它具有2…...

自注意力机制(self-attention)
自注意力机制(self-attention) 之前听过吴恩达老师的课,吴恩达老师CNN那一块讲的特别好,但是后面RNN这一部分我听的不是很明白,今天有看了李宏毅老师attention这部分的课,总结一下笔记。 self-attention …...

Nuxt3入门:过渡效果(第5节)
你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。 Nuxt 利用 Vue 的 <Transition> 组件在页面和布局之间应用过渡效果。 一、页面过渡效果 你可以启用页面过渡效果,以便对所有页面应用自动过渡效果。 nuxt.config.js export defaul…...

【开发工具】IntelliJ IDEA插件推荐:Json Helper——让JSON处理更高效
导语:在Java开发过程中,JSON作为一种轻量级的数据交换格式,被广泛应用于前后端数据交互。今天,我要为大家介绍一款IntelliJ IDEA插件——Json Helper,帮助开发者更高效地处理JSON数据。 一、什么是Json Helper&#x…...

Lua垃圾回收机制
Lua垃圾回收机制 在 Lua 中,一共只有8种数据类型,分别为 nil 、boolean 、userdata 、number 、string 、 table 、 function 、 userdata 和 thread 。其中,只有 string table function thread 四种是以引用方式共享,是需要被 G…...

Java学习路线:详细指引
Java学习路线可以分为几个阶段,每个阶段都有其重点和推荐学习的内容。下面我将按照初学者、进阶和高级三个阶段来举例说明: 初学者阶段 目标: 熟悉Java基础语法理解面向对象编程掌握基本数据类型和数据结构学会使用IDE(如Intel…...

商家转账到零钱如何开通-微信支付
商家转账到零钱是微信支付的一项实用功能,允许商户将资金从商户号余额直接转账到用户的微信零钱。我们以上万次成功申请的经验整理了本文的详细的步骤和建议以帮助商户可以快速开通该功能。 1. 准备工作 - 确认申请资格:只有公司性质的商户可以申请此功能…...

自研商家如何快速接入电商平台订单数据?
随着电子商务行业的快速发展,越来越多的商家开始寻求高效的订单管理和数据整合方案。对于那些自研系统的商家来说,如何实现与各大电商平台之间的无缝对接,成为了一项重要挑战。点三电商API正是为此类需求量身打造,为商家提供了一站…...