图像修复的可视化demo代码

news2025/6/3 14:58:45
  • 做项目的时候需要用到一个windows窗口可视化来展示我们的工作,我们的工作是一个文本指导的人脸图像修复,所以窗口需要包括输入图像,文本指导输入和修复结果,并且提供在输入图像上画mask的功能,使用tkinter来实现,相关代码如下:
# Authro: Wu
# define of gui
# borrow from https://github.com/zsyzzsoft/co-mod-gan

import tkinter as tk
from PIL import Image, ImageTk, ImageDraw
import numpy as np
import cv2
import torch
import os
def adjust_dynamic_range(data, drange_in, drange_out):
    if drange_in != drange_out:
        scale = (np.float32(drange_out[1]) - np.float32(drange_out[0])) / (np.float32(drange_in[1]) - np.float32(drange_in[0]))
        bias = (np.float32(drange_out[0]) - np.float32(drange_in[0]) * scale)
        data = data * scale + bias
    return data


class App(tk.Tk):
    def __init__(self, model, window_size=256):
        super().__init__()
        self.state = -1
        self.window_size = window_size
        self.canvas = tk.Canvas(self, bg='gray', height=self.window_size, width=self.window_size*2+10)
        self.canvas.bind("<Button-1>", self.L_press)
        self.canvas.bind("<ButtonRelease-1>", self.L_release)
        self.canvas.bind("<B1-Motion>", self.L_move)
        self.canvas.bind("<Button-3>", self.R_press)
        self.canvas.bind("<ButtonRelease-3>", self.R_release)
        self.canvas.bind("<B3-Motion>", self.R_move)
        self.canvas.bind("<Key>", self.key_down)
        self.canvas.bind("<KeyRelease>", self.key_up)
        self.canvas.pack()

        self.canvas.focus_set()
        self.canvas_image_left = self.canvas.create_image(0, 0, anchor='nw')
        self.canvas_image_right = self.canvas.create_image(self.window_size + 10, 0, anchor='nw')
        
        # 'generate' button
        self.btn_pen = tk.Button(self, text="生成", command=self.generate)
        self.btn_pen.pack(side="left", padx="10")

        # 'continue' button
        self.btn_pen = tk.Button(self, text="继续", command=self.switch)
        self.btn_pen.pack(side="left", padx="10")

        # text
        self.text = None
        self.entry01 = tk.Entry(self, textvariable=self.text, width=50)
        self.entry01.pack()

        self.model = model

        self.new_image()
        self.display()
    
    def generate(self):
        real = adjust_dynamic_range(self.input_image, [0, 255], [0, 1])
        # real: np array (1,3,256,256); 
        # mask: np array (1,1,256,256),masked 0, unmasked 1; 
        # text: string
        self.text = self.entry01.get()
        if len(self.text) < 1:
            self.text = 'a man'
        # with torch.no_grad():
        #     self.output_image = self.model.inpaint_(real, self.mask, self.text)  

        # save to local
        save_path = 'D:\我的文件\dd\demo\mask'
        if not os.path.exists(save_path):
            os.makedirs(save_path)
        mask_to_save = np.repeat(np.expand_dims(np.squeeze((1-self.mask)*255),2),3,2)
        Image.fromarray(mask_to_save).save(os.path.join(save_path, '7532_mask.png'))
        input_to_save = np.transpose(np.squeeze(self.input_image*np.repeat(self.mask,3,1)+np.repeat((1-self.mask)*255,3,1)), (1, 2, 0))
        Image.fromarray(input_to_save).save(os.path.join(save_path, '7532_masked.png'))
        # predict_to_save = np.transpose(np.squeeze(self.output_image), (1, 2, 0))
        # Image.fromarray(predict_to_save).save(os.path.join(save_path, 'predict.png'))

        self.display(2)
        self.mask = np.ones((1, 1, self.resolution, self.resolution), np.uint8)
        self.mask_history = [self.mask]
        
    def switch(self):
        self.input_image = self.output_image
        self.display(1)
        
    
    def new_image(self):
        ################################
        # load image from source
        image_path = tk.filedialog.askopenfilename()
        # self.input_image = Image.open(image_path).convert('RGB').resize((256,256))
        self.input_image = Image.open(image_path).convert('RGB')
        # self.input_image = Image.open('./application/eyeglasses/mmceleba/5995.jpg').convert('RGB').resize((256,256))
        self.input_image = np.expand_dims(np.transpose(np.asarray(self.input_image, dtype=np.uint8), (2,0,1)),axis=0)
        #######################
        self.resolution = self.input_image.shape[-1]
        self.mask = np.ones((1, 1, self.resolution, self.resolution), np.uint8)
        self.mask_history = [self.mask]

    def display(self, state=0):
        if state != self.state:
            self.last_state = self.state
        self.state = state
        
        if self.state == 0: #  painting
            image = self.input_image * self.mask + (1-self.mask)*255
            image_for_display = np.transpose(image[0, :3], (1, 2, 0))
            image_for_display_resized = cv2.resize(image_for_display, (self.window_size, self.window_size))
            self.tkimage = ImageTk.PhotoImage(image=Image.fromarray(image_for_display_resized))
            self.canvas.itemconfig(self.canvas_image_left, image=self.tkimage)
        elif self.state == 1: # switch
            image = self.input_image
            image_for_display = np.transpose(image[0, :3], (1, 2, 0))
            image_for_display_resized = cv2.resize(image_for_display, (self.window_size, self.window_size))
            self.tkimage = ImageTk.PhotoImage(image=Image.fromarray(image_for_display_resized))
            self.canvas.itemconfig(self.canvas_image_left, image=self.tkimage)
        elif self.state == 2: # generate
            image =  self.output_image 
            image_for_display = np.transpose(image[0, :3], (1, 2, 0))
            image_for_display_resized = cv2.resize(image_for_display, (self.window_size, self.window_size))
            self.tkimage_right = ImageTk.PhotoImage(image=Image.fromarray(image_for_display_resized))
            self.canvas.itemconfig(self.canvas_image_right, image=self.tkimage_right)
            image =  self.input_image 
            image_for_display = np.transpose(image[0, :3], (1, 2, 0))
            image_for_display_resized = cv2.resize(image_for_display, (self.window_size, self.window_size))
            self.tkimage_left = ImageTk.PhotoImage(image=Image.fromarray(image_for_display_resized))
            self.canvas.itemconfig(self.canvas_image_left, image=self.tkimage_left)
    
    def get_pos(self, event):
        return (int(event.x * self.resolution / self.window_size), int(event.y * self.resolution / self.window_size))
    
    def L_press(self, event):
        self.last_pos = self.get_pos(event)
    
    def L_move(self, event):
        a = self.last_pos
        b = self.get_pos(event)
        width = 6
        img = Image.fromarray(self.mask[0, 0])
        draw = ImageDraw.Draw(img)
        draw.line([a, b], fill=0, width=width)
        draw.ellipse((b[0] - width // 2, b[1] - width // 2, b[0] + width // 2, b[1] + width // 2), fill=0)
        self.mask = np.array(img)[np.newaxis, np.newaxis, ...]
        self.display()
        self.last_pos = b
    
    def L_release(self, event):
        self.L_move(event)
        self.mask_history.append(self.mask)
    
    def R_press(self, event):
        self.last_pos = self.get_pos(event)
    
    def R_move(self, event):
        a = self.last_pos
        b = self.get_pos(event)
        self.mask = self.mask_history[-1].copy()
        self.mask[0, 0, max(min(a[1], b[1]), 0): max(a[1], b[1]), max(min(a[0], b[0]), 0): max(a[0], b[0])] = 0
        self.display()
    
    def R_release(self, event):
        self.R_move(event)
        self.mask_history.append(self.mask)
    
    def key_down(self, event):
        if event.keysym == 'z':
            if len(self.mask_history) > 1:
                self.mask_history.pop()
                self.mask = self.mask_history[-1]
                self.display()
    
    def key_up(self, event):
        if event.keysym in ['1', '2']:
            self.display(self.last_state)

if __name__ == "__main__":
    # 这里model不能用None,应当定义一个nn.Module对象并load参数用于修复,这里就不给出来model的定义了。
    app = App(model=None, window_size=256)
    app.mainloop()

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

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

相关文章

autodl 安装了多个conda虚拟环境 选择合适虚拟环境的语句

1.conda env list 列出所有虚拟环境 可以看到&#xff0c;我有两个虚拟环境&#xff0c;一个是joygen&#xff0c;一个是base conda activate base 或者 conda activate joygen 激活对应的环境。我选择激活 joygen 环境 然后就可以在joygen环境下进行操作了 base环境也是同理…

ansible-playbook 进阶 接上一章内容

1.异常中断 做法1&#xff1a;强制正常 编写 nginx 的 playbook 文件 01-zuofa .yml - hosts : web remote_user : root tasks : - name : create new user user : name nginx-test system yes uid 82 shell / sbin / nologin - name : test new user shell : gete…

趋势直线指标

趋势直线副图和主图指标&#xff0c;旨在通过技术分析工具帮助交易者识别市场趋势和潜在的买卖点。 副图指标&#xff1a;基于KDJ指标的交易策略 1. RSV值计算&#xff1a; - RSV&#xff08;未成熟随机值&#xff09;反映了当前收盘价在过去一段时间内的相对位置。通过计算当前…

基线配置管理:为什么它对网络稳定性至关重要

什么是基线配置&#xff08;Baseline Configuration&#xff09; 基线配置&#xff08;Baseline Configuration&#xff09;是经过批准的标准化主设置&#xff0c;代表所有设备应遵循的安全、合规且运行稳定的配置基准&#xff0c;可作为评估变更、偏差或未授权修改的参考基准…

Nest全栈到失业(一):Nest基础知识扫盲

Nest 是什么? 问你一个问题,node是不是把js拉出来浏览器环境运行了?当然,他使用了v8引擎加上自己的底层模块从而实现了,在外部编辑处理文件等;然后它使用很多方式来发送请求是吧,你知道的什么http.request 或 https.request; 我们浏览器中,使用AJAX以及封装AJAX和http的Axios…

摩尔线程S4000国产信创计算卡性能实战——Pytorch转译,多卡P2P通信与MUSA编程

简介 MTT S4000 是基于摩尔线程曲院 GPU 架构打造的全功能元计算卡&#xff0c;为千亿规模大语言模型的训练、微调和推理进行了定制优化&#xff0c;结合先进的图形渲染能力、视频编解码能力和超高清 8K HDR 显示能力&#xff0c;助力人工智能、图形渲染、多媒体、科学计算与物…

Tesseract OCR 安装与中文+英文识别实现

一、下载 https://digi.bib.uni-mannheim.de/tesseract/ 下载&#xff0c;尽量选择时间靠前的&#xff08;识别更好些&#xff09;。符合你的运行机&#xff08;我的是windows64&#xff09; 持续点击下一步安装&#xff0c;安装你认可的路径即可&#xff0c;没必要配置环境变…

Cypress + React + TypeScript

🧪 Cypress + React + TypeScript 组件测试全流程实战:从入门到自动化集成 在现代前端开发中,组件测试 是保障 UI 行为可靠性的重要手段。本文将通过一个 React 项目示例,实战演示如何结合 Cypress + React + TypeScript 实现从零配置到自动化集成的完整测试链路。 一、项…

第2期:APM32微控制器键盘PCB设计实战教程

第2期&#xff1a;APM32微控制器键盘PCB设计实战教程 一、APM32小系统介绍 使用apm32键盘小系统开源工程操作 APM32是一款与STM32兼容的微控制器&#xff0c;可以直接替代STM32进行使用。本教程基于之前开源的APM32小系统&#xff0c;链接将放在录播评论区中供大家参考。 1…

Docker-搭建MySQL主从复制与双主双从

Docker -- 搭建MySQL主从复制与双主双从 一、MySQL主从复制1.1 准备工作从 Harbor 私有仓库拉取镜像直接拉取镜像运行容器 1.2 配置主、从服务器1.3 创建主、从服务器1.4 启动主库&#xff0c;创建同步用户1.5 配置启动从库1.6 主从复制测试 二、MySQL双主双从2.1 创建网络2.2 …

canvas 实现全屏倾斜重复水印

​ 参考&#xff1a; html、js、canvas实现水印_html页面使用canvas绘制重复水印-CSDN博客 效果 ​​​​ 不求水印显示完全。 实现代码 <template><div class"watermark" ref"waterMark"></div></template><script lang&q…

vue3项目 前端文件下载的两种工具函数

1、Blob 流下载 Blob 表示不可变的原始数据的类文件对象&#xff0c;通常用于处理文件或大块二进制数据。 注意&#xff1a;js中还有一个二进制数据类型ArrayBuffer&#xff0c;它们的区别如下 Blob 可以位于磁盘、高速缓存内存和其他不可用的位置&#xff1b;ArrayBuffer 是存…

5.31 day33

知识点回顾&#xff1a; PyTorch和cuda的安装 查看显卡信息的命令行命令&#xff08;cmd中使用&#xff09; cuda的检查 简单神经网络的流程 数据预处理&#xff08;归一化、转换成张量&#xff09; 模型的定义 继承nn.Module类 定义每一个层 定义前向传播流程 定义损失函数和优…

HTML 计算网页的PPI

HTML 计算网页的PPI vscode上安装live server插件&#xff0c;可以实时看网页预览 有个疑问&#xff1a; 鸿蒙density是按照类别写死的吗&#xff0c;手机520dpi 折叠屏426dpi 平板360dpi <html lang"en" data - overlayscrollbars - initialize><header&…

MMR-Mamba:基于 Mamba 和空间频率信息融合的多模态 MRI 重建|文献速递-深度学习医疗AI最新文献

Title 题目 MMR-Mamba: Multi-modal MRI reconstruction with Mamba and spatial-frequency information fusion MMR-Mamba&#xff1a;基于 Mamba 和空间频率信息融合的多模态 MRI 重建 01 文献速递介绍 磁共振成像&#xff08;MRI&#xff09;因其无创、无辐射特性以及…

2.5/Q2,Charls最新文章解读

文章题目&#xff1a;Trajectories of depressive symptoms and risk of chronic liver disease: evidence from CHARLS DOI&#xff1a;10.1186/s12876-025-03943-7 中文标题&#xff1a;抑郁症状的轨迹和慢性肝病风险&#xff1a;来自 CHARLS 的证据 发表杂志&#xff1a;BM…

Unity QFramework 简介

目录 什么是MVC模式&#xff1f; QFramework 架构提供了 Model 的概念 QFramework 架构引入 Command 的方式 QFramework 架构引入 Event事件机制 四个层&#xff1a;表现层、系统层、数据层、工具层 委托和回调函数的关系 命令和事件的区别 工具篇 QFramework整体基于M…

C++ 日志系统实战第五步:日志器的设计

全是通俗易懂的讲解&#xff0c;如果你本节之前的知识都掌握清楚&#xff0c;那就速速来看我的项目笔记吧~ 本文项目代码编写收尾&#xff01; 日志器类 (Logger) 设计&#xff08;建造者模式&#xff09; 日志器主要用于和前端交互。当我们需要使用日志系统打印 log 时&…

性能测试-jmeter实战1

课程&#xff1a;B站大学 记录软件测试-性能测试学习历程、掌握前端性能测试、后端性能测试、服务端性能测试的你才是一个专业的软件测试工程师 性能测试-jmeter实战1 为什么需要性能测试呢&#xff1f;性能测试的作用&#xff1f;性能测试体系性能测试基础性能测试工具性能监控…

杏仁海棠花饼的学习日记第十四天CSS

一&#xff0c;前言 第二天&#xff0c;今天看CSS。 二&#xff0c;CSS简介及导入方式 CSS简介 CSS&#xff08;层叠样式表&#xff0c;Cascading Style Sheets&#xff09;是一种用于描述 HTML 或 XML&#xff08;包括 SVG、XHTML 等&#xff09;文档呈现效果的样式语言。…