python 使用pyqt5绘制窗口界面,调用第三方接口实现人物动漫化
使用到的技术:
- pyqt5
- Qt Designer
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