python 使用pyqt5绘制窗口界面,调用第三方接口实现人物动漫化

该文章演示了如何使用Python的PyQt5库和QtDesigner设计GUI,结合BaiduAI的接口实现人物照片转动漫化的功能。用户可以选择图片,通过一键转换按钮触发调用接口,将图片转换为动漫风格,然后保存结果。代码涵盖了窗口设计、图片上传、调用API以及保存图片的完整流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用到的技术:

  1. pyqt5
  2. Qt Designer

1、效果图

最终实现效果:
在这里插入图片描述

整体操作流程展示:

  1. 初始化启动页面:
    在这里插入图片描述

  2. 点击【上传照片】按钮:
    在这里插入图片描述

  3. 选择需要待转换的图片:
    在这里插入图片描述

  4. 点击【一键转换】按钮:

在这里插入图片描述

  1. 点击【保存】按钮:
    在这里插入图片描述

2、代码实现

窗口界面使用的是PyQt5,它是一个创建GUI应用程序的工具包。可以使用Qt Designer直接进行可视化图形化页面设计。然后导出为python文件或C++文件。

pyqt5官方指导文档:https://www.riverbankcomputing.com/static/Docs/PyQt5/

1. 窗口设计

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import QtGui, QtWidgets, QtCore
from thirdParty.baiduAi import *


class Ui_MainWindow(QWidget):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(690, 400)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")

        # 照片
        self.photo = QLabel(self.centralwidget)
        self.photo.setObjectName(u"photo")
        self.photo.setGeometry(QRect(50, 80, 221, 201))
        self.photo.setFixedSize(200, 200)
        self.photo.setText(u"照片")
        # 设置照片标签边框样式
        self.photo.setFrameShape(QtWidgets.QFrame.Box)
        # 设置阴影 据说只有加了这步才能设置边框颜色。///可选样式有Raised、Sunken、Plain(这个无法设置颜色)等
        self.photo.setFrameShadow(QtWidgets.QFrame.Raised)
        # 设置背景颜色,包括边框颜色
        # self.label.setStyleSheet()
        self.photo.setFrameShape(QFrame.Box)
        # 设置边框样式
        # 设置背景填充颜色'background-color: rgb(0, 0, 0)'
        # 设置边框颜色border-color: rgb(255, 170, 0);
        self.photo.setStyleSheet(
            'border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);background-color: rgb(100, 149, 237);')

        # 调整文字与边框的对齐,可以多试几个参数,比如AlignTop
        self.photo.setAlignment(Qt.AlignCenter)

        # 转换后的动漫头像
        self.avatar = QLabel(self.centralwidget)
        self.avatar.setObjectName(u"avatar")
        self.avatar.setGeometry(QRect(440, 80, 221, 201))
        self.avatar.setFixedSize(200, 200)
        self.avatar.setText(u"头像")

        # 设置头像标签边框样式
        self.avatar.setFrameShape(QtWidgets.QFrame.Box)
        # 设置阴影 据说只有加了这步才能设置边框颜色。///可选样式有Raised、Sunken、Plain(这个无法设置颜色)等
        self.avatar.setFrameShadow(QtWidgets.QFrame.Raised)
        # 设置背景颜色,包括边框颜色
        # self.label.setStyleSheet()
        self.avatar.setFrameShape(QFrame.Box)
        # 设置边框样式
        # 设置背景填充颜色'background-color: rgb(0, 0, 0)'
        # 设置边框颜色border-color: rgb(255, 170, 0);
        self.avatar.setStyleSheet(
            'border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);background-color: rgb(100, 149, 237);')
        self.avatar.setAlignment(Qt.AlignCenter)

        # 上传 按钮
        self.upload = QPushButton(self.centralwidget)
        self.upload.setObjectName(u"upload")
        self.upload.setGeometry(QRect(300, 120, 81, 26))
        self.upload.setAutoFillBackground(False)
        self.upload.setText(u"上传照片")
        self.upload.clicked.connect(self.uploadimage)

        # 一键转换 按钮
        self.transfer = QPushButton(self.centralwidget)
        self.transfer.setObjectName(u"transfer")
        self.transfer.setGeometry(QRect(300, 180, 81, 26))
        self.transfer.setAutoFillBackground(False)
        self.transfer.setText(u"一键转换")
        self.transfer.clicked.connect(self.transferimage)

        # 保存图片 按钮
        self.save = QPushButton(self.centralwidget)
        self.save.setObjectName(u"save")
        self.save.setGeometry(QRect(300, 240, 81, 26))
        self.save.setAutoFillBackground(False)
        self.save.setText(u"保存👉")
        self.save.clicked.connect(self.saveimage)

        # 其余菜单项配置
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")
        self.menubar.setGeometry(QRect(0, 0, 731, 21))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        QMetaObject.connectSlotsByName(MainWindow)

2. 调用第三方接口

第三方接口文档地址:http://ai.baidu.com/ai-doc/IMAGEPROCESS/Mk4i6olx5

注意点:此接口需要获取授权,获取到token后,将下面代码中的access_token值进行替换。获取授权方法在此接口文档中可以找到。

import json
import requests


def transferPhotoToAnamiation(img):
    '''
    人像动漫化
    img : base64编码格式的流,不包含图片头
    return:
        {
            "log_id":739539874,
            "image":base64str // 不带前缀
        }
    '''
    request_url = "https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime"
    # 二进制方式打开图片文件
    # f = open('[本地文件]', 'rb')
    # img = base64.b64encode(f.read())

    params = {"image": img}
    access_token = '[调用鉴权接口获取的token]'  # 需要进行替换
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/x-www-form-urlencoded'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        return response.json().get('image')

3. 上传图片方法

    def uploadimage(self):
        '''
        上传图片功能
        :return:
        '''
        imgName, imgType = QFileDialog.getOpenFileName(self, "打开图片", "", "*.jpg;;*.png;;All Files(*)")
        jpg = QtGui.QPixmap(imgName).scaled(self.photo.width(), self.photo.height())
        self.photo.setPixmap(jpg)

4. 调第三方接口实现图片转换方法

知识点:涉及到base64编码和QPixmap格式的互转
(因为调用的百度AI第三方接口入参/返参是base64编码格式;PyQt5的图片是QPixmap格式)

    def transferimage(self):
        '''
        照片转动漫形象
        :return:
        '''
        # 1. pixmap转base64
        device = QBuffer()
        assert device.open(QBuffer.ReadWrite)
        self.photo.pixmap().save(device, b'png')
        device.close()
        data = bytes(device.data())
        payload = base64.b64encode(data).decode("ascii")
        print("data:image/png;base64," + payload)
        # 2. 调用第三方接口
        avatarBase64Str = transferPhotoToAnamiation(payload)
        # 3. base64转pixmap,并给标签avatar赋值
        avatar = base64.b64decode(avatarBase64Str)  # 对处理好的base编码进行转换(不带前面的前缀)
        pix = QPixmap()
        pix.loadFromData(avatar)
        # 自适应label大小
        self.avatar.setScaledContents(True)
        self.avatar.setPixmap(pix)

5. 保存图片方法

    def saveimage(self):
        '''
        保存图片
        :return:
        '''
        fd, type = QFileDialog.getSaveFileName(self.centralwidget, "保存图片", "", "*.jpg;;*.png;;All Files(*)")
        self.avatar.pixmap().save(fd, "JPG", 100)

注意点
self.avatar.pixmap().save(fd, “JPG”, 100);
1.fd为图片文件的路径,需要注意的是路径必须要有权限读写,这里使用打开文件窗口后选定的路径作为保存路径;
2.“JPG"为图片的格式,注意不需要带”.";
3.100指的是图片的质量因数,范围必须在0到100之内或-1,指定0以获取小型压缩文件,指定100表示大型未压缩文件,使用-1(默认值)使用默认设置。

3、完整代码

文件位置:

– characterAnimation
|— design。 #窗口设计所在包
|----- init.py
|----- design.py # 放窗口设计、按钮功能代码
|— thirdParty # 调用第三方接口的包
|----- init.py
|----- baiduAi.py # 放窗口设计、按钮功能代码
|—main.py # 启动
|—venv

先导入依赖:
在终端执行:pip install -r requirements.txt
(导出项目依赖的方法:pip freeze > requirements.txt

certifi==2023.5.7
charset-normalizer==3.1.0
click==8.1.3
idna==3.4
PyQt5==5.15.9
pyqt5-plugins==5.15.9.2.3
PyQt5-Qt5==5.15.2
PyQt5-sip==12.12.1
pyqt5-tools==5.15.9.3.3
PySide2==5.15.2.1
python-dotenv==1.0.0
qt5-applications==5.15.2.2.3
qt5-tools==5.15.2.1.3
requests==2.31.0
shiboken2==5.15.2.1
urllib3==1.26.15

安装完依赖以后,Qt Designer的位置:venv/qt5_applications/Qt/bin
双击Designer
在这里插入图片描述

design.py:

# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'characterAnimationgdZItS.ui'
##
## Created by: Qt User Interface Compiler version 5.15.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
import base64

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import QtGui, QtWidgets, QtCore
from thirdParty.baiduAi import *


class Ui_MainWindow(QWidget):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(690, 400)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")

        # 照片
        self.photo = QLabel(self.centralwidget)
        self.photo.setObjectName(u"photo")
        self.photo.setGeometry(QRect(50, 80, 221, 201))
        self.photo.setFixedSize(200, 200)
        self.photo.setText(u"照片")
        # 设置照片标签边框样式
        self.photo.setFrameShape(QtWidgets.QFrame.Box)
        # 设置阴影 据说只有加了这步才能设置边框颜色。///可选样式有Raised、Sunken、Plain(这个无法设置颜色)等
        self.photo.setFrameShadow(QtWidgets.QFrame.Raised)
        # 设置背景颜色,包括边框颜色
        # self.label.setStyleSheet()
        self.photo.setFrameShape(QFrame.Box)
        # 设置边框样式
        # 设置背景填充颜色'background-color: rgb(0, 0, 0)'
        # 设置边框颜色border-color: rgb(255, 170, 0);
        self.photo.setStyleSheet(
            'border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);background-color: rgb(100, 149, 237);')

        # 调整文字与边框的对齐,可以多试几个参数,比如AlignTop
        self.photo.setAlignment(Qt.AlignCenter)

        # 转换后的动漫头像
        self.avatar = QLabel(self.centralwidget)
        self.avatar.setObjectName(u"avatar")
        self.avatar.setGeometry(QRect(440, 80, 221, 201))
        self.avatar.setFixedSize(200, 200)
        self.avatar.setText(u"头像")

        # 设置头像标签边框样式
        self.avatar.setFrameShape(QtWidgets.QFrame.Box)
        # 设置阴影 据说只有加了这步才能设置边框颜色。///可选样式有Raised、Sunken、Plain(这个无法设置颜色)等
        self.avatar.setFrameShadow(QtWidgets.QFrame.Raised)
        # 设置背景颜色,包括边框颜色
        # self.label.setStyleSheet()
        self.avatar.setFrameShape(QFrame.Box)
        # 设置边框样式
        # 设置背景填充颜色'background-color: rgb(0, 0, 0)'
        # 设置边框颜色border-color: rgb(255, 170, 0);
        self.avatar.setStyleSheet(
            'border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);background-color: rgb(100, 149, 237);')
        self.avatar.setAlignment(Qt.AlignCenter)

        # 上传 按钮
        self.upload = QPushButton(self.centralwidget)
        self.upload.setObjectName(u"upload")
        self.upload.setGeometry(QRect(300, 120, 81, 26))
        self.upload.setAutoFillBackground(False)
        self.upload.setText(u"上传照片")
        self.upload.clicked.connect(self.uploadimage)

        # 一键转换 按钮
        self.transfer = QPushButton(self.centralwidget)
        self.transfer.setObjectName(u"transfer")
        self.transfer.setGeometry(QRect(300, 180, 81, 26))
        self.transfer.setAutoFillBackground(False)
        self.transfer.setText(u"一键转换")
        self.transfer.clicked.connect(self.transferimage)

        # 保存图片 按钮
        self.save = QPushButton(self.centralwidget)
        self.save.setObjectName(u"save")
        self.save.setGeometry(QRect(300, 240, 81, 26))
        self.save.setAutoFillBackground(False)
        self.save.setText(u"保存👉")
        self.save.clicked.connect(self.saveimage)

        # 其余菜单项配置
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")
        self.menubar.setGeometry(QRect(0, 0, 731, 21))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        QMetaObject.connectSlotsByName(MainWindow)

    def uploadimage(self):
        '''
        上传图片功能
        :return:
        '''
        imgName, imgType = QFileDialog.getOpenFileName(self, "打开图片", "", "*.jpg;;*.png;;All Files(*)")
        jpg = QtGui.QPixmap(imgName).scaled(self.photo.width(), self.photo.height())
        self.photo.setPixmap(jpg)
        print(jpg, end="\n")

    def transferimage(self):
        '''
        照片转动漫形象
        :return:
        '''
        # 1. pixmap转base64
        device = QBuffer()
        assert device.open(QBuffer.ReadWrite)
        self.photo.pixmap().save(device, b'png')
        device.close()
        data = bytes(device.data())
        payload = base64.b64encode(data).decode("ascii")
        print("data:image/png;base64," + payload)
        # 2. 调用第三方接口
        avatarBase64Str = transferPhotoToAnamiation(payload)
        # 3. base64转pixmap,并给标签avatar赋值
        avatar = base64.b64decode(avatarBase64Str)  # 对处理好的base编码进行转换(不带前面的前缀)
        pix = QPixmap()
        pix.loadFromData(avatar)
        # 自适应label大小
        self.avatar.setScaledContents(True)
        self.avatar.setPixmap(pix)

    def saveimage(self):
        '''
        保存图片
        :return:
        '''
        fd, type = QFileDialog.getSaveFileName(self.centralwidget, "保存图片", "", "*.jpg;;*.png;;All Files(*)")
        self.avatar.pixmap().save(fd, "JPG", 100)

baiduAi.py:

import json
import requests


def transferPhotoToAnamiation(img):
    '''
    人像动漫化
    img : base64编码格式的流,不包含图片头
    return:
        {
            "log_id":739539874,
            "image":base64str // 不带前缀
        }
    '''
    request_url = "https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime"
    # 二进制方式打开图片文件
    # f = open('[本地文件]', 'rb')
    # img = base64.b64encode(f.read())

    params = {"image": img}
    access_token = '[调用鉴权接口获取的token]'  # 需要进行替换
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/x-www-form-urlencoded'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        return response.json().get('image')

main.py:

import sys

from PyQt5 import QtWidgets

from design.design import Ui_MainWindow

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()  # 创建窗体对象
    ui = Ui_MainWindow()  # 创建PyQt设计器的窗体对象
    ui.setupUi(MainWindow)  # 调用PyQt窗体的方法对象进行初始化设置
    MainWindow.setWindowTitle("人物动漫化")
    MainWindow.show()  # 显示窗体
    sys.exit(app.exec_())  # 程序关闭时退出进程

项目代码指路:https://download.csdn.net/download/qq_45722699/87856065

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值