首页 > 其他分享 >完整

完整

时间:2024-03-31 09:00:11浏览次数:13  
标签:canvas self width 完整 path root image

import tkinter as tk
from tkinter import filedialog, ttk
from PIL import Image, ImageTk
import requests
import base64
import os
import io
import random
import threading
import time


def encode_pil_to_base64(image):
    with io.BytesIO() as output_bytes:
        image.save(output_bytes, format="PNG")
        bytes_data = output_bytes.getvalue()
    return base64.b64encode(bytes_data).decode("utf-8")


def save_decoded_image(b64_image, folder_path, image_name):
    seq = 0
    output_path = os.path.join(folder_path, f"{image_name}.png")
    while os.path.exists(output_path):
        seq += 1
        output_path = os.path.join(folder_path, f"{image_name}({seq}).png")
    with open(output_path, 'wb') as image_file:
        image_file.write(base64.b64decode(b64_image))
    print(f"Image saved to: {output_path}")
    return output_path  # 返回保存的图片路径


class PhotoSketchGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("建筑效果图转彩色手绘")
        self.root.configure(bg='black')
        self.root.state('zoomed')
        self.folder_path = ''  # 初始化 folder_path
        self.timer_running = False  # 初始化计时器运行状态为False
        self.start_time = None  # 初始化计时器开始时间
        self.buttons_y = None  # 初始化按钮的y坐标
        self.setup_ui()

    def setup_ui(self):
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        self.canvas_width = screen_width * 0.4
        self.canvas_height = screen_height * 0.8
        self.left_canvas_x = screen_width * 0.25 - self.canvas_width / 2
        self.right_canvas_x = screen_width * 0.75 - self.canvas_width / 2
        self.setup_buttons_and_canvas()
        self.add_intro_labels()

    def setup_buttons_and_canvas(self):
        self.left_frame = tk.Canvas(self.root, width=self.canvas_width, height=self.canvas_height, bg='black',
                                    highlightthickness=0)
        self.left_frame.place(x=self.left_canvas_x, rely=0.5, anchor='w')
        self.left_frame.create_rectangle(2, 2, self.canvas_width - 2, self.canvas_height - 2, outline='white',
                                         dash=(5, 5))

        self.buttons_y = self.left_frame.winfo_y() + self.canvas_height + 95  # 在画布下方95像素处

        self.upload_btn = tk.Button(self.root, text="上传参考图", command=self.upload_image, bg='darkgrey', fg='white',
                                    font=('微软雅黑', 12))
        self.upload_btn.place(x=self.left_canvas_x, y=self.buttons_y, width=(self.canvas_width / 2 - 5), height=30,
                              anchor='nw')

        self.save_dir_btn = tk.Button(self.root, text="选择保存路径", command=self.select_save_folder, bg='darkgrey',
                                      fg='white', font=('微软雅黑', 12))
        self.save_dir_btn.place(x=self.left_canvas_x + self.canvas_width / 2 + 5, y=self.buttons_y,
                                width=(self.canvas_width / 2 - 5), height=30, anchor='nw')

        self.right_frame = tk.Canvas(self.root, width=self.canvas_width, height=self.canvas_height, bg='black',
                                     highlightthickness=0)
        self.right_frame.place(x=self.right_canvas_x, rely=0.5, anchor='w')
        self.right_frame.create_rectangle(2, 2, self.canvas_width - 2, self.canvas_height - 2, outline='white',
                                          dash=(5, 5))

    def add_intro_labels(self):
        intro_label1 = tk.Label(self.root, text="建筑效果图转彩色手绘", bg='black', fg='white',
                                font=('微软雅黑', 18, 'bold'))
        intro_label1.place(x=self.left_canvas_x, y=10)
        intro_label2 = tk.Label(self.root, text="使用介绍: 请在左侧框内上传一张建筑渲染图", bg='black', fg='white',
                                font=('微软雅黑', 10))
        intro_label2.place(x=self.left_canvas_x, y=45)

    def select_save_folder(self):
        folder_selected = filedialog.askdirectory()
        if folder_selected:
            self.folder_path = folder_selected
            print(f"Selected folder: {self.folder_path}")

    def start_timer(self):
        self.timer_running = True
        self.start_time = time.time()
        self.timer_label = tk.Label(self.root, text="生成时间:0秒", bg='black', fg='white', font=('微软雅黑', 10))
        self.timer_label.place(x=self.right_frame.winfo_x(), y=self.buttons_y, anchor='w')
        self.update_timer()

    def update_timer(self):
        if self.timer_running:
            elapsed_time = round(time.time() - self.start_time)
            self.timer_label.config(text=f"生成时间:{elapsed_time}秒")
            self.root.after(1000, self.update_timer)

    def stop_timer(self):
        self.timer_running = False
        elapsed_time = round(time.time() - self.start_time)
        self.timer_label.config(text=f"生成时间:{elapsed_time}秒")

    def upload_image(self):
        self.upload_btn.config(state='disabled')  # 禁用上传按钮以防止多次上传
        filepath = filedialog.askopenfilename()
        if filepath:
            self.start_timer()  # 开始计时
            self.display_image(filepath, self.left_frame, 'image_label', self.left_canvas_x)
            threading.Thread(target=self.call_api_for_sketch, args=(filepath,)).start()  # 在新线程中调用API

    def display_image(self, image_path, canvas, label_attr, canvas_x):
        img = Image.open(image_path)
        img.thumbnail((canvas.winfo_width(), canvas.winfo_height()))
        img_tk = ImageTk.PhotoImage(img)

        if hasattr(self, label_attr):
            getattr(self, label_attr).configure(image=img_tk)
            getattr(self, label_attr).image = img_tk
        else:
            label = tk.Label(self.root, image=img_tk, bg='black')
            setattr(self, label_attr, label)
            getattr(self, label_attr).image = img_tk
            label.place(x=canvas_x, rely=0.5, anchor='w')

        if label_attr == 'generated_image_label':
            self.stop_timer()

    def call_api_for_sketch(self, image_path):
        # 模拟一些处理时间
        time.sleep(1)
        with Image.open(image_path) as img:
            encoded_image = encode_pil_to_base64(img)
        data = {
            "prompt": "<lora:CWG_archisketch_v1:1>,Building,pre sketch,masterpiece,best quality,featuring markers,(3D:0.7)",
            "negative_prompt": "blurry, lower quality, glossy finish,insufficient contrast",
            "init_images": [encoded_image],
            "steps": 30,
            "width": img.width,
            "height": img.height,
            "seed": random.randint(1, 10000000),
            "alwayson_scripts": {
                "ControlNet": {
                    "args": [
                        {
                            "enabled": "true",
                            "pixel_perfect": "true",
                            "module": "canny",
                            "model": "control_v11p_sd15_canny_fp16 [b18e0966]",
                            "weight": 1,
                            "image": encoded_image
                        },
                        {
                            "enabled": "true",
                            "pixel_perfect": "true",
                            "module": "depth",
                            "model": "control_v11f1p_sd15_depth_fp16 [4b72d323]",
                            "weight": 1,
                            "image": encoded_image
                        }
                    ]
                }
            }
        }

        url = "http://127.0.0.1:7860/sdapi/v1/txt2img"
        response = requests.post(url, json=data)
        if response.status_code == 200:
            response_json = response.json()
            saved_image_path = save_decoded_image(response_json['images'][0], self.folder_path, "sketched_image")
            self.root.after(0, self.display_image, saved_image_path, self.right_frame, 'generated_image_label',
                            self.right_canvas_x)
            self.root.after(0, lambda: self.upload_btn.config(
                state='normal'))  # Re-enable the upload button after processing
        else:
            print("Failed to get response from API, status code:", response.status_code)
            self.root.after(0, lambda: self.upload_btn.config(
                state='normal'))  # Re-enable the upload button if the API call fails


if __name__ == "__main__":
    root = tk.Tk()
    app = PhotoSketchGUI(root)
    root.mainloop()

 

标签:canvas,self,width,完整,path,root,image
From: https://www.cnblogs.com/zly324/p/18106374

相关文章

  • C#实现窗体弹出的三种方式(附完整源码)
    C#实现窗体弹出的三种方式以下是C#实现窗体弹出的三种方式的完整源码:使用Show方法弹出窗体:usingSystem;usingSystem.Windows.Forms;namespaceWindowsFormsApp1{publicpartialclassForm1:Form{publicForm1(){......
  • 【STM32项目】基于STM32多传感器融合的新型智能导盲杖设计(完整工程资料源码)
    基于STM32多传感器融合的新型智能导盲杖设计演示效果基于stm32智能盲杖  前言:      目前,中国盲人数量已突破两千万大关,而城市盲道设计不合理、盲道被非法侵占等危害盲人出行安全的问题屡禁不止[1-3]。随着科技发展,智能盲杖不断涌现,但这些智能盲杖并不智能[4,5]......
  • 一行一行讲解深度学习代码(零)如何利用pytorch搭建一个完整的深度学习项目——深度学习
    本文适合没有基础的pytorch深度学习小白和python基础不太好的同学!!建议有基础的同学不要看~文章目录深度学习项目的大致结构(一)数据集加载1.功能2.工具(1)datasets(2)DataLoader(二)数据预处理1.功能2.工具(1)torchvision.transforms(2)Compose()3.实战(1)定义数据集(2)数据预处理......
  • sfc命令参数 扫描所有保护的系统文件的完整性,并使用正确的 Microsoft 版本替换 不正确
    sfc/?Microsoft(R)Windows(R)ResourceChecker6.0版版权所有(C)MicrosoftCorporation。保留所有权利。扫描所有保护的系统文件的完整性,并使用正确的Microsoft版本替换不正确的版本。SFC[/SCANNOW][/VERIFYONLY][/SCANFILE=<file>][/VERIFYFILE=<file>] ......
  • superset安装完整过程
    1.安装superset所需python依赖包wtforms_json、flask_compress、celery、flask_migrate、flask_talisman、flask_caching、sqlparse、bleach、markdown、numpy、pandas、parsedatetime、pathlib2、simplejson,humanize,python-geohash,polyline,geopy,cryptography,backoff,msgpack,pyarr......
  • DNS协议 是什么?说说DNS 完整的查询过程?
    一、是什么DNS(DomainNamesSystem),域名系统,是互联网一项服务,是进行域名和与之相对应的IP地址进行转换的服务器简单来讲,DNS相当于一个翻译官,负责将域名翻译成ip地址IP地址:一长串能够唯一地标记网络上的计算机的数字域名:是由一串用点分隔的名字组成的Internet上某一台计......
  • 【图论 | 数据结构】用链式前向星存图(保姆级教程,详细图解+完整代码)
    一、概述链式前向星是一种用于存储图的数据结构,特别适合于存储稀疏图,它可以有效地存储图的边和节点信息,以及边的权重。它的主要思想是将每个节点的所有出边存储在一起,通过数组的方式连接(类似静态数组实现链表)。这种方法的优点是存储空间小,查询速度快,尤其适合于处理大规模......
  • 前端下载超大文件的完整方案
    本文从前端方面出发实现浏览器下载大文件的功能。不考虑网络异常、关闭网页等原因造成传输中断的情况。分片下载采用串行方式(并行下载需要对切片计算hash,比对hash,丢失重传,合并chunks的时候需要按顺序合并等,很麻烦。对传输速度有追求的,并且在带宽允许的情况下可以做并行分片下载)。......
  • 完整的logback-spring.xml配置文件
    <?xmlversion="1.0"encoding="UTF-8"?><!--日志级别从低到高分为TRACE<DEBUG<INFO<WARN<ERROR<FATAL,如果设置为WARN,则低于WARN的信息都不会输出--><!--scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true--><!--scanPeriod:设置监......
  • Java版商城:Spring Cloud+SpringBoot b2b2c实现多商家入驻直播带货及 免 费 小程序商城
    随着互联网的快速发展,越来越多的企业开始注重数字化转型,以提升自身的竞争力和运营效率。在这个背景下,鸿鹄云商SAAS云产品应运而生,为企业提供了一种简单、高效、安全的数字化解决方案。鸿鹄云商SAAS云产品是一种基于云计算的软件服务,旨在帮助企业实现业务流程的自动化和优化。......