【完整项目】基于Python+Tkinter+FFD(free-form deformations)的2D彩色图像实时网格自由变形软件的设计与实现

文章目录

  • 一、效果展示
  • 二、前言介绍
  • 三、软件使用说明
    • 3.1 环境配置
    • 3.2 文件结构
    • 3.3 准备工作
  • 四、快速开始
  • 五、主要思路
    • 算法思路
    • 网格变形和实时操作思路
  • 六、总结与反思
  • 七、代码链接
  • 八、其他完整项目


一、效果展示

校正比萨斜塔:

请添加图片描述

人脸变形:

请添加图片描述

图像拼接结果中,重叠区域的对齐warp细节修正:

请添加图片描述


二、前言介绍

这是一个基于Python+Tkinter+FFD(free-form deformations)的2D彩色图像实时网格自由变形软件,它可以将任意彩色RGB图像划分为若干网格,用户可以使用鼠标点击网格顶点,按住并拖拽移动,释放鼠标后,图像会根据网格的变形而实时变形。

网格的自由变形技术(FFD,mesh warp/grid warp)在图像配准领域广泛使用,包括图像的旋转校正、图像人脸变形(image morphing)等。而在图像拼接领域,网格变形也几乎涵盖了所有的传统方法,在图像翘曲步骤使用。所以,了解网格变形技术对于图像拼接技术的学习也是大有裨益。

做这个软件或者写这篇文章的动机:

  1. 目前没有公开类似的软件,也没有好的文章来讲网格变形。
  2. 有图像变形的需求。
  3. 看到文章Deep Rotation Correction Without Angle Prior里nie等人开发了这样的软件制作数据集(文章第四部分),手痒就做一个类似的,也算复现文章的一部分。
    在这里插入图片描述
    为了进一步提高数据集的质量,我们开发了一个基于网格的程序,对旋转结果进行手动微调。基于网格的程序来手动微调旋转结果。He等人的旋转方法[7]。它允许用户用鼠标拖动拖动网格顶点,以交互方式修改网格变形。

文章链接:【图像拼接】论文精读:Deep Rotation Correction without Angle Prior(DRC)

  1. 学习网格变形原理,对加深图像拼接中网格变形的原理有帮助。(虽然FFD和图像拼接中的图像warp不太一样)
  2. 网格变形简单,但是让图像跟随网格的变化而变化比较难。(怎么实现网格到图像的映射呢?我看这也是大多数人比较发愁的地方)
  3. 学习软件开发,练练tkinter

软件的基础功能:

  1. 2D图像实时网格变形,包括灰度图、彩色RGB图像
  2. 保存变形后的图像

软件的特色功能:

  1. 颜色复原:一般FFD都是变形灰度图,只有形状变化,没有颜色和亮度变化;而本软件可以在颜色和亮度变化后,通过算法将颜色和亮度恢复到和原输入图像一致。(前面效果展示中只有变形步骤,没有颜色恢复步骤,颜色复原的效果见第四部分【快速开始】中的第6步)。
  2. 支持任意大小的网格,并保证实时处理速度。网格越密,图像微调的越精细。
  3. 可以应用到各种需要图像变形的场景,比如上面展示的图像内容校正、捏脸、全景图/鱼眼图的扭曲消除、各种细节微调、甚至可以通过拉伸将全景图矩形化。
  4. 使用极简风格编写,只用了numpy,pillow,torch三个库,没有用opencv等打包后文件比较大的库。

三、软件使用说明

3.1 环境配置

下载源码后,用pycharm打开该项目,setting中设置好所需的python环境。建议新建一个虚拟环境进行配置。

安装依赖:torch可能比较慢,建议使用清华镜像

pip install -r requirements.txt 或
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/

requirments.txt中的库以及库版本:
在这里插入图片描述
numpy用于存储网格结构和图像输入,PIL用于将图像显示在tkinter上,torch用于将网格变化映射到图像时计算损失,即将图像以张量的形式输入及操作。

3.2 文件结构

项目文件结构如下:
在这里插入图片描述

  • main.py:主函数运行tkinter的GUI窗口
  • mesh_warp.py:网格变形相关算法,包括B样条、插值算法等
  • tk_utils.py:tkinter的相关操作,包括组件逻辑等

3.3 准备工作

在本地任意位置准备好待处理的图像,支持jpg和png格式。

四、快速开始

  1. 运行main.py打开软件界面:
    请添加图片描述
  2. 输入网格大小,然后点击【确定网格大小】。以15*15为例:
    在这里插入图片描述
  3. 点击菜单栏【文件】,然后选择自己要处理的图像(或快捷键A)
    在这里插入图片描述
  4. 选择好的图像如下所示,如果窗口大小显示不全可以拖拽改变窗口大小:
    在这里插入图片描述
  5. 鼠标点击网格顶点,拖拽移动,释放鼠标,图像产生对应的形变,颜色和亮度会发生变化
    在这里插入图片描述
  6. 形变完成后,点击【恢复图像颜色】,会弹出提示框,等待较长时间后,会弹窗提示颜色恢复完毕。(注:颜色恢复的时长与你的形变量和图像质量有关,如果形变较多,图像质量较高,请耐心等待
    在这里插入图片描述
    在这里插入图片描述
  7. 图像恢复原色后,可以点击【文件】,然后【保存图像】;或按快捷键S,可以将图像保存到本地的任意位置。
    在这里插入图片描述
  8. 菜单栏的【帮助】中有详细的【使用说明】
    在这里插入图片描述
  9. 菜单栏的【帮助】中的【关于】有软件的相关说明
    在这里插入图片描述

五、主要思路

整体过程描述:将图像放入网格阵中,通过控制网格的变形来定义一个空间变换函数,使各点映射到变形后的空间中,与图像的插值算法结合,从而实现图像变形。

算法思路

空间变换函数使用三次B样条,具体原理见下面文献:

D. Rueckert, L. I. Sonoda, C. Hayes, D. L. G. Hill, M. O. Leach, and D. J. Hawkes, “Nonrigid
registration using free-form deformations: application to breast mr images,” IEEE Transactions
on Medical Imaging, vol. 18, no. 8, pp. 712–721, 1999.

三次B样条的基函数:
在这里插入图片描述
重点:将网格变形映射到图像上

一般的方法是利用网格的变换结果对图像中的像素点进行插值运算,场景的有双线性插值等,就是图像resize用的那个插值算法。但是,图像resize并不涉及图像的warp。换句话说,图像resize的变换是线性的,而图像warp的变化是非线性的。那么,如果我想让图像变形后的插值尽量与原变化一致,就需要对每个像素点计算变形的贡献,即添加权重。没有形变的像素位置的权重为0,有形变的像素通过核函数施加权重,最后得到图像每个像素的加权和。

然而,当图像很大,质量很高时,上述方法的计算复杂度将是非常高的,计算缓慢,无法实现我们想达到的实时效果。

于是,我们受到深度学习中损失函数的启发,将目标图求逆得到反向图,将反向图与原图之间的差别视为loss,然后最小化这个loss,最后再变换回来,则得到损失最小的形变图像。(是不是很像图像拼接中网格变形的那些能量函数,定义很多个能量项,然后最小二乘找最优解就是最优的warp。这里我们也是这种思想,只不过我们的损失是简单的二次平方差。

为了计算上述损失,那么图像的输入numpy流转为tensor流,求解后转为PIL流,用于显示到界面中。

上述原理对应mesh_warp.py中的函数,大家可以根据代码理解上述原理。

numpy流:输入图像,输入网格
tensor流:网格和图像转为tensor输入
pillow流:tkinter的GUI界面显示

先迭代2次,实现实时形变,最后迭代40次,用于恢复图像原色。

注:不是只有训练模型才会用到torch,也会有只用到计算loss,只用反向传播的情况。

网格变形和实时操作思路

用tkinter的canvas显示网格和图像,网格由顶点和线组成。层级关系由上到下依次为:顶点、线、图像。

初始化网格后,要能得到网格顶点的相关信息,包括网格顶点坐标,网格顶点的序号;与网格顶点相交的线的信息,线的id等。用户用鼠标点击网格顶点后,要能知道用户点击的是哪个网格顶点,从而知道与其相交的线,进而移动它们。

初始化网格时,每个顶点对应右、下两条相邻的网格边。除了最后一列和最后一行,每个网格顶点及其右、下临边作为一个整体按先列后行初始化;最后一列是从上到下初始化,最后一行是从左到右初始化。

只移动与顶点相交的线:
在这里插入图片描述
上述思路见tk_utils.py,代码注释详细。

六、总结与反思

  1. 恢复原图颜色和亮度实际上还是有一些不同的,但是已经足够接近了。起码可以变形彩色的RGB图像了,能满足一部分需求。
  2. 实现过程中,一定要设计好变量流,比如网格mesh是如何变换的,怎么存储顶点和线的坐标,怎么得到它们的索引;图像从输入开始是如何变化的。本例中图像就有numpy,PIL,tensor三种形式。
  3. 可以用cuda加速颜色复原过程,感兴趣的朋友可以试试。

七、代码链接

项目源码链接:基于Python+Tkinter+FFD(free-form deformations)的2D彩色图像实时网格自由变形软件

八、其他完整项目

【完整项目】基于Python+Tkinter+OpenCV+Yolo+手写OCR的双模式答题卡识别软件的设计与实现

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

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

相关文章

C# 读取Word表格到DataSet

目录 功能需求 Office 数据源的一些映射关系 范例运行环境 配置Office DCOM 关键代码 组件库引入 ​核心代码 杀掉进程 总结 功能需求 在应用项目里,多数情况下我们会遇到导入 Excel 文件数据到数据库的功能需求,但某些情况下,也存…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十七:演示功能模块相关功能实现

一、本章内容 本章实现常见业务功能,包括文章管理、商品管理、订单管理、会员管理等功能。 1. 详细课程地址: https://edu.csdn.net/course/detail/38183 2. 源码下载地址: 点击下载 二、界面预览 三、开发视频 3.1 B站视频地址:

Jenkins 自动设置镜像版本号

使用Jenkins环境变量当作镜像版本号 这样version变量就是版本号,在镜像构建的过程中可以使用 docker build 之后,如果有自己的镜像库,肯定要docker push 一下 至于部署的步骤,一般需要stop并删除原有的容器.我这里用的是docker-compose。同样…

如何使用 pnpm 实现前端 Monorepo项目管理

前言 随着软件开发项目变得越来越庞大和复杂,如何有效管理和维护代码库成为了一个重要的问题。一种流行的解决方案是 Monorepo,也就是在一个版本控制系统中管理所有的项目代码。 什么是 Monorepo Monorepo 是一种项目代码管理方式,指单个仓…

PHP-8.1.0-dev 后门命令执行漏洞复现_zerodiumvar_dump

0x00漏洞描述 PHP 8.1.0-dev 版本在2021年3月28日被植入后门,但是后门很快被发现并清除。当服务器存在该后门时,攻击者可以通过发送User-Agentt头来执行任意代码。 0x01影响范围 PHP 8.1.0-dev 0x02环境搭建 1、本次环境搭建使用vulhub中的docker环…

PPT中加入页码

PPT中加入页码 文章目录 简单版本样式更改 简单版本 PPT中插入页码,基础的就是在“插入”选项卡中单机“幻灯片编号”即可 样式更改 然而,就像我们做幻灯片不满足于白底黑字一样,页码也总不能是默认的样式。 比如,在页码下面…

2023年全国省市区县行政区划矢量数据(含10段线)

2023年,中国地图面貌发生了重大变化,领土面积由960万平方公里扩大到1045万平方公里,九段线改为了十段线。 因此在使用地图的时候,特别是做全国的地图的时候,一定需要最新的行政界限,今天就将最新的省市县行…

在Vue3中使用qrcode库实现二维码生成

本文主要介绍在Vue3中使用qrcode库实现二维码生成的方法。 目录 一、基础用法实现二、toDataURL()方法三、toCanvas()方法四、create()方法五、QRCodeRenderersOptions()方法 在Vue3中实现二维码生成需要使用第三方库来处理生成二维码的逻辑。常用的库有 qrcode和 vue-qrcode…

使用 pytest.ini 文件控制输出 log 日志

一、前置说明 pytest.ini 文件中可以配置参数来控制 pytest 的运行行为,其存放路径要求与 conftest.py 一样。 项目根目录project_root/ ├── pytest.ini ├── tests/ │ └── test_demo.py以test开头的测试子目录project_root/ ├── tests/ │ ├── pytest.in…

c# OpenCvSharp透视矫正六步实现透视矫正(八)

透视矫正,引用文档拍照扫描,相片矫正这块。 读取图像Cv2.ImRead();预处理(灰度化,高斯滤波、边缘检测)轮廓检测(获取到最大轮廓)获取最大面积轮廓的四个顶点标识最小矩形坐标透视矫正显示 完整代码 // 1、…

Linux系统安装及管理

目录 一、Linux应用程序基础 1.1应用程序与系统命令的关系 1.2典型应用程序的目录结构 1.3常见的软件包装类型 二、RPM软件包管理 1.RPM是什么? 2.RPM命令的格式 2,1查看已安装的软件包格式 2.2查看未安装的软件包 3.RPM安装包从哪里来? 4.挂…

web前端项目-七彩夜空烟花【附源码】

web前端项目-七彩动态夜空烟花【附源码】 本项目仅使用了HTML,代码简单,实现效果绚丽,且本项目代码直接运行即可实现,无需图片素材,接下来让我们一起实现一场美丽的烟花秀叭 运行效果:鼠标点击和移动可控制…

理解SpringMVC的工作流程

组件 前置控制器 DispatcherServlet。 映射控制器 HandlerMapping。 处理器 Controller。 模型和视图 ModelAndView。 视图解析器 ViewResolver。 工作流程 spring mvc 先将请求发送给 DispatcherServlet。 DispatcherServlet 查询一个或多个 HandlerMapping,找到…

jmeter-set up先登录获取token,再测试

一、何为setup 一种特殊类型的线程组,可用于执行预测试操作;简单来讲就是执行测试线程组前,先执行setup 作用 例如前面,我们说到的,压测之前只用JMeter调用业务接口造数或者通过JDBC操作数据库造数,可以放…

网络安全法规和模型

基础 ISO信息安全:为数据处理系统建立和采取技术、管理的安全保护,保护计算机硬件、软件、数据不因偶然的或恶意的原因而受到破坏、更改、泄露 信息安全属性: CIA三元组:保密性、完整性、可用性 其他属性:真实性、不…

鸿蒙开发中的坑(持续更新……)

最近在使用鸿蒙开发时,碰到了一些坑,特做记录,如:鸿蒙的preview不能预览,轮播图组件Swiper使用时的问题,console.log() 打印的内容 一、鸿蒙的preview不能预览 首先,只有 ets文件才能预览。 其…

Spring系列学习二、Spring框架的环境配置

Spring框架的环境配置 一、Java环境配置二、 Spring框架的安装与配置三、Maven与Gradle环境的配置四、IDE环境配置(Eclipse与IntelliJ IDEA)五、结语 一、Java环境配置 所有编程旅程总是得从基础开始,如同乐高积木大作的基座,首先…

408数据结构错题知识点拾遗

408相关: 408数据结构错题知识点拾遗 408计算机网络错题知识点拾遗 对于数据结构的学习,个人认为要对概念性的东西进行理解,特别是树的性质、图的相关性质和考察的相应算法。应用题强化的话,对于每一章节尾的应用小节&#xff0c…

蓝桥杯c/c++程序设计——冶炼金属

冶炼金属 问题描述 小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。这个炉子有一个称作转换率的属性 V,V 是一个正整数,这意味着消耗 V 个普通金属 O 恰好可以冶炼出一个特殊金属 X,当普通金属 O 的数目不足 V 时&#xff0…

Python - 深夜数据结构与算法之 Divide Conquer Backtrack

目录 一.引言 二.分治与回溯简介 1.Divide & Conquer 分治 2.BackTrack 回溯 三.经典算法实战 1.Combination-Of-Phone [17] 2.Permutations [46] 3.Permutations-2 [47] 4.Pow-X [50] 5.N-Queen [51] 6.Combinations [78] 7.Sub-Sets [78] 8.Majority-Elemen…