前言
前段時間,寫了篇博客關于Python自制一款炫酷音樂播放器,有粉絲問我,音樂播放器為什么要用PyQt5,效果是不是比Tkinter贊?PyQt5真的可以實作這些炫酷的UI畫面嗎?之前沒接觸過PyQt5,能不能多分享一些這方面的開發案例?
今天就帶大家,一起用Python的PyQt5開發一個有趣的自定義桌面影片掛件,看看實作的影片掛件效果!

下面,我們開始介紹這個自定義桌面影片掛件的制作程序,
一、核心功能設計
總體來說,我們需要實作將自己喜歡的動態圖gif或者視頻轉成一個桌面影片掛件,知識點主要包含了對GIF圖/視頻決議,人像提取分割,PyQt5表單設定,自定義掛件影片實作,ico圖示生成,程式打包等,
拆解需求,大致可以整理出我們需要分為以下幾步完成:
- 對gif或者視頻進行逐幀決議,獲取轉換的圖片,提取影像中人體區域,并對圖片進行批量尺寸大小修改替換
- 初始化設定影片掛件表單顯示效果,表單位置、大小等
- 桌面影片掛件功能實作,影片輪播、滑鼠控制掛件位置拖動
- 掛件打包圖示設定、打包配置
二、實作步驟
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函式保存當前幀圖片,賦值給current
im.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 += 1
else:
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_secret
request = 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'] = img
params['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_token
request = 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 = 1650
self.y = 860
self.setGeometry(self.x, self.y, 300, 300)
self.setWindowTitle('My Gadgets')
self.img_num = 1
self.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 += 1
else:
self.img_num = 1
self.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().y
QMouseEvent.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看看影片掛件效果,

今天我們就到這里,明天繼續努力!

若本篇內容對您有所幫助,請三連點贊,關注,收藏支持下,
創作不易,白嫖不好,各位的支持和認可,就是我創作的最大動力,我們下篇文章見!
Dragon少年 | 文
如果本篇博客有任何錯誤,請批評指教,不勝感激 !
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/293365.html
標籤:python
