前言

前段时间,写了篇博客关于Python自制一款炫酷音乐播放器。有粉丝问我,音乐播放器为什么要用PyQt5,效果是不是比Tkinter赞?PyQt5真的可以实现这些炫酷的UI画面吗?之前没接触过PyQt5,能不能多分享一些这方面的开发案例?

今天就带大家,一起用Python的PyQt5开发一个有趣的自定义桌面动画挂件,看看实现的动画挂件效果!

下面,我们开始介绍这个自定义桌面动画挂件的制作过程。

直接跳到文末获取粉丝专属福利。

一、核心功能设计

总体来说,我们需要实现将自己喜欢的动态图gif或者视频转成一个桌面动画挂件,知识点主要包含了对GIF图/视频解析人像提取分割,PyQt5窗体设置,自定义挂件动画实现,ico图标生成,程序打包等。

拆解需求,大致可以整理出我们需要分为以下几步完成:

  1. 对gif或者视频进行逐帧解析,获取转换的图片,提取图像中人体区域,并对图片进行批量尺寸大小修改替换
  2. 初始化设置动画挂件窗体显示效果,窗体位置、大小等
  3. 桌面动画挂件功能实现,动画轮播、鼠标控制挂件位置拖动
  4. 挂件打包图标设置、打包配置

二、实现步骤

1. 解析提取,修改图片

GIF图解析:

Gif动态图资源大家可以根据自己的喜好,自己选择。博主就用之前写过的仙女蹦迪动态Gif来演示效果。

首先我们需要将Gif动态图按照每一帧进行解析 ,转换成图片格式。代码如下:

from PIL import Image  # 导入PIL的Image包
import os
gifFileName = "./demo.gif"  # 把gif图赋值给gifFileName
im = Image.open(gifFileName)  # 使用Image的open函数打开test.gif图像
pngDir = gifFileName[:-4]  # 倒着从gifFileName中的倒数第四个开始取字符(跳过.gif),赋值给pngDir,作为文件夹的名字
if not os.path.exists(pngDir):os.makedirs('./img')  # 用图片名创建一个文件夹,用来存放每帧图片,名字为pngDir的值try:while True:  # 死循环current = im.tell()  # 用tell函数保存当前帧图片,赋值给currentim.save(pngDir+'/'+str(current+1)+'.png')  # 调用save函数保存该帧图片im.seek(current+1)  # 调用seek函数获取下一帧图片,参数变为current帧图片+1# 这里再次进入循环,当为最后一帧图片时,seek会抛出异常,代码执行except
except EOFError:pass  # 最后一帧时,seek抛出异常,进入这里,pass跳过

这样就可以把动态Gif图转换成图片了,效果如下:


视频解析:

同理,对视频解析,也是按照每一帧进行解析,转换成图片格式。核心代码如下:

# 将视频按照每一帧转成图片png
import cv2
videoFileName = "./demo.mp4"  # 把视频路径赋值给videoFileName
pngDir = videoFileName[:-4]  # 倒着从gifFileName中的倒数第四个开始取字符(跳过.后缀),赋值给pngDir,作为文件夹的名字
if not os.path.exists(pngDir):os.makedirs(pngDir)  # 用图片名创建一个文件夹,用来存放每帧图片,名字为pngDir的值
# 视频处理 分割成一帧帧图片
cap = cv2.VideoCapture(videoFileName)
num = 1
while True:# 逐帧读取视频  按顺序保存到本地文件夹ret, frame = cap.read()if ret:cv2.imwrite(f"{pngDir}/{num}.png", frame)  # 保存一帧帧的图片num += 1else:break
cap.release()   # 释放资源

效果如下:

逐帧提取的图片已经拿到了,下面我们需要对这些图片中的人像进行分割提取。

人像分割:

我们调用的是百度开放的人体分析接口 – 百度AI开放平台链接。


这里面我们可以创建一个人像分割的应用,其中的API Key及Secret Key后面我们调用人脸识别检测接口时会用到。


我们可以看到官方提供的帮助文档,介绍地很详细。如何调用请求URL数据格式,向API服务地址使用POST发送请求,必须在URL中带上参数access_token,可通过后台的API Key和Secret Key生成。这里面的API Key和Secret Key就是我们上面提到的。

那我们如何获取空背景的人像图片呢?根据API文档,可以看到里面有个type属性设置为foreground 就可以提取空背景的人像图片。


人像分割的接口流程基本就已经清楚了,可以进行代码实现了。

# 保存图片
def save_base_image(img_str, filename):img_data = base64.b64decode(img_str)with open(filename, 'wb') as f:f.write(img_data)# 获取token
def get_token():host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + client_id + '&client_secret=' + client_secretrequest = urllib.request.Request(host)request.add_header('Content-Type', 'application/json; charset=UTF-8')response = urllib.request.urlopen(request)token_content = response.read()if token_content:token_info = json.loads(token_content)token_key = token_info['access_token']return token_key# 人像分割
def body_seg_fore(filename, resultfilename):request_url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_seg"# 二进制方式打开图片文件f = open(filename, 'rb')img = base64.b64encode(f.read())params = dict()params['image'] = imgparams['type'] = 'foreground'params = urllib.parse.urlencode(params).encode("utf-8")# params = json.dumps(params).encode('utf-8')access_token = get_token()request_url = request_url + "?access_token=" + access_tokenrequest = urllib.request.Request(url=request_url, data=params)request.add_header('Content-Type', 'application/x-www-form-urlencoded')response = urllib.request.urlopen(request)content = response.read()if content:# print(content)content = content.decode('utf-8')# print(content)data = json.loads(content)# print(data)img_str = data['foreground']save_base_image(img_str, resultfilename)

这样我们就可以根据图片,进行人像分割,提取出空背景的人像图。效果如下:



如果提取的人像图片大小不符合我们的要求,我们还可以对图片大小进行调整。

file_list = os.listdir("./image")  # 读取当前文件夹所有文件
# print(file_list)
n = len(file_list)
for i in range(n):s = str(file_list[i])if s[-4:] == ".png":  # 检查后缀src = os.path.join(os.path.abspath('./image/'), s)  # 原先的图片名字img = Image.open(src)new_img = img.resize((128, 128), Image.BILINEAR)new_img.save(src)

我们需要的空背景图片已经拿到了,接下来我们来实现桌面挂件功能。

2. 初始化动画挂件

# 窗体初始化
def windowinit(self):self.x = 1650self.y = 860self.setGeometry(self.x, self.y, 300, 300)self.setWindowTitle('My Gadgets')self.img_num = 1self.img_path = './image/{file}/{img}.png'.format(file=self.dis_file, img=str(self.img_num))self.lab = QLabel(self)self.qpixmap = QPixmap(self.img_path)self.lab.setPixmap(self.qpixmap)self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)self.setAutoFillBackground(False)self.setAttribute(Qt.WA_TranslucentBackground, True)self.show()def __init__(self):super(Gadgets, self).__init__()self.dis_file = "img1"self.windowinit()self.icon_quit()self.pos_first = self.pos()self.img_count = len(os.listdir('./image/{}'.format(self.dis_file)))

这样图片挂件就可以显示出来,效果如下:

现在的桌面挂件是静态显示,下面我们可以通过计时器进行挂件动画轮播显示。

3. 动画挂件功能实现

动画轮播:

self.timer = QTimer()
self.timer.timeout.connect(self.img_update)
self.timer.start(100)
def img_update(self):if self.img_num < self.img_count:self.img_num += 1else:self.img_num = 1self.img_path = './image/{file}/{img}.png'.format(file=self.dis_file, img=str(self.img_num))self.qpixmap = QPixmap(self.img_path)self.lab.setPixmap(self.qpixmap)

鼠标控制挂件位置拖动:

def mousePressEvent(self, QMouseEvent):if QMouseEvent.button() == Qt.LeftButton:self.pos_first = QMouseEvent.globalPos() - self.pos()QMouseEvent.accept()self.setCursor(QCursor(Qt.OpenHandCursor))def mouseMoveEvent(self, QMouseEvent):if Qt.LeftButton:self.move(QMouseEvent.globalPos() - self.pos_first)print(self.pos())self.x, self.y = self.pos().x, self.pos().yQMouseEvent.accept()def quit(self):self.close()sys.exit()

至此,自定义动画挂件功能已经实现完成,动画挂件效果如下:

4. 打包配置

前段时间有粉丝问我,Python能不能打包成exe?如何打包呢?今天就通过这个来一起介绍下。

Python常用的打包工具是第三方库Pyinstaller,首先需要安装下pyinstaller。

pip install Pyinstaller

接下来,我们需要打开命令窗口,切换到项目目录下再执行打包命令。

pyinstaller -F -i ./img.ico Qt_Gadgets.py

打包常用的参数如下:

  • -F 表示生成单个可执行文件

  • -w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!

  • -p 表示你自己自定义需要加载的类路径,一般情况下用不到

  • -i 表示可执行文件的图标

之前有小伙伴问我,打包的图标需要.ico后缀的图片,应该如何把普通图片转成图标格式.ico呢?Python当然可以帮你实现,今天就一起教给大家。核心代码如下:

import PythonMagick# 生成图标ico(png格式图片转成ico)
img = PythonMagick.Image('./image/img1/1.png')
# 这里要设置一下尺寸,不然会报ico尺寸异常错误
img.sample('128x128')
img.write('./img.ico')

图标得到了,下面我们就可以进行打包操作了。

打包完成之后,我们可以看见项目目录下会有生成的exe程序。

至此,整个自定义动画挂件就全部完成了,下面我们一起运行下exe看看动画挂件效果。

源码及数据已上传,关注文末公众号回复【源码】即可获取完整源码

Python往期精彩:

  • 见过仙女蹦迪吗?一起用python做个小仙女代码蹦迪视频

  • python自制一款炫酷音乐播放器,想听啥随便搜!

  • 斗地主老是输?一起用Python做个AI出牌器,豆子蹭蹭涨!

  • 桌面太单调?一起用Python做个自定义动画挂件,好玩又有趣!

  • 一起用Python做个车牌自动识别系统,好玩又实用!

  • 桌面太单调?一起用Python做个自定义动态壁纸,竟然还可以放视频!

  • 一起用Python做个自动化弹钢琴脚本,我竟然弹出了《天空之城》!
    往期精彩源码均可通过下方公众号获取

桌面太单调?一起用Python做个自定义动画挂件,好玩又有趣!相关推荐

  1. 一起用Python做个上课点名器,好玩又实用!

    前言 前段时间,用PyQt5写了几篇文章,关于Python自制一款炫酷音乐播放器.自定义动态壁纸.车牌自动识别系统.今天就继续给大家分享一个读者粉丝投稿的,关于上课点名的实战案例,一起来看看是如何实现 ...

  2. 一起用Python做个自动化短视频生成脚本,实现热门视频流水线生产!

    前言 前几天有粉丝和我说,最近在网上看到一些视频营销号一天能发布几百条短视频, 感觉都是批量生成的,能不能用Python做个自动化短视频生成脚本呢? 今天就带大家一起用Python做个自动化视频生成脚 ...

  3. 一起用python做个炫酷音乐播放器【V3.0含源码及打包exe】

    前言 熟悉的小伙伴都知道,前段时间写了一篇关于音乐播放器的文章–Python自制一款炫酷音乐播放器.不少小伙伴私信我,对播放器提了一些改进建议,对播放器的一些逻辑bug优化完善.今天音乐播放器3.0版 ...

  4. 小年到了,回家抢票太难,用Python做个脚本12306自动查票以及自动购票....

    今天就是小年了,听说还有人买不到票?不要慌,今天咱们来用Python做一个自动查票抢票的脚本,24小时抢票,谁抢的过你!源码包已打包文件夹获取方式:点击这里[ Python全套资料] 即可获取. 准备 ...

  5. 【含源码】用python做游戏有多简单好玩

    有很多同学问我还有其他什么小游戏吗,游戏是怎么做的,难不难.我就用两篇文章来介绍一下,如何使用Python做游戏. 兔子与灌 俄罗斯方块 休闲五子棋 走迷宫 推箱子 消消乐 超多小游戏玩转不停↓  更 ...

  6. python做flash帧动画_[练习]利用CSS steps 实现逐帧动画

    网页逐帧动画的实现方式 网页中的逐帧动画,大致可分为两大类的实现方式, 分别是使用JS控制,和单纯使用CSS实现,两者的优劣总体概括来说就是: JS动画可控性更强,但开销大,实现复杂. CSS动画实现 ...

  7. 七夕节特辑,浏览器桌面太无聊,为什么不做个挂件来陪自己呢?

    相信很多人都玩过QQ宠物吧,QQ宠物停运之后,说实话心里还是有点不舍的,所以一直有着自己制作一只桌面宠物的想法,现在先在浏览器中试着实现了一下,感觉还是挺有趣的,如果有人喜欢,后续还可以加入更多的操作 ...

  8. 斗地主老是输?一起用Python做个AI出牌器!

    前言 最近在网上看到一个有意思的开源项目,基于快手团队开发的开源AI斗地主--DouZero做的一个"成熟"的AI,项目开源地址[https://github.com/tianqi ...

  9. 斗地主老是输?一起用Python做个AI出牌器,欢乐豆蹭蹭涨

    前言 最近在网上看到一个有意思的开源项目,快手团队开发的开源AI斗地主--DouZero.今天我们就一起来学习制作一个基于DouZero的欢乐斗地主出牌器,看看AI是如何来帮助我们斗地主,赢欢乐豆,实 ...

最新文章

  1. etal斜体吗 参考文献_论文格式与论文参考文献格式
  2. 解吧源码解析重点看withWeight
  3. pytorch模型加载测试_使用Pytorch实现物体检测(Faster R-CNN)
  4. java调用静态方法原理_传智播客:Java学科08static关键字的概述和使用格式以及静态原理...
  5. 删除Linux下/tmp目录引起的不正常登录系统
  6. mysql安装显示3534_MySQL安装成功之后启动错误 3534、28000和简单使用
  7. 水彩手绘中华美食PNG素材,提高海报设计效率!
  8. centos7.3 kvm虚拟化全自动化部署(0915金测OK)
  9. java map 缓存数据_Map方式实现JAVA数据缓存
  10. 初中级前端开发工程师如何提升个人能力?
  11. 《OpenGL超级宝典第五版》Windows + VS2019配置
  12. Windows socket测试工具
  13. dbv连接mysql_mysql数据库版本控制dbv使用_MySQL
  14. 我的自定义Spring框架 | Spring核心功能结构
  15. 连线封面:2亿多支付宝用户选择的背后,一个数据与评分带来的「等级世界」
  16. CF1556E Equilibrium
  17. okhttp之自定义Interceptor:请求失败切换IP重试拦截器
  18. 【字符串处理函数】sprintf与snprintf
  19. php面试自我介绍结束语,面试自我介绍的结束语
  20. 提问的艺术 - 敏捷教练技巧

热门文章

  1. 基于ALOS PALSAR 和 Landsat(光学)数据 2010 年全球红树林基线图数据集(gee和官网都可以下载)
  2. Java--比较日期大小
  3. Android使用OpenGL ES 3.0实现随手指旋转3D立方体
  4. 「Suiteki」- 小米手环密钥获取工具的实现原理
  5. 剪切音乐的使用方法有哪些
  6. Print Spooler自动停止
  7. 1-丁基咪唑四氟硼酸盐([HC4im]BF4)|1-丁基-3-甲基咪唑四氟硼酸盐(BMI-BF4)|1-甲基3-丁基咪唑六氟磷酸盐([C4mim]PF6)
  8. ubuntu进入单用户模式
  9. 最新中文版Studio One6音乐制作DAW工具
  10. 猎人服务器注册满了怎么办,猎人手游一区爆满怎么进?一区爆满注册进入方法介绍[多图]...