Python图像处理【5】图像扭曲/逆扭曲

news2024/12/25 9:05:23

图像扭曲/逆扭曲

    • 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/102558.html

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

相关文章

3ds Max:加强型文本

3ds Max 中的加强型文本 TextPlus工具能够实现非常多的功能。在 3ds Max 中,加强型文本也是标准基本体。新建加强型文本后,可以看到其相关参数,在下方可以更改文本的内容外观。插值Interpolation步数Steps用来控制文本图形线段间的端点数&…

[附源码]计算机毕业设计Python高校流浪动物领养网站(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等…

MySQL基础操作汇总(干货)

数据库操作: 1)创建数据库:create database数据库名; 2)查看所有数据库:show databases; 3)选中指定数据库:use 数据库名; 4)删除数据库: drop database数据库名; 数据表操作 1)创建表:create table表…

Mycat(7):分片详解之枚举

1 分片思路 打开rule.xml 文件,找到对呀的分片规则,如:sharding-by-intfile 标签含义: columns:代表数据库里面的字段名 algorithm:分片算法 找到rule.xml文件中的hash-int分片算法地址,指向文件partition-…

满大街都在叫我学Python,真有必要学吗?

前言 前一段时间在网上看到非常多的推广,无一例外都是分享自己学python的经历,告诉你自己学了之后,无一例外都是说找工作好找,需求多,2个小时的工作5分钟就做完了,找资料要30分钟,学会之后只要…

数据中心网络学习资料

目录 该文章持续更新,收集了一些比较好的与数据中心相关的文章和课程。 文章: 老网工:浅谈数据中心云网技术的历经风雨和演进:https://www.sdnlab.com/22920.html 数据中心网络架构浅谈(一):…

2022年seo优化怎么做:百度官方给出解答

最近百度搜索平台最近对站长圈部分站长进行了SEO、网络建站、搜索合作等方向的经验征集,2022年seo优化怎么做,对于站长们今年网站优化提供了新的思路,非常值得参考: 2022年对于SEO从业者而言,需要将更多的精力聚焦在流量的变化上,这可能是不平凡的一年,作为站长后续在网…

自动驾驶专题介绍 ———— 制动系统

制动系统 使行驶中的汽车减速甚至停车,使下坡行驶的汽车保持速度稳定,以及使已停驶的汽车保持不动,这些作用统称为汽车制动。而对汽车进行制动的外力来源则是制动系统。  制动系统由制动器和制动驱动机构构成。制动器是指产生阻碍车辆运动或…

微服务框架 SpringCloud微服务架构 微服务面试篇 54 微服务篇 54.8 Sentinel的限流与Gateway的限流有什么差别?

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 微服务面试篇 文章目录微服务框架微服务面试篇54 微服务篇54.8 Sentinel的限流与Gateway的限流有什么差别?54.8.1 限流与常见 限…

dlib实现人脸识别+活体检测

目录: 一:dlib的shape_predictor_68_face_landmarks模型 二、眨眼检测 三、张口检测 四、眨眼检测张口检测 五、人脸识别 六、人脸识别活体检测 七、人脸识别破解方法 八、参考资料及下载 一:dlib的shape_predictor_68_face_landmarks模型 …

二、导入文献

导入文献 1.导入文献的方式 2.直接检索方式 (1)增加检索条件(最右侧): (2)设置逻辑关系(最左侧): (3)跨年度检索: 3.英…

Web3中文|美前总统特朗普发布NFT,数千美元“换取”一顿晚餐

本周三,特朗普在他的社交媒体网站上开玩笑说他将发布“重大公告”,随后他于周四在Truth social上宣布推出45,000个NFT。 根据网站介绍,这些特朗普数字交易卡以类似于可收藏棒球卡的风格来展现这位美国前总统的形象。 这些NFT在Polygon上铸造…

(附源码)ssm心理咨询服务平台 毕业设计 324615

ssm心理咨询服务平台 摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对心理咨询服务平台等问…

FDDB roc验证工具使用方法

官方提供的是cpp的代码 环境:vs,opencv 1.配置opencv 首先在vs中新建个项目,把下载到的tgz文件解压,然后把hpp的放到头文件,cpp文件放到原文件,然后调整项目的属性,引入opencv。 参考https://…

编程学习简谈

如果你想知道怎么有效自学编程,欢迎继续往下看。我会和你分享这几年总结下来的5大绝招,让你少走一些弯路,以最快的速度上手编程。最近有很多朋友都在问我,究竟能不能自学编程呢?以我多年的经验,我可以负责任…

Python自动化运维—Paramiko实验(思科)

Paramiko实验——(思科)网络搭建 小白网工的python之路 【Python-自动化】paramiko模块 paramiko介绍 paramiko是基于Python实现的SSH2远程安全连接,支持认证及密钥方式。可以实现远程命令执行、文件传输、中间SSH代理等功能,相对…

网站seo优化到底该怎么做呢

企业网站seo优化到底该怎么做?”,今天为大家分享这个问题,推广做得好不好,全看你知不知道这些神技巧。 话不多说,一起来看看网站seo优化到底该怎么做吧! 企业网站seo优化到底该怎么做? 首先我们先思考SEO到底从哪几个方面入手。其实在做网站的时候,已经做过最基础的SEO…

Contest2800 - 【在线编程平台】2022年计算机类数据结构作业9.20221110-1115

问题 BW: 将邻接矩阵存储的图转换为邻接表存储的图,附加代码模式 内存限制:128 MB时间限制:1.000 S 评测方式:文本比较命题人:liuyong 提交:906解决:652 返回比赛提交提交记录侧边提交 题目…

Clickhouse表引擎探究-ReplacingMergeTree

作者:耿宏宇 1 表引擎简述 1.1 官方描述 MergeTree 系列的引擎被设计用于插入极大量的数据到一张表当中。数据可以以数据片段的形式一个接着一个的快速写入,数据片段在后台按照一定的规则进行合并。相比在插入时不断修改(重写)…

(1)Linux搭建 zookeeper+kafka集群

因为之前公司业务都是使用mqtt接收数据,随着设备的增加,公司觉得用kafka集群来实现会更好 下面是我写一个demo 仅供参考 一、安装jdk 没有安装的可以百度去看看怎么安装的 不行的话在私聊我!!!! 二、搭建…