python实现图像的几何变换——冈萨雷斯数字图像处理

1、 实现图像的平移。

原理:
图像的平移是一种基本的图像处理操作,它将图像中的每个像素沿着指定的方向和距离移动,以创建一个新的平移后的图像。平移的原理很简单,通常涉及到以下几个步骤:

  1. 确定平移的距离和方向:首先,确定您希望将图像沿着哪个方向移动以及移动多远。这可以通过定义一个平移向量来实现,该向量包含了水平和垂直方向上的移动距离。

  2. 创建一个新的图像:为了执行平移操作,您需要创建一个与原始图像相同大小的新图像,通常称为目标图像。这个目标图像将用于存储平移后的图像。

  3. 遍历原始图像的像素:对于原始图像中的每个像素,将其从原始图像中取出。

  4. 计算新的像素位置:对于每个取出的像素,根据平移向量的值计算其在目标图像中的新位置。通常,新位置的计算方法如下:
    新X坐标 = 原X坐标 + 水平平移距离
    新Y坐标 = 原Y坐标 + 垂直平移距离

  5. 将像素放置到目标图像中:将每个像素放置到目标图像的新位置上。如果新位置超出了目标图像的边界,可以选择丢弃该像素或采用某种插值方法来填充。

重复步骤3至步骤5:重复以上步骤,直到遍历了原始图像的所有像素。
完成平移操作:完成后,目标图像就包含了原始图像沿指定方向平移后的图像。

在这里,我们采用OpenCV的warpAffine函数来解决图像平移,cv2.warpAffine 是 OpenCV(Open Source Computer Vision Library)中的一个函数,用于执行仿射变换(Affine Transformation)操作。仿射变换是一种线性变换,它可以用来实现图像的平移、旋转、缩放、剪切等操作。该函数的主要作用是将输入图像应用一个仿射变换矩阵,从而生成一个经过变换的输出图像。通常,可以使用这个函数来实现图像的平移、旋转、缩放和剪切等操作,而不需要手动编写复杂的像素级操作。

以下是 cv2.warpAffine 函数的一般用法:

cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])

src:输入图像。
M:仿射变换矩阵,用于指定要执行的变换操作。
dsize:输出图像的大小。
dst(可选):输出图像。如果未提供,则函数会创建一个新的图像。
flags(可选):插值方法的标志,用于确定如何处理像素之间的插值。
borderMode(可选):图像边界像素的处理方式,通常用于变换后的图像可能超出原始图像边界的情况。
borderValue(可选):用于边界填充的像素值。

编写代码,输出如下图所示的结果:

在这里插入图片描述
如果(x,y)方向的平移量分别为(t_x, t_y),则变换矩阵
在这里插入图片描述

可以用类型为np.float32的numpy数组来表示它,并将其作为参数传给cv2.warpAffine函数完成几何变换。上图中
在这里插入图片描述

代码实现

import  cv2
import  numpy as np
import  matplotlib.pyplot as plt
img=cv2.imread("lena_gray_512.tif")

rows,cols,channel=img.shape


affineShrink = np.array([[1,0,100],[0,1,50]],np.float32)
shrinkTwoTimes = cv2.warpAffine(img, affineShrink, (cols, rows), borderValue=10)
plt.subplot(121),plt.imshow(img,'gray'),plt.title("original")
plt.subplot(122),plt.imshow(shrinkTwoTimes,'gray'),plt.title("translation")
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()

结果展示

在这里插入图片描述

2、实现图像的旋转

原理

图像旋转是数字图像处理中的一项基本操作,它的原理可以分为几个关键步骤:

**定义旋转中心:**通常旋转是围绕图像的某一点进行的。这个点可以是图像的中心,也可以是任意一点。

旋转变换:在二维空间中,旋转可以通过旋转矩阵来实现。对于一个给定的旋转角度θ,旋转矩阵是这样的:
在这里插入图片描述
这个矩阵可以用来计算图像中每个像素旋转后的新位置。

像素映射:在旋转图像时,原始图像中的像素需要映射到新的位置。这通常涉及插值算法,如最近邻插值、双线性插值或三次样条插值,以确定新位置的像素值。

处理边界问题:旋转后,图像可能会超出原始图像的边界。这可能需要对图像进行裁剪或填充。

反走样:由于旋转可能导致像素不再对齐,因此可能需要进行反走样处理以减少锯齿效应。

但是在OpenCV 允许在任意地方进行旋转,这里旋转矩阵的形式应该修改为

在这里插入图片描述
其中:

在这里插入图片描述
为了构建这个旋转矩阵,OpenCV 提供了一个函数:cv2.getRotationMatrix2D

编写代码,输出如下图所示的结果:

在这里插入图片描述

提示:

可以先用函数cv2.getRotationMatrix2D得到变换矩阵,该函数的参数包括:旋转中心坐标、旋转角度等,所以利用该函数可以实现围绕任意中心的旋转;旋转角度为正表示逆时针旋转。之后将得到的变换矩阵作为参数传给cv2.warpAffine函数完成几何变换。上图中旋转中心为图像中心,旋转角度为45°。

import cv2
import numpy as np
import matplotlib.pyplot as plt
img=cv2.imread('lena_gray_512.tif',0)
rows,cols=img.shape
# 这里的第一个参数为旋转中心,第二个为旋转角度,第三个为旋转后的缩放因子
# 可以通过设置旋转中心,缩放因子,以及窗口大小来防止旋转后超出边界的问题
M=cv2.getRotationMatrix2D((cols/2,rows/2),45,1)
# 第三个参数是输出图像的尺寸中心
dst=cv2.warpAffine(img,M,(cols,rows))

plt.subplot(121),plt.imshow(img,'gray'),plt.title("original")
plt.subplot(122),plt.imshow(dst,'gray'),plt.title("rotation")
plt.show()
cv2.destroyAllWindows()

结果展示

在这里插入图片描述

3、 实现图像的缩放

原理

图像缩放是数字图像处理中的一项重要技术,它涉及改变图像的尺寸,包括放大和缩小。主要流程如下

**定义缩放比例:**首先确定缩放的比例。这个比例可以是均匀的(横向和纵向相同)或不均匀的(横向和纵向不同)。
**计算新像素位置:**根据缩放比例,为原始图像中的每个像素计算在缩放后图像中的新位置。如果是放大图像,新图像中的许多像素位置将没有直接对应的原始像素;如果是缩小图像,一些原始像素将不会在新图像中有对应位置。
**像素插值:**由于缩放过程中新像素位置可能并不对应原始图像中的确切像素,因此需要通过插值算法来确定这些新位置的像素值。常见的插值方法包括:
**最近邻插值:**将新像素的值设置为最接近的原始像素值。这种方法简单快速,但可能导致图像走样。
双线性插值:考虑最接近的四个像素,通过线性插值计算新像素值。这种方法在图像质量和计算复杂度之间提供了一个较好的平衡。
**双三次插值:**考虑最接近的16个像素,使用三次插值算法计算新像素值。这种方法可以提供更高质量的结果,但计算更为复杂。
**处理边界问题:**在缩放过程中,新图像的尺寸可能与原始图像不完全相符,特别是在不均匀缩放的情况下。这可能需要对图像进行裁剪或填充。
**质量控制:**图像缩放可能会引入各种失真,如锯齿效应或模糊。因此,可能需要采用附加的图像处理技术来优化结果,如锐化处理或反走样技术。

实现下图显示的结果

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

提示

用函数cv2.resize对图像进行8倍放大,参数分别为cv2.INTER_NEAREST、cv2.INTER_LINEAR和cv2.INTER_CUBIC时代表选择最近邻插值法、双线性插值法、三次样条插值法。

import  cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img=cv.imread("jellybeans.png")
img= cv.cvtColor(img,cv.COLOR_RGB2GRAY)
print(img.shape)
x, y = img.shape[0:2]
near = cv.resize(img,(0,0),  fx=8, fy=8,interpolation=cv.INTER_NEAREST)
linear= cv.resize(img, (0,0), fx=8, fy=8,interpolation=cv.INTER_LINEAR)
cubic=cv.resize(img, (0,0), fx=8, fy=8,interpolation=cv.INTER_CUBIC)



plt.subplot(221),plt.imshow(img,'gray'),plt.title("original")
plt.subplot(222),plt.imshow(near,'gray'),plt.title("nearest")
plt.subplot(223),plt.imshow(linear,'gray'),plt.title("linear")
plt.subplot(224),plt.imshow(cubic,'gray'),plt.title("cubic")
plt.show()

结果展示

在这里插入图片描述

import cv2
import numpy as np
import matplotlib.pyplot as plt


img=cv2.imread("binarysmall.png")
img=cv2.cvtColor(img,cv2.COLOR_RGV2GRAY)
print(img.shape)
x,y=img.shape[0:2]
near=cv2.resize(img,(0,0),fx=8,fy=8,interpolation=cv2.INTER_NEAREST)
linear=cv2.resize(img,(0,0),fx=8,fy=8,interpolation=cv2.INTER_LINEAR)
cubic=cv2.resize(img,(0,0),fx=8,fy=8,interpolation=cv2.INTER_CUBIC)

plt.subplot(221),plt.imshow(img,"gray"),plt.title("original")
plt.subplot(222),plt.imshow(near,"gray"),plt.title("nearst")
plt.subplot(223),plt.imshow(linear,"gray"),plt.title("linear")
plt.subplot(224),plt.imshow(cubic,"gray"),plt.title("cubic")
plt.show()

结果展示

在这里插入图片描述

结果分析
INTER_NEAREST - 最近邻插值
根据名字也知道,这是插入的数值采用与原图像最近的那个点的数值,这种方法比较简单,但是人为痕迹有点重。
插值后的边缘效果:由于是以最近的点作为新的插入点,因此边缘不会出现缓慢的渐慢过度区域,这也导致放大的图像容易出现锯齿的现象
INTER_LINEAR - 线性插值
在这里插入图片描述

比如插值点为(x,y),这个像素是由围着他的4个点的像素决定的,
先求得:
f(x,0)=f(0,0)+x[f(1,0)-f(0,0)]
f(x,1)=f(0,1)+x[f(1,1)-f(0,1)]
在对求得值做一次线性插值:
f(x,y)=f(x,0)+y[f(x,1)-f(x,0)]
即可。这个准确的说是双线性
插值后的边缘效果:可以有效避免出现锯齿的现象

INTER_CUBIC –三次样条插值
基本的原理跟线性插值类似,都是做完一个方向再做另一个,不过他是用4*4的像素来计算的,但是在求权的时候不是线性的,而是逼近sin(x)/x:
在这里插入图片描述

插值后的边缘效果:可以有效避免出现锯齿的现象
总的来说,最近邻插值会出现锯齿现象,导致图片变形,感觉不太好。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024苹果手机iOS管理软软件iMazing2.17永久免费版下载教程

iMazing2024是一款专业的苹果IOS设备管理器,强悍的性能远超苹果的iTunes,iMazing 能让广大果粉能已自己的方式管理苹果设备,无需iTunes即可畅快传输或者保存苹果设备中的音乐、消息、文件以及其他数据。 iMazing2Mac-最新绿色安装包下载如下&…

下一站,上岸@24考研er

时间过的好快, 考研倒计时①天 去年这个时候, 我应该也是充满未知地进入即将来到的考研初试 去年,这个时候,疫情😷刚刚放开 许多人都🐑,发烧,可幸的是我受影响不大 &#x1f3…

供应链 | 顶刊MSOM论文精选——关税对全球供应链网络配置的影响:模型、预测和未来研究

编者按 关税对企业全球供应链网络设计决策的影响 本文为 M&SOM期刊20周年特邀论文,原文信息: Lingxiu Dong, Panos Kouvelis (2020) Impact of Tariffs on Global Supply Chain Network Configuration: Models, Predictions, and Future Research…

MySQL 数据库系列课程 05:MySQL命令行工具的配置

一、Windows启动命令行工具 (1)打开 Windows 的开始菜单,找到安装好的 MySQL,点击MySQL 8.0 Command Line Client - Unicode,这个带有 Unicode 的,是支持中文的,允许在命令行中敲中文。 &…

Java经典面试题——手写快速排序和归并排序

题目链接:https://www.luogu.com.cn/problem/P1177 输入模板: 5 4 2 4 5 1快速排序 技巧:交换数组中的两个位置 a[l] a[l] a[r] - (a[r] a[l]); 稳定不稳定?:不稳定 注意找哨兵那里内循环的等于号不能漏,不然…

【STM32】I2C通信

基本的任务是:通过通信线,实现单片机读写外挂模块寄存器的功能。其中至少要实现在指定位置写寄存器和在指定的位置读寄存器这两个功能。 异步时序的优点:省一根时钟线,节约资源;缺点:对事件要求严格&#…

VSCode运行时弹出powershell

问题 安装好了vscode并且装上code runner插件后,运行代码时总是弹出powershell,而不是在vscode底部终端 显示运行结果。 解决方法 打开系统cmd ,在窗口顶部条右击打开属性,把最下面的旧版控制台选项取消,即可

关于JVM的垃圾回收GC的一些记录

目录 一、JVM内存区域划分 二、从一个基本问题开始引入垃圾回收 三、GC作用的区域 三、如何确定一个对象是否可以被当成垃圾进行回收 (1)引用计数法 (2)可达性分析算法 (3)引用的类型 (3…

Netty Review - Netty自动重连机制揭秘:原理与最佳实践

文章目录 概述Pre客户端自动重连CodeServerClient (重点) 测试启动自动重连运行过程中断链后的自动重连 概述 Pre Netty Review - 深入探讨Netty的心跳检测机制:原理、实战、IdleStateHandler源码分析 客户端自动重连 自动重连是一个用于提高网络应用稳定性和可靠…

OpenSource - SCM服务管理平台

文章目录 官方网址文档下载版本功能解决了哪些问题使用对象优势Linxu版本scm-dev deb服务列表 Windows版本scm-dev 服务列表scm-all 服务列表scm-jdk 服务列表scm-springboot 精简版本服务列表scm-springboot 服务列表scm-tomcat 服务列表 SCM 截图 官方网址 https://scm.chus…

如何更好的去理解源码

前言 这篇文章我准备来聊一聊如何去阅读开源项目的源码。 在聊如何去阅读源码之前,先来简单说一下为什么要去阅读源码,大致可分为以下几点原因: 最直接的原因,就是面试需要,面试喜欢问源码,读完源码才可以…

代码随想录-刷题第三十六天

435. 无重叠区间 题目链接:435. 无重叠区间 思路:本题与452. 用最少数量的箭引爆气球非常像,弓箭的数量就相当于是非交叉区间的数量,只要把弓箭那道题目代码里射爆气球的判断条件加个等号(认为[0,1][1&am…

Kafka集群架构服务端核心概念

目录 Kafka集群选举 controller选举机制 Leader partition选举 leader partition自平衡 partition故障恢复机制 follower故障 leader故障 HW一致性保障 HW同步过程 Epoch Kafka集群选举 1. 在多个broker中, 需要选举出一个broker, 担任controller. 由controller来管理…

深入理解 Git 分支管理:提升团队协作与开发效率

目录 前言1 什么是分支2 分支的好处2.1 并行开发的支持2.2 独立性与隔离性2.3 灵活的版本控制2.4 提高安全性和代码质量2.5 项目历史的清晰记录 3 Git 分支操作命令3.1 git branch -v3.2 git branch 分支名称3.3 git checkout 分支名称3.4 git merge 分支名称3.5 git rebase 分…

RabbitMQ的概念与使用

什么是MQ? MQ 是消息队列(Message Queue)的简称。消息队列是一种应用程序间通信的方式,用于在不同的应用程序之间传递消息。它通过解耦发送者和接收者之间的直接依赖关系,提供了一种异步、可靠的消息传递机制。 什么是…

爬虫是什么?起什么作用?

【爬虫】 如果把互联网比作一张大的蜘蛛网,数据便是放于蜘蛛网的各个节点,而爬虫就是一只小蜘蛛,沿着网络抓取自己得猎物(数据)。这种解释可能更容易理解,官网的,就是下面这个。 爬虫是一种自动…

红日靶场-2

目录 前言 外网渗透 外网渗透打点 1、arp探测 2、nmap探测 3、nikto探测 4、gobuster目录探测 WebLogic 10.3.6.0 1、版本信息 2、WeblogicScan扫描 3、漏洞利用 4、哥斯拉连接 内网渗透 MSF上线 1、反弹连接 2、内网扫描 3、frpc内网穿透 4、ms17-010 5、ge…

第十三章 常用类(包装类和 String 相关类)

一、包装类 1. 包装类的分类 (1)针对八种基本数据类型相应的引用类型—包装类 (2)有了类的特点,就可以调用类中的方法。 2. 包装类和基本数据类型的转换 (1)jdk5 前的手动装箱和拆箱方式 publ…

Unity预设体

目录 预设体是什么? 如何创建预设体? 如何修改预设体? 如何删除预设体? 预设体是什么? Unity中的预设体(Prefab)是一种可重复使用的游戏对象模板。它允许开发者创建一个或多个游戏对象&…

模型评估系列:回归模型的评估指标介绍和代码实践

文章目录 1. 简介2. 回归评估指标2.1 平均绝对误差(MAE)2.2 均方误差(MSE)2.3 均方根误差(RMSE)2.4 R平方(决定系数)2.5 调整后的R平方2.6 交叉验证的R22.7 回归评估指标 - 结论 3 设…