Python图像处理【5】图像扭曲与逆扭曲详解

news2025/1/24 22:31:49

图像扭曲与逆扭曲详解

    • 0. 前言
    • 1. 使用 scikit-image warp() 函数执行图像变换
      • 1.1 scikit-image warp() 函数原理
      • 1.2 利用 warp() 函数实现图像变换
    • 2. 漩涡变换详解
      • 2.1 旋涡变换原理
      • 2.2 使用 scikit-image warp() 实现旋涡变换
      • 2.3 使用 scipy.ndimage 实现漩涡变换
    • 3. 使用 scikit-image 实现弹性变形
      • 3.1 弹性变形原理
      • 3.2 实现弹性变形
    • 小结
    • 系列链接

0. 前言

我们已经知道,可以将图像变换分为线性变换与非线性变换两类,在《图像线性变换》一节中,我们介绍了如何在图像上应用欧几里得变换(例如,旋转、反射)和仿射转换。在本节中,我们将进一步学习如何利用 scikit-image 库执行图像变换,除了线性变换外,本节着重讲解了如何执行旋涡变换、弹性变换等非线性变换。

1. 使用 scikit-image warp() 函数执行图像变换

2D 线性几何变换是点转换,它们会被应用于图像中的每个像素,以得到变换后的输出图像。本节中,我们将介绍如何使用 scikit-image 库中的 warp() 函数来执行图像变换。

1.1 scikit-image warp() 函数原理

对于变换后的输出图像中的像素值 f ( x ′ , y ′ ) f(x',y') f(x,y) 可以使用以下方程式在输入图像对应位置 ( u , v ) (u, v) (u,v) 处获取,将得到的像素值赋值给输出图像即可得到结果:

f ( x ′ , y ′ ) = g ( u , v ) f(x',y')=g(u,v) f(x,y)=g(u,v)

其中, x ′ x' x y ′ y' y 分别表示沿 x x x y y y 轴的变换 x ( u , v ) = x ′ x(u,v)= x' x(u,v)=x y ( u , v ) = y ’ y(u,v)=y’ y(uv)=y,我们也可以使用反扭曲来实现图像变换。使用 warp() 函数是更通用的图像变换方式,可用于实现线性(例如,使用矩阵乘法来实现的变换)和非线性图像变换。使用 warp() 函数执行图像变换,我们需要提供(反向)变换函数,而非变换矩阵。

1.2 利用 warp() 函数实现图像变换

根据 scikit-image 文档,我们得知 warp() 函数可以通过使用如下输入参数调用,利用该函数我们可以以更通用的方式实现图像变换(函数的输入参数如下):

skimage.transform.warp(image, inverse_map, map_args={}, output_shape= None, order=1, mode='constant', cval=0.0, clip=True, preserve_range=False)

warp() 函数根据给定的坐标变换函数 inverse_map 扭曲图像 image。接下来,我们实际应用 warp() 函数实现图像变换。

(1) 首先,导入所有所需的库,从 scikit-image 库的 transform 模块中导入 warp 函数:

from skimage.io import imread
from skimage.transform import warp
import matplotlib.pylab as plt

(2) 接下来,定义 translate() 函数,该函数用于在 warp() 函数中作为 inverse_map 参数实现像素坐标变换:

def translate(xy, t_x, t_y):
    xy[:, 0] -= t_y
    xy[:, 1] -= t_x
    return xy

(3) 读取输入图像,并将输入图像与变换函数一起传入 warp() 函数作为参数:

im = imread('1.png')
im = warp(im, translate, map_args={'t_x':-250, 't_y':200}) # 创建字典用于变换参数
plt.imshow(im)
plt.title('Translated image', size=20)
plt.show()

下图显示了程序执行后的输出,即将变换函数应用于输入图像后得到的输出图像:

平移变换

2. 漩涡变换详解

在上一小节中,我们学习了如何执行图像的线性变换,在本节中,我们将学习如何实现图像的非线性变换——漩涡变换 (swirl transform)。

2.1 旋涡变换原理

我们假设输出图像中的坐标为 ( x , y ) (x,y) (x,y),漩涡变换的反向映射首先应计算其相对于中心 ( x 0 , y 0 ) (x_0,y_0) (x0,y0) 的极坐标:
θ = a r c t a n ( y x ) ρ = ( x − x 0 ) 2 + ( y − y 0 ) 2 \theta=arctan(\frac y x) \\ ρ=\sqrt {(x-x_0)^2+(y-y_0)^2} θ=arctan(xy)ρ=(xx0)2+(yy0)2
然后,根据以下公式对其进行变换:
r = l n 2 ⋅ r a d i o u s 5 θ ′ = ψ + s ⋅ e − ρ r + θ r=ln2\cdot \frac {radious} 5 \\ \theta'=ψ+s\cdot e^{-\frac ρ r+\theta} r=ln25radiousθ=ψ+serρ+θ
其中 ψ ψ ψ 表示旋转角度, s s s 表示像素值强度。接下来,我们利用 warp() 函数实现漩涡变换。

2.2 使用 scikit-image warp() 实现旋涡变换

(1) 首先,导入所需库,并定义 swirl() 函数,该函数根据上述数学公式实现像素漩涡变换:

from skimage.io import imread
from skimage.transform import warp
import matplotlib.pylab as plt
import numpy as np

def swirl(xy, x0, y0, R):
    r = np.sqrt((xy[:,1]-x0)**2 + (xy[:,0]-y0)**2)
    a = np.pi*r / R
    xy[:, 1] = (xy[:, 1]-x0)*np.cos(a) + (xy[:, 0]-y0)*np.sin(a) + x0
    xy[:, 0] = -(xy[:, 1]-x0)*np.sin(a) + (xy[:, 0]-y0)*np.cos(a) + y0
    return xy

(2) 读取输入图像,然后将图像与 swirl() 函数输入参数调用 warp() 函数,以将非线性变换应用于输入图像:

im = imread('1.png')
print(im.shape)
im1 = warp(im, swirl, map_args={'x0':250, 'y0':350, 'R':600})
plt.figure(figsize=(20,10))
plt.subplot(121), plt.imshow(im), plt.axis('off'), plt.title('Input image', size=10)
plt.subplot(122), plt.imshow(im1), plt.axis('off'), plt.title('Output image', size=10)
plt.show()

函数 swirl() 接受参数 xyx0y0r,并根据 warp() 函数的 map_args 参数进行设定。
执行以上代码,可以得到以下结果图像:

旋涡变换
需要注意的是,x0y0R 参数传递给 swirl() 函数,通过修改这些参数值,可以观察到不同参数对输出图像的影响。

2.3 使用 scipy.ndimage 实现漩涡变换

在上一小节中,我们学习了如何使用 scikit-image warp() 实现旋涡变换;在本小节中,我们将继续学习如何使用 scipy.ndimagegeometric_transform() 函数实现非线性漩涡变换。

(1) 首先,导入所需库,并定义实现漩涡变换所需的函数 apply_swirl()

from scipy import ndimage as ndi
from skimage.io import imread
from skimage.color import rgb2gray
import matplotlib.pylab as plt, numpy as np

def apply_swirl(xy, x0, y0, R):                                                                        
    r = np.sqrt((xy[1]-x0)**2 + (xy[0]-y0)**2)
    a = np.pi*r / R
    return ((xy[1]-x0)*np.cos(a) + (xy[0]-y0)*np.sin(a) + x0, -(xy[1]-x0)*np.sin(a) + (xy[0]-y0)*np.cos(a) + y0)

函数 apply_swirl() 接受参数 xyx0y0r,并根据 geometric_transform() 函数的 extra_arguments 参数进行设定。

(2) 接下来,读取输入图像,并将其转换为灰度图像,从 scipy.ndimage 模块中调用 geometric_transform() 函数,然后将 apply_swirl() 函数作为参数传递给 geometric_transform() 函数,用于执行漩涡变换。

im = rgb2gray(imread('1.png'))
print(im.shape)
im1 = ndi.geometric_transform(im, apply_swirl, extra_arguments=(300, 200, 620))

(3) 最后,绘制原始图像和变换后的图像:

plt.figure(figsize=(20,10))
plt.gray()
plt.subplot(121), plt.imshow(im), plt.axis('off'), plt.title('Input image', size=10)
plt.subplot(122), plt.imshow(im1), plt.axis('off'), plt.title('Output image', size=10)
plt.show()

请添加图片描述

3. 使用 scikit-image 实现弹性变形

3.1 弹性变形原理

对图像应用位移场( displacement fields )可以产生图像畸变,通过位移场可以计算每个像素原始位置的新目标位置。位置 ( x , y ) (x,y) (x,y) 处的新目标位置根据原位置得出,例如,如果 Δ X ( x , y ) = 1 ΔX(x,y)=1 ΔX(x,y)=1 Δ y ( x , y ) = 0 Δy(x,y)=0 Δy(x,y)=0 这意味着每个像素的新位置都向右移动 1。我们可以通过以下步骤创建图像弹性变形:

  • 首先,生成随机位移场,即 Δ y ( x , y ) = r a n d ( − 1 , + 1 ) Δy(x,y)= rand(-1,+1) Δy(x,y)=rand(1,+1) Δ x ( x , y ) = r a n d ( − 1 , + 1 ) Δx(x,y)= rand(-1,+1) Δx(x,y)=rand(1,+1),其中 r a n d ( − 1 , + 1 ) rand(-1,+1) rand(1,+1) 用于生成一个在 -11 之间的随机数
  • 然后用标准偏差为 σ σ σ 的高斯函数(以像素为单位)与 Δ x Δx Δx Δ y Δy Δy 执行卷积
  • 如果 σ σ σ 很大,因为随机值的平均值为 0,则将导致结果值非常小,如果我们将位移场进行归一化,则位移场将接近具有随机方向的常数;如果 σ σ σ 很小,则位移场在归一化后近似于完全随机的场。如果 σ σ σ 值大小合适,位移场则类似弹性变形,其中 σ σ σ 为弹性系数
  • 然后将位移场乘以控制变形强度的缩放因子 α α α

3.2 实现弹性变形

(1) 首先导入所需的库,然后自定义函数实现弹性变形函数 elastic_transform()

import numpy as np
import matplotlib.pylab as plt
from skimage.color import rgb2gray
from scipy.ndimage import gaussian_filter, map_coordinates

def elastic_transform(image, alpha, sigma):
    random_state = np.random.RandomState(None)
    h, w = image.shape
    dx = gaussian_filter((random_state.rand(*image.shape) * 2 - 1), sigma, mode="constant", cval=0) * alpha
    dy = gaussian_filter((random_state.rand(*image.shape) * 2 - 1), sigma, mode="constant", cval=0) * alpha
    x, y = np.meshgrid(np.arange(w), np.arange(h))
    indices = np.reshape(y+dy, (-1, 1)), np.reshape(x+dx, (-1, 1))
    distored_image = map_coordinates(image, indices, order=1, mode='reflect')
    return distored_image.reshape(image.shape)

函数 map_coordinates() 通过插值将输入阵列映射到新的坐标,坐标的数组用于为输出中的每个点找到输入中的相应坐标,这些坐标处的输入值由调用函数时所用的插值参数 order 确定。

(2) 使用 matplotlibimread() 函数读取输入图像,并使用 skimage.colorrgb2gray() 函数将其转换为灰度图像:

img = rgb2gray(plt.imread('2.png'))

(3) 调用 elastic_transform() 函数将弹性变形应用于图像:

img1 = elastic_transform(img, 100, 4)

(4) 绘制原始输入和应用弹性形变后的输出图像:

plt.figure(figsize=(20,10))
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.axis('off'), plt.title('Original', size=10)
plt.subplot(122)
plt.imshow(img1, cmap='gray')
plt.axis('off'), plt.title('Deformed', size=10)
plt.tight_layout()

弹性变形

小结

在本节中,我们学习了如何使用 scikit-image 库中的通用图像变换函数 warp(),该函数不仅可以实现常见的图像线性变换,而且能够实现包括旋涡变换、弹性变换等在内的非线性变换。在实际应用 warp() 函数之前,我们还学习了不同非线性变换的基本数学原理,以分辨其与线性变换之间的差别。

系列链接

Python图像处理【1】图像与视频处理基础
Python图像处理【2】探索Python图像处理库
Python图像处理【3】Python图像处理库应用
Python图像处理【4】图像线性变换

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

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

相关文章

如何抓住2023年技术创新的浪潮和趋势?

编辑 | 阿冒 设计 | 沐由千百年以来,技术的进步始终与人类社会的发展紧密相连,每一次重大的技术变革均对社会带来的深刻而持久的影响。最近半个世纪以来的表征,尤其明显。数字技术,正在以其“春风化雨”的姿态滋润着万物&#…

界面组件DevExpress v22.2官宣发布——正式支持.NET 7

DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpress Dashboard eXpressApp 框架、适用于 Visual Studio的CodeRush等一系列辅助工具,该组件拥有众多新产品和数十个具有高影响力的功能,可为桌面、Web和移动应…

最新系统MacOs13 Ventura(M1/M2芯片) + Parallels Desktop 18(PD18史上最强虚拟机)永久使用攻略

众神殿内,高朋满座,胜友如云,Vmware、VirtualBox、Utm等虚拟机大神群英荟萃,只见位于C位王座上的Parallels怅惘抬头,缓缓逡巡,睥睨群小,目光到处,无人敢抬头对视。 是的&#xff0c…

网络空间安全中高职业院校职技能大赛——借助.htaccess上传绕过

1.选择pass-04 查看源码发现 .php .php5 …这些文件都不能上传 2.修改一句话木马为a.jpg 3.新建.htaccess文件,内容如下 上传.htaccess 编辑菜刀去连接,取得shell

C++数学与算法系列之初等数论

1. 数 什么是数? 一个用作计数、标记或用作量度的抽象概念。 代表数的一系列符号,包括数字、运算符号等统称为记数系统。 在日常生活中,数通常出现在标记(如公路、电话和门牌号码)、序列号和编码上。在数学里&…

一年后,那个残酷的 Log4j 漏洞仍然潜伏

©网络研究院 一年前,随着俄罗斯在其与乌克兰的边境集结军队以及Covid-19 Omicron 变种开始在全球范围内激增,Apache 软件基金会披露了一个漏洞,在全球科技行业掀起了一阵狂热。 该错误称为 Log4Shell,在无处不在的开源日志…

《MySQL系列-主从相关》Docker安装MySQL,实现主从复制

Docker安装MySQL,实现主从复制 一、前言 1 Docker安装MySQL 参考历史文章Docker安装MySQL,准备两台MySQL容器 master节点 容器名称 MySQL01 容器ID faf2312fd62a 端口 33061 slave节点 容器名称 MySQL01 容器ID dfc693c2bb04 端口 33062 2 M…

【Numpy基础知识】Datatypes数据类型

Numpy 数据类型 来源:Numpy官网:https://numpy.org/doc/stable/user/basics.html 文章目录Numpy 数据类型导包【1】数组类型和类型之间的转换【2】数组标量【3】溢出错误【4】扩展精度导包 import numpy as np【1】数组类型和类型之间的转换 NumPy支持…

弃购频频发生?跨境电商卖家必知的弃购原因以及解决方案!

关键词:弃购、跨境电商卖家 电子商务商店平均有 75% 的销售额因数字购物车放弃而损失。 本文分解了放弃购物车的主要原因(以及如何预防)。 放弃购物车的十大原因 放弃购物车是一个问题。正如我们在介绍中分享的那样,据估计&#…

使用css3实现一个超浪漫的新年倒计时

新年快到了,使用css3实现一个超浪漫的新年倒计时吧,希望大家喜欢。 目录 1 实现思路 2 实现浪漫的心形背景 3 布局小时分钟和秒的区域 4、js倒计时 5、然后就是将所得的小时、分钟、秒对DOM进行赋值 6、每秒一更新 7、补充知识点1- 倒计时为什…

爆款微信小游戏,你都知道几款?

紧随微信2017年上线小程序平台,11月份便开始向各大小游戏厂商发送邀请函开发微信小游戏。2017年12月28日,微信正式对外开放微信小游戏。 就微信小游戏来说,其开发者数量在今年已经超过10万人;而产品方面除了《跳一跳》《羊了个羊…

全网首次揭秘:微秒级“复活”网络的HARP协议及其关键技术

导读|云计算时代,承担服务器之间数据传输工作的交换机成了数据中心的“神经枢纽”,一旦出故障将波及上层业务。然而单个交换机故障时,腾讯云的新一代高性能网络却可以在100微秒内找到新的通路实现0断链,做到高可用、高…

基于springboot layui疫苗接种信息管理系统源码

开发工具:idea 数据库mysql5.7 数据库链接工具:navcat,小海豚等 开发技术:springboot layui 伴随着社会的迅速发展,电子计算机对世界的作用影响是全面并且长久的。人们日常生活消费综合应用水平的持续增高,生活中人…

[ 数据结构 -- 手撕排序算法总结篇 ]

文章目录前言一、常见的排序算法二、测试排序的性能对比随机数排序时间对比有序数排序时间对比三、排序算法的复杂度四、排序算法的稳定性前言 手撕排序算法总结 本篇文章进行总结,我会对比并分析常见的几种排序,例如像插入排序,冒泡排序&am…

【金猿案例展】福特电马——一键五联私域流量运营

‍映盛中国案例本项目案例由映盛中国投递并参与“数据猿年度金猿策划活动——《2022大数据产业年度创新服务企业》榜单/奖项”评选。‍数据智能产业创新服务媒体——聚焦数智 改变商业随着中国电动车市场及消费者对电动汽车的需求的不断变化,汽车市场进入存量竞争时…

如何用VS2010创建并生成动态链接库

1、目的 在某些应用程序场景下,需要将一些类或者方法编译成动态链接库dll,以便别的.exe或者.dll文件可以通过第三方库的方式进行调用,下面就简单介绍一下如何通过VS2010来创建动态链接库。 2、新建动态链接库 1) 打开VS2010&…

546103-85-9,PR-AMC,二肽标记肽

PR-AMC, a fluorogenic Plasmodium falciparum dipeptidyl aminopeptidase 1 (DPAP1, cathepsin C) substrate.一种含氟恶性疟原虫二肽基氨基肽酶1 (DPAP1,组织蛋白酶C)底物。编号: 177167 中文名称: 二肽标记肽PR-7-氨基-4-甲基香豆素2HCl英文名: H-Pro-Arg-AMCCAS…

clickhouse 数据字典使用详解

一、数据字典介绍 数据字典是ClickHouse提供一种非常简单且实用的存储媒介,他以键值和属性映射的形式定义数据。字典中的数据会主动或被动加载到内存并支持动态更新。由于字典数据常驻内存的特性,所以非常适合保存常量或经常使用的维度表数据&#xff0c…

2001-2020年沪深A股上市公司管理者短视主义指标数据

2001-2020年沪深A股上市公司管理者短视主义指标数据 1、时间:2001-2020年 2、包括所有沪深A股所有上市公司 3、指标包括: 证券代码:以上海证券交易所和深圳证券交易所公布的证券代码为准。 证券简称:以上海证券交易所和深圳证…

从搭建到落地,详解证券基金行业数字化运营体系

近年来,金融行业的数字化转型呈现了新的特点,即要做更精准的营销和数字化运营。本文根据神策数据杨雪杉关于《面向落地的证券基金行业运营体系搭建》的主题演讲整理,点击文末“阅读原文”即可观看完整版演讲回放。一、基于 SDAF 数据闭环方法…