【完整项目】基于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,一经查实,立即删除!

相关文章

【运维】大日志文件按日期划分方法的改进及思考

之前由于运维需求,需要对一个大日志文件按照日期进行划分,将每天的日志写入一个单独的文件中。 刚开始接到这个需求后,我浏览了一遍日志文件,发现里面只有11月17号到11月22号的日志,天数不多,可以尝试手动…

conan 入门(三十七):conan 2.x通过定义环境变量(environment)执行make编译只有Makefile的项目(erpcgen)

之前一篇博客《conan 入门(三十四):conan 2.x实现对只有Makefile的项目(erpcgen)的封装示例》介绍如何用AutotoolsToolchain,Autotools实现来编译只有Makefile的项目,因为Autotools.make,Autotools.install方法就是执行make来编译项目。 我原本是想用self.run来执行…

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环…

加速 SQL 查询的 9 种方法

SQL 是开发和查询数据库的主要语言,但它有一些怪癖。在我的上一篇文章中,我分享了 7 个需要避免的 SQL 错误。现在,让我们来看看编写更快的 SQL 查询的 9 个最佳实践。 更快 SQL 查询的 9 个最佳实践 仅检索您需要的列 使用 CASE 而不是 UP…

PPT中加入页码

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

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

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

http请求超时 ,用PHP如何解决的?

当进行HTTP请求时,有时候可能会遇到请求超时的情况。为了解决这个问题,你可以考虑以下几个方面: 设置脚本的最大执行时间: 在PHP中,可以使用set_time_limit函数来设置脚本的最大执行时间。该函数接受一个以秒为单位的整…

串口发送控制命令,实现一些外设LED 风扇 马达

main.c #include "uart4.h"int main(){char a;char buf[128];uart4_config();while (1){/* //接收一个字符数据agetchar();//发送接收的字符1putchar(a1);putchar(\r);putchar(\n); */gets(buf); // 读取字符串//puts(buf); // 输出字符串if(strcmp(buf,"l…

linux无法访问共享目录,ls hgfs失败

刚在新买的华为电脑上安装ubuntu20,共享文件出现各种问题: dlubuntu:/mnt$ ls ls: cannot access hgfs: Permission denied hgfs 解决方法: 1.首先输入vmware-hgfsclient,看看是否共享文件夹已经建立,没有的话去参考…

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

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

支付平台在选择服务器租用时要注意什么?

如果要建设一个支付平台的话要进行服务器租用,一旦涉及到钱的方面就必须要顾虑到多方面,这样才能保证安全性,今天小编就给大家讲一讲要注意什么呢? 1、带宽:带宽是业务稳定性的直接因素,只有带宽充足,这样…

kafka发送大消息

1 kafka消息压缩 kafka关于消息压缩的定义(来源于官网): 此为 Kafka 中端到端的块压缩功能。如果启用,数据将由 producer 压缩,以压缩格式写入服务器,并由 consumer 解压缩。压缩将提高 consumer 的吞吐量…

使用 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,代码简单,实现效果绚丽,且本项目代码直接运行即可实现,无需图片素材,接下来让我们一起实现一场美丽的烟花秀叭 运行效果:鼠标点击和移动可控制…