首页 > 其他分享 >缺计时器

缺计时器

时间:2024-03-31 09:01:41浏览次数:23  
标签: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.setup_ui()


    # 类的其余定义...

    def select_save_folder(self):
        selected_folder_path = filedialog.askdirectory()
        if selected_folder_path:  # 检查是否选择了文件夹
            self.folder_path = selected_folder_path
            # 在文件夹选择后继续其他操作
    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 select_save_folder(self):
        folder_selected = filedialog.askdirectory()
        if folder_selected:  # 确保用户选择了一个文件夹
            self.folder_path = folder_selected
            print(f"Selected folder: {self.folder_path}")

    def upload_image(self):
        filepath = filedialog.askopenfilename()
        if filepath:
            # 这里可以添加更新左侧画布图片的代码
            print(f"Uploaded image: {filepath}")

    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))

        # 将按钮放置在左框下方,下移40像素
        buttons_y = self.left_frame.winfo_y() + self.canvas_height + 90  # 在画布下方15像素处,额外下移40像素

        # 上传参考图的按钮
        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=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=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 upload_image(self):
        self.upload_btn.config(state='disabled')  # Disable the button to prevent multiple uploads during processing
        filepath = filedialog.askopenfilename()
        if filepath:
            self.display_image(filepath, self.left_frame, 'image_label', self.left_canvas_x)
            threading.Thread(target=self.call_api_for_sketch, args=(filepath,)).start()

    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)
            # 重要:更新引用,防止新的PhotoImage对象被垃圾回收
            getattr(self, label_attr).image = img_tk
        else:
            # 如果标签属性不存在,创建一个新的标签并设置图片
            label = tk.Label(self.root, image=img_tk, bg='black')
            setattr(self, label_attr, label)
            # 保存PhotoImage对象的引用,防止被垃圾回收
            getattr(self, label_attr).image = img_tk
            label.place(x=canvas_x, rely=0.5, anchor='w')

    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/18106365

相关文章

  • .NET分布式Orleans - 4 - 计时器和提醒
    Timer是什么Timer是一种用于创建定期粒度行为的机制。与标准的.NETSystem.Threading.Timer类相似,Orleans的Timer允许在一段时间后执行特定的操作,或者在特定的时间间隔内重复执行操作。它在分布式系统中具有重要作用,特别是在处理需要周期性执行的任务时非常有用。Timer......
  • 轻盈高效:深入了解.NET中的ValueStopwatch计时器
     概述:ValueStopwatch是.NET中轻量级计时器,用于高性能时间测量。作为值类型,避免了装箱拆箱开销,内存占用小。通过简单的使用方法,轻松实现代码块执行时间测量,且相比Stopwatch更为高效。在.NET中,ValueStopwatch是一个轻量级的计时器类,用于测量代码块的执行时间。相较于System.Dia......
  • 计时器
    StopWatch类计时(误差在2ms以内)StopWatch可以测量一个间隔的已用时间,或跨多个间隔测量已用总时间。publicstaticvoidgetTime(){StopwatchstopWatch=newStopwatch();//初始化TimeSpants=stopWatch.Elapsed;//时间间隔stopWatch.Start();/......
  • 计时器工具
    思路制作一个计时器蓝图,放到关卡中实例化后使用关卡蓝图调用展示步骤1.计时器蓝图2.关卡蓝图调用......
  • 事件循环-同步异步-计时器精确问题
    消息队列的解释每个任务都有一个任务类型。同一个类型的任务必须在一个队列中。不同类型的任务可以分属于不同的队列中。在一次事件循环中,浏览器可以【根据实际情况】从不同的队列中取出任务执行。浏览器必须准备好一个微队列,微队列中的任务优先其他所有类型的任务。chrome......
  • Spring 工具:StopWatch 计时器
    工具类:org.springframework.util.StopWatch作用:记录方法执行耗时,统计每个方法的耗时占比所在模块:spring-core方法描述voidstart(StringtaskName)开始一个新的监测任务,可设置任务名称。记录当前时间和任务名称voidstop()结束当前监测任务。记录任务执行......
  • Cocos Creator 2.x之通用计时器
    一,代码核心1,CommonTimer.ts/***通用计时器*/import{CommonTimerModeType,ICommonTimerInfo}from"./CommomTimerDefine";exportdefaultclassCommonTimerMgrextendscc.Component{publicstaticinstance:CommonTimerMgr;privatetimerList:ICo......
  • 超时实现 select 计时器
     github.com\eclipse\[email protected]\token.go//WaitTimeoutimplementstheTokenWaitTimeoutmethod.func(b*baseToken)WaitTimeout(dtime.Duration)bool{  timer:=time.NewTimer(d)  select{  case<-b.complete:    if!tim......
  • Linux第五章 计时器和计时器服务
    #5.计时器和计时器服务本章介绍计时器和计时器服务。它解释了硬件定时器的原理和基于Intelx86的PC中的硬件定时器。它涵盖了CPU操作和中断处理。它描述了与计时器相关的系统调用、库函数和Linux计时器服务的命令。它讨论了进程间隔定时器、计时器生成信号,并通过示例演示了进程......
  • jquery 简单的计时器
    简单的计时器jQuery只显示当前的时分秒,以下代码直接运行即可只显示当前的时分秒,以下代码直接运行即可关键起作用的就是这个函数setInterval(),第二个参数1000代码1000毫秒,也就是1秒,调用一下函数f(),id为timer里面的内容就被替换为最新的时间<!DOCTYPEhtml><html><head> <t......