opencv-22 图像几何变换01-缩放-cv2.resize()(图像增强,图像变形,图像拼接)

什么是几何变换?

几何变换是计算机图形学中的一种图像处理技术,用于对图像进行空间上的变换,而不改变图像的内容。这些变换可以通过对图像中的像素位置进行调整来实现。

常见的几何变换包括:

平移(Translation):将图像在水平和/或垂直方向上进行平移,即将图像的每个像素沿着指定的距离进行移动。

缩放(Scaling):通过增大或减小图像的尺寸,使图像变得更大或更小。在缩放过程中,图像中的每个像素的位置会相应地调整。

旋转(Rotation):将图像绕着一个特定的旋转中心进行旋转,使得图像的内容按照指定的角度进行旋转。

翻转(Flip):将图像在水平和/或垂直方向上进行翻转,即将图像的像素按照指定的方向进行镜像反转。

剪切(Shearing):在某个方向上,将图像的一部分像素按照一定的比例进行平移,使得图像在该方向上发生错切效果。

几何变换的应用场景

几何变换在计算机图形学和计算机视觉领域有广泛的应用场景。以下是一些常见的几何变换的应用场景:

图像配准(Image Registration):在医学影像、遥感图像等领域,需要将多幅图像进行对齐,使得它们在空间上对应的位置一致。几何变换可以用于实现图像的平移、旋转和缩放,从而实现图像的配准。

图像增强(Image Enhancement):在图像增强中,几何变换可以用于调整图像的尺寸和位置,使得图像在显示或处理时更合适。比如将图像缩放到指定大小,或者对图像进行裁剪。

视觉效果和动画:在计算机游戏、动画制作等领域,几何变换可以用于实现图像或物体的平移、旋转和缩放,从而创建出各种视觉效果和动画。

图像变形(Image Warping):图像变形是指将图像的某些区域按照一定的规则进行变形,从而实现特定的效果,如人脸变形、风格化效果等。

2D到3D的转换:在计算机辅助设计(CAD)和虚拟现实(VR)中,几何变换可以用于将2D图像转换成3D模型或场景。

视角变换(Viewpoint Transformation):在计算机视觉中,几何变换可以用于将图像从不同视角进行观察,从而对图像进行重建、分析或识别。

图像拼接(Image Stitching):将多幅图像拼接成一幅全景图时,需要进行图像的平移、旋转和缩放等几何变换,以使得不同图像之间能够无缝地对齐。

总的来说,几何变换在图像处理和计算机图形学中起着至关重要的作用,它们能够改变图像的位置和形状,从而实现图像的对齐、增强、变形和合成等多种功能。

以下对几个常用的图像变换操作进行单独分析

缩放

在 OpenCV 中,使用函数 cv2.resize()实现对图像的缩放,该函数的具体形式为:

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

式中:
 dst 代表输出的目标图像,该图像的类型与 src 相同,其大小为 dsize(当该值非零时),
或者可以通过 src.size()、fx、fy 计算得到。
 src 代表需要缩放的原始图像。
 dsize 代表输出图像大小。
 fx 代表水平方向的缩放比例。
 fy 代表垂直方向的缩放比例。
 interpolation 代表插值方式,具体如表 5-1 所示。

在这里插入图片描述
在这里插入图片描述

在 cv2.resize()函数中,目标图像的大小可以通过“参数 dsize”或者“参数 fx 和 fy”二者之一来指定,具体介绍如下。

 情况 1:通过参数 dsize 指定
如果指定参数 dsize 的值,则无论是否指定了参数 fx 和 fy 的值,都由参数 dsize 来决定目
标图像的大小。
此时需要注意的是,dsize 内第 1 个参数对应缩放后图像的宽度(width,即列数 cols,与参数 fx 相关),第 2 个参数对应缩放后图像的高度(height,即行数 rows,与参数 fy 相关)。
指定参数 dsize 的值时,x 方向的缩放大小(参数 fx)为:

(double)dsize.width/src.cols

同时,y 方向的缩放大小(参数 fy)为:

(double)dsize.height/src.rows

情况 2:通过参数 fx 和 fy 指定

如果参数 dsize 的值是 None,那么目标图像的大小通过参数 fx 和 fy 来决定。此时,目标图像的大小为:

dsize=Size(round(fx*src.cols),round(fy*src.rows))

插值是指在对图像进行几何处理时,给无法直接通过映射得到值的像素点赋值。

例如,将图像放大为原来的 2 倍,必然会多出一些无法被直接映射值的像素点,对于这些像素点,插值方式决定了如何确定它们的值。

除此以外,还会存在一些非整数的映射值,例如,反向映射可能会把目标图像中的像素点值映射到原始图像中的非整数值对应的位置上,当然原始图像内是不可能存在这样的非整数位置的,即目标图像上的该像素点不能对应到原始图像的某个具体位置上,此时也要对这些像素点进行插值处理,以完成映射。

函数 cv2.resize()能实现对原始图像的缩放功能,需要注意的是,开始运算前,操作前的目标图像 dst 自身的大小、类型与最终得到的目标图像 dst 是没有任何关系的。
目标图像 dst 的最终大小和类型是通过 src、dsize、fx、fy 指定的。如果想让原始图像调整为和目标图像一样大,
则必须通过上述属性指定。

当缩小图像时,使用区域插值方式(INTER_AREA)能够得到最好的效果;
当放大图像时,使用三次样条插值(INTER_CUBIC)方式和双线性插值(INTER_LINEAR)方式都能够取得较好的效果。
三次样条插值方式速度较慢,双线性插值方式速度相对较快且效果并不逊色。

实验:使用函数 cv2.resize()对一个数组进行简单缩放

import cv2
import numpy as np
img=np.ones([2,4,3],dtype=np.uint8)
#获取图像的尺寸
size=img.shape[:2]
print("size=\n",size)
#缩放图像
rst=cv2.resize(img,size)print("img.shape=\n",img.shape)
print("img=\n",img)
print("rst.shape=\n",rst.shape)
print("rst=\n",rst)

在本例中,我们期望通过函数 cv2.resize()对原始图像进行缩放。为了方便观察,将目标图像设置为与原始图像等大小
运行结果:

size=(2, 4)
img.shape=(2, 4, 3)
img=[[[1 1 1][1 1 1][1 1 1][1 1 1]][[1 1 1][1 1 1][1 1 1][1 1 1]]]
rst.shape=(4, 2, 3)
rst=[[[1 1 1][1 1 1]][[1 1 1][1 1 1]][[1 1 1][1 1 1]][[1 1 1][1 1 1]]]

通过程序我们观察到,我们的目的没有达到,目标图像的大小与原始图像的大小并不一致。
原始图像的大小是 2 行 4 列,目标图像的大小是 4 行 2 列:

 目标图像的行数是原始图像的列数。
 目标图像的列数是原始图像的行数。

通过以上例题我们进一步确认:函数 cv2.resize()内 dsize 参数与图像 shape 属性在行、列的顺序上是不一致的,或者说,
 在 shape 属性中,第 1 个值对应的是行数,第 2 个值对应的是列数。
 在 dsize 参数中,第 1 个值对应的是列数,第 2 个值对应的是行数。
我们通常使用等大小的图像进行测试,在这种情况下,可能无法发现 cv2.resize()函数内 dsize 参数的具体使用方式。
在使用 cv2.resize()函数时,要额外注意参数 dsize 的属性顺序问题

实验2:使用函数 cv2.resize()完成一个简单的图像缩放

import cv2
img=cv2.imread("lena.png")
print(img.shape)
rows,cols=img.shape[:2]
#重置图像大小
size=(int(cols*0.9),int(rows*0.5))
rst=cv2.resize(img,size)
print("img.shape=",img.shape)
print("rst.shape=",rst.shape)cv2.imshow("img",img)
cv2.imshow("rst",rst)cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:

(512, 512, 3)
img.shape= (512, 512, 3)
rst.shape= (256, 460, 3)

在这里插入图片描述
从程序可以看出:
 列数变为原来的 0.9 倍
 行数变为原来的 0.5 倍

实验3:控制函数 cv2.resize()的 fx 参数、fy 参数,完成图像缩放

import cv2
img=cv2.imread("lena.png")
print(img.shape)
rows,cols=img.shape[:2]
#重置图像大小
size=(int(cols*0.9),int(rows*0.5))#rst=cv2.resize(img,size)rst=cv2.resize(img,None,fx=2,fy=0.5)print("img.shape=",img.shape)
print("rst.shape=",rst.shape)cv2.imshow("img",img)
cv2.imshow("rst",rst)cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:

(512, 512, 3)
img.shape= (512, 512, 3)
rst.shape= (256, 1024, 3)

在这里插入图片描述

从程序可以看出:
 fx 进行的是水平方向的缩放,将列数变为原来的 2 倍,得到 512×2=1024。
 fy 进行的是垂直方向的缩放,将行数变为原来的 0.5 倍,得到 512×0.5=256。

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

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

相关文章

STM32MP157驱动开发——按键驱动(tasklet)

文章目录 “tasklet”机制:内核函数定义 tasklet使能/ 禁止 tasklet调度 tasklet删除 tasklet tasklet软中断方式的按键驱动程序(stm32mp157)tasklet使用方法:button_test.cgpio_key_drv.cMakefile修改设备树文件编译测试 “tasklet”机制: …

【Ansible】Ansible自动化运维工具之playbook剧本

playbook 一、playbook 的概述1. playbook 的概念2. playbook 的构成 二、playbook 的应用1. 安装 httpd 并启动2. 定义、引用变量3. 指定远程主机 sudo 切换用户4. when条件判断5. 迭代6. Templates 模块6.1 添加模板文件6.2 修改主机清单文件6.3 编写 playbook 7. tags 模块 …

vue权限按钮的实现

鉴权函数 由于下面几种方式都需要用到鉴权函数,所以将其放置在组件外面,供组件或其他文件调用。 // src/utils/hasPermission.jsimport { usePermissionStore } from /stores import array from lodash/array export const hasPermission (value, def…

EXCEL,如何比较2个表里的数据差异(使用数据透视表)

目录 1 问题: 需要比较如下2个表的内容差异 1.1 原始数据喝问题 1.2 提前总结 2 使用EXCEL公式方法 2.1 新增辅助列: 辅助index 2.2 具体公式 配合条件格式 使用 3 数据透视表方法 3.1 新增辅助列: 辅助index 3.2 需要先打开 数据透视表向导 …

Ubuntu 20.04 Ubuntu18.04安装录屏软件Kazam

1.在Ubuntu Software里面输入Kazam,就可以找不到这个软件,直接点击install就可以了 2.使用方法: 选择Screencast(录屏) Fullscreen(全屏)-----Windows(窗口)--------Ar…

20.3 HTML表格

1. table表格 table标签是HTML中用来创建表格的元素. table标签通常包含以下子标签: - th标签: 表示表格的表头单元格(table header), 用于描述列的标题. - tr标签: 表示表格的行(table row). - td标签: 表示表格的单元格(table data), 通常位于tr标签内, 用于放置单元格中的…

数据结构之动态顺序表(附带完整程序)

🎈基本概念 🌈一.线性表、顺序表的定义 ☀️(1)线性表: 是n个具有相同特性的数据元素的有限序列。线性表在逻辑上是线性结构,但在物理上存储时,通常以数组和链式结构的形式存储。 ☀️&…

c# 此程序集中已使用了资源标识符

严重性 代码 说明 项目 文件 行 禁止显示状态 错误 CS1508 此程序集中已使用了资源标识符“BMap.NET.WindowsForm.BMapControl.resources” BMap.NET.WindowsForm D:\MySource\Decompile\BMap.NET.WindowsForm\CSC 1 活动 运行程序时&a…

Mock-MOCO使用过程

一、jar包下载:https://github.com/dreamhead/moco 二、准备mock的json文件 data.json内容: ####GET请求 [{"description": "response使用Content-Type为charsetGBK编码格式来查看返回信息为中文的内容","request": {&q…

《Elasticsearch 源码解析与优化实战》第5章:选主流程

《Elasticsearch 源码解析与优化实战》第5章:选主流程 - 墨天轮 一、简介 Discovery 模块负责发现集群中的节点,以及选择主节点。ES 支持多种不同 Discovery 类型选择,内置的实现称为Zen Discovery ,其他的包括公有云平台亚马逊的EC2、谷歌…

Ansible单yaml文件部署Zabbix5.0监控平台

文章目录 Ansible单yaml文件部署Zabbix5.0监控平台节点规划案例实施基础环境准备编写剧本文件ZabbixWeb界面(1)改中文(2)添加监控主机 Ansible单yaml文件部署Zabbix5.0监控平台 节点规划 IP主机名节点192.168.200.10ansibleAnsible节点192.168.200.20zabbix-serverZabbix-ser…

深度学习入门(一):神经网络基础

一、深度学习概念 1、定义 通过训练多层网络结构对位置数据进行分类或回归,深度学习解决特征工程问题。 2、深度学习应用 图像处理语言识别自然语言处理 在移动端不太好,计算量太大了,速度可能会慢 eg.医学应用、自动上色 3、例子 使用…

Effective Java 案例分享(八)

39、使用注解而不是通过命名规则分类 如果需要对定义class,property,或者method进行分类管理,推荐的做法是使用注解对其添加类别,而不是通过命名规则分类。这里以JUnit为例: 在JUnit 3中,如果要写测试的方…

linux环境安装mysql数据库

一:查看是否自带mariadb数据库 命令:rpm -qa | grep mariadb 如果自带数据库则卸载掉重新安装 命令:yum remove mariadb-connector-c-3.1.11-2.el8_3.x86_64 二:将压缩文件上传到/user/local/mysql文件夹 或者直接下载 命令&a…

基于ssm+mysql+html道路养护管理系统

基于ssmmysqlhtml道路养护管理系统 一、系统介绍二、功能展示1.道路信息管理2.损害类型信息管理3.损害类型信息管理4.评定等级信息管理5.日常巡查信息管理6.定期检查信息管理 四、获取源码 一、系统介绍 系统主要功能:道路信息管理、损害类型信息管理、评定等级信息…

【网络原理】 (1) (应用层 传输层 UDP协议 TCP协议 TCP协议段格式 TCP内部工作机制 确认应答 超时重传 连接管理)

文章目录 应用层传输层UDP协议TCP协议TCP协议段格式TCP内部工作机制确认应答超时重传 网络原理部分我们主要学习TCP/IP协议栈这里的关键协议(TCP 和 IP),按照四层分别介绍.(物理层,我们不涉及). 应用层 我们需要学会自定义一个应用层协议. 自定义协议的原因? 当前的软件(应用…

【JAVASE】顺序和选择结构

⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:浅谈Java 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 顺序和选择 1. 顺序结构2. 分支结构2.1 …

Ubuntu18.04 下配置Clion

配置Clion 安装gcc、g、make Ubuntu中用到的编译工具是gcc©,g(C),make(连接)。因此只需安装对应的工具包即可。Ubuntu下使用命令安装这些包: (1)安装gcc sudo apt install gcc&am…

解决Cannot resolve plugin org.apache.maven.plugins:xxxxxxxx

解决Cannot resolve plugin org.apache.maven.plugins:xxxxxxxx 方法一、检查配置设置 下图中三个方框圈出来的地方设置为自己的下载的maven地址,配置文件地址,仓库地址。刷新maven。 我个人试过没用,不过网上有的朋友用这个方法解决了。 …

Day 69-70:矩阵分解

代码: package dl;import java.io.*; import java.util.Random;/** Matrix factorization for recommender systems.*/public class MatrixFactorization {/*** Used to generate random numbers.*/Random rand new Random();/*** Number of users.*/int numUsers…