PySide6 项目开发

Prerequisite

在之前的博客(PyQt6 / PySide6)讲了基础,这篇博客就是项目实战的过程(人工智能 + PySide6)

项目参考:

基于人工智能的图片动漫化

项目地址:https://github.com/CourserLi/PyComic

目标功能:

  • AnimeGANv2 基础功能实现【✔】
  • 增加功能页面【✔】
    • 主页(无内容)
    • 功能介绍(介绍该模型)
    • 选择模型(说明 + 演示)
    • 图片动漫化(模型运行)
    • 电脑信息
    • 退出程序
    • 设置
      • 切换主题
      • 查看论文(跳转到论文页)
      • 查看项目(跳转到 Github 项目地址)
  • 功能整合
    • 改署名(包括名字、图标等)【✔】
    • 功能区分模块(参考1参考2)【×】
    • 打包【×】
      • 下载打包库:pip install pyinstaller
      • 一个 exe(但需要静态资源),缺点是启动慢 pyinstaller -F .\main.py
      • 一个 exe + 多个文件(依然需要静态资源),缺点是文件多 pyinstaller -D .\main.py

主要功能讲解

图片动漫化

功能使用:

① 点击选择模型
② 图片动漫化

有两种运行方式,分别是线程运行和套娃运行,需要在代码中修改:

# 测试功能:图片动漫化
...
# start_transform【高配置】和 python_comic【低配置】
widgets.btn_start.clicked.connect(self.start_transform) # self.python_comic

线程运行【高配置运行】
原理是利用 PySide 自带的线程,运行 AnimeGANv2 项目中的代码。众所周知,Python 的多线程和多进程本质都是,单线程快速转换线程(进程)以达到模仿多线程(进程)的效果,因此这种方法就是单线程运行

class ComicThread(QThread):
    def __init__(self, model, oropic_pic):
        super(ComicThread, self).__init__()
        self.model = model
        self.oropic_pic = oropic_pic
    
    def run(self):
        import sys
        sys.path.append(os.path.join(os.path.abspath('.'), 'AnimeGANv2'))
        from AnimeGANv2 import test
        # 是否要冻结路径
        checkpoint_dir = "./AnimeGANv2/checkpoint/" + self.model
        style_name = "./images/comic"
        # test_dir = "./images/oripic"
        sample_file = "./images/oripic/" + self.oropic_pic
        if_adjust_brightness = True
        test.test(checkpoint_dir, style_name, sample_file, if_adjust_brightness)

在函数中调用线程

def start_transform(self):
    """
    开始图片动漫化,转换后的图片的路径是 images/comic【适合高配置】
    """
    QMessageBox.information(self, "提示", "动漫化过程需要等待约半分钟", QMessageBox.Yes)
    self.comic_thread = ComicThread(self.model, self.oropic_pic)
    self.comic_thread.start()
    if self.comic_thread.isRunning():
        pass
        # self.comic_thread.terminate()
        # del self.comic_thread
    """
    显示动漫化图片,但期间不能进行其他操作,不建议使用【PASS】
    """
    # self.comic_thread.wait() # 等待线程跑完
    # label_comic = widgets.label_comic
    # url = "./images/comic/" + self.oropic_pic
    # pix = QPixmap(url).scaled(label_comic.size(), aspectMode=Qt.KeepAspectRatio)
    # label_comic.setPixmap(pix)
    # label_comic.repaint()

套娃运行【低配置运行】
原理是 Python 调用 bat 文件,bat 文件再调用另一个 python 文件,此 python 负责运行 AnimeGANv2 项目中的代码。这种方法就是真正的双线程运行,因为在程序调用完 bat 文件时,此接口就结束了,相当于断开了连接,一个线程分成了两个线程,对于电脑性能很难接受单线程急速运转的,可以采取这种方式

def python_comic(self):
    """
    调用 python 文件,该文件再调用 AnimeGANv2 项目【适合低配置】
    """
    import os
    QMessageBox.information(self, "提示", "动漫化过程需要等待约半分钟", QMessageBox.Yes)
    checkpoint_dir = "./AnimeGANv2/checkpoint/" + self.model
    style_name = "./images/comic"
    sample_file = "./images/oripic/" + self.oropic_pic
    if_adjust_brightness = True
    sys_argv = f" {checkpoint_dir} {style_name} {sample_file} {if_adjust_brightness}"
    os.system("comic.bat" + sys_argv)

系统监控

采用的不是线程运行,而是瞬时加载。说白了,就是提前用脚本运行得到数据,并存储在 JSON 文件中,PySide 运行时就可以直接调用 JSON 文件

from pprint import pprint
import psutil
import os
import sys
import platform
import subprocess
import re
import torch
import tensorflow as tf
import json

def runcmd(command):
    # 不显示输入内容 stdout=subprocess.PIPE, stderr=subprocess.PIPE
    # 编码方式 encoding="utf-8"
    ret = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    if ret.returncode == 0:
        return ("success:", ret)
    else:
        return ("error:", ret)

# 显卡信息
result = str(runcmd(["nvdebugdump", "--list"])[1]).split(f"\\r\\n\\t")[2]
pattern = re.compile(r"Device name:\s+(.+?)(?:\s+\(\*PrimaryCard\))?$")
try:
    Card_Information = re.search(pattern, result).group(1)
except Exception as e:
    Card_Information = str(None)

# 操作系统的名称及版本号
OS_Version = platform.platform()

# CUDA 版本
result = str(runcmd(["nvcc", "-V"])[1])
pattern = r"V\d+\.\d+\.\d+"
try:
    CUDA_Version = re.search(pattern, result).group(0)
except Exception as e:
    CUDA_Version = str(None)

# Python 版本
Python_Version = platform.python_version()

# pytorch 的版本
try:
    Pytorch_Version = torch.__version__
except Exception as e:
    Pytorch_Version = str(None)

# pytorch 是否可用 CUDA
try:
    Pytorch_CUDA = str(torch.cuda.is_available())
except Exception as e:
    Pytorch_CUDA = str(None)

# tensorflow 的版本
try:
    Tensorflow_Version = tf.__version__
except Exception as e:
    Tensorflow_Version = str(None)

# tensorflow 是否可用 CUDA
try:
    Test = tf.config.list_physical_devices('GPU')
    if "device_type='GPU'" in str(Test): Tensorflow_CUDA = str(True)
    else: Tensorflow_CUDA = str(False)
except Exception as e:
    Tensorflow_CUDA = str(None)

# 计算机的处理器架构
PC_Framework = platform.machine()

# 计算机的处理器信息
PC_Information = platform.processor()

# CPU 的逻辑数量
CPU_logic = str(psutil.cpu_count())

# CPU 的物理核心数量
CPU_core = str(psutil.cpu_count(logical=False))

# CPU 使用率
CPU_List = psutil.cpu_percent(interval=0.5, percpu=True)
CPU_Use = []
for i in range(len(CPU_List)):
    tmp = "CPU_" + str(i+1) + ": " + str(CPU_List[i]) + "%    "
    CPU_Use.append(tmp)
    if i == len(CPU_List)//2-1: CPU_Use.append("\n")
CPU_Use = "".join(CPU_Use)

# 内存使用情况
Memory_List = psutil.virtual_memory()
Memory = ["总内存: %.2f G" % (Memory_List.total/1024/1024/1024)]
Memory.append("已使用内存: %.2f G" % (Memory_List.used/1024/1024/1024))
Memory.append("未使用内存: %.2f G" % (Memory_List.free/1024/1024/1024))
Memory.append("内存使用率: " + str(Memory_List.percent) + "%")
Memory = ",   ".join(Memory)

data = {
    "Card_Information": Card_Information,
    "OS_Version": OS_Version,
    "CUDA_Version": CUDA_Version,
    "Python_Version": Python_Version,
    "Pytorch_Version": Pytorch_Version,
    "Pytorch_CUDA": Pytorch_CUDA,
    "Tensorflow_Version": Tensorflow_Version,
    "Tensorflow_CUDA": Tensorflow_CUDA,
    "PC_Framework": PC_Framework,
    "PC_Information": PC_Information,
    "CPU_logic": CPU_logic,
    "CPU_logic": CPU_logic,
    "CPU_core": CPU_core,
    "CPU_Use": CPU_Use,
    "Memory": Memory
}
posted @ 2023-04-14 09:27  筱团  阅读(1224)  评论(0编辑  收藏  举报