Рабочий стол слишком однообразен? Давайте воспользуемся Python, чтобы сделать собственный кулон с анимацией, это весело и интересно!

предисловие

Некоторое время назад я написал блог о классном музыкальном проигрывателе, сделанном на Python . Некоторые фанаты спрашивали меня, почему я использую PyQt5 для музыкальных плееров, эффект лучше, чем у Tkinter? Может ли PyQt5 действительно достичь этих крутых изображений пользовательского интерфейса? Я никогда раньше не контактировал с PyQt5, можете ли вы поделиться другими примерами разработки в этом отношении?

Сегодня я возьму вас всех, чтобы разработать интересную пользовательскую подвеску с анимацией для рабочего стола с помощью Python PyQt5 и увидеть эффект подвески с анимацией!
вставьте сюда описание изображения

Далее мы начинаем знакомить вас с процессом производства этого индивидуального анимационного кулона для рабочего стола.

Перейдите прямо к концу статьи , чтобы получить эксклюзивные преимущества для поклонников.

1. Дизайн основных функций

В общем, нам нужно преобразовать наш любимый динамический gif или видео в кулон с анимацией на рабочем столе.Точки знаний в основном включают анализ изображения / видео GIF , извлечение и сегментацию портрета , настройки формы PyQt5 , реализацию пользовательской подвесной анимации , создание значков ico , упаковку программ. , и т.д.

Требования к демонтажу можно грубо разобрать, и нам нужно разделить их на следующие шаги для выполнения:

  1. Проанализируйте gif или видео кадр за кадром, получите преобразованное изображение, извлеките область человеческого тела на изображении, а также измените и замените размер изображения в пакетном режиме.
  2. Инициализируйте и задайте эффект отображения формы анимационной подвески, положение и размер формы и т. д.
  3. Реализация функции подвески анимации рабочего стола, карусель анимации, перетаскивание положения подвески управления мышью
  4. Настройки значка упаковки подвески, конфигурация упаковки

2. Этапы реализации

1. Разбирать и извлекать, изменять картинки

Анализ 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()   # 释放资源

Эффект следующий:
вставьте сюда описание изображения
Получены кадр за кадром извлеченные картинки, и нам нужно сегментировать и извлечь портреты на этих картинках.

Портретная сегментация:

То, что мы называем открытым интерфейсом Baidu для анализа человеческого телаBaidu AI Open Platform Link .

вставьте сюда описание изображения
Здесь мы можем создать приложение портретной сегментации, в котором ключ API и секретный ключ будут использоваться позже, когда мы вызовем интерфейс обнаружения распознавания лиц.

вставьте сюда описание изображения
Мы можем увидеть официальную справочную документацию, которая очень подробная. Как вызвать формат данных URL-адреса запроса и отправить запрос на адрес службы API с помощью POST , параметр access_token должен быть включен в URL-адрес , который может быть сгенерирован API-ключом и секретным ключом в фоновом режиме. Ключ API и секретный ключ — это те, о которых мы упоминали выше.
вставьте сюда описание изображения
Так как же нам получить портретное изображение с пустым фоном? Согласно документации 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 запаковать в исполняемый файл? Как его упаковать? Давайте представим его вместе сегодня.

Обычно используемым инструментом упаковки для Python является сторонняя библиотека Pyinstaller.Во-первых, вам нужно установить pyinstaller.

pip install Pyinstaller

Далее нам нужно открыть командное окно, переключиться в директорию проекта и выполнить команду пакета.

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

Обычно используемые параметры упаковки следующие:

  • -F означает генерировать один исполняемый файл

  • -w означает удалить окно консоли, что очень полезно в графическом интерфейсе. Но если это программа командной строки, то удалите эту опцию!

  • -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:

Je suppose que tu aimes

Origine blog.csdn.net/hhladminhhl/article/details/119568090
conseillé
Classement