利用PyQt5中QLabel组件实现亚克力磨砂效果

作者:之一Yo 时间:2023-12-13 18:33:04 

前言

Windows10 在 UWP 应用中支持亚克力画刷,可以在部件的底部绘制亚克力效果的背景图。下面我们使用 QLabel 来模拟这个磨砂过程。

实现方法

MSDN 文档中介绍了亚克力材料的配方,包括:高斯模糊、亮度混合、色调混合和噪声纹理。

利用PyQt5中QLabel组件实现亚克力磨砂效果

高斯模糊

我们先来实现高斯模糊的效果,使用 scipy 可以很轻松的实现这个过程:

# coding:utf-8
import numpy as np
from PIL import Image
from PyQt5.QtGui import QPixmap
from scipy.ndimage.filters import gaussian_filter

def gaussianBlur(imagePath: str, blurRadius=18, brightFactor=1, blurPicSize: tuple = None) -> np.ndarray:
   """ 对图片进行高斯模糊处理

Parameters
   ----------
   imagePath: str
       图片路径

blurRadius: int
       模糊半径

brightFactor:float
       亮度缩放因子

blurPicSize: tuple
       高斯模糊前将图片缩放到指定大小,可以加快模糊速度

Returns
   -------
   image: `~np.ndarray` of shape `(w, h, c)`
       高斯模糊后的图像
   """
   if not imagePath.startswith(':'):
       image = Image.open(imagePath)
   else:
       image = Image.fromqpixmap(QPixmap(imagePath))

if blurPicSize:
       # 调整图片尺寸,减小计算量,还能增加额外的模糊
       w, h = image.size
       ratio = min(blurPicSize[0] / w, blurPicSize[1] / h)
       w_, h_ = w * ratio, h * ratio

if w_ < w:
           image = image.resize((int(w_), int(h_)), Image.ANTIALIAS)

image = np.array(image)

# 处理图像是灰度图的情况
   if len(image.shape) == 2:
       image = np.stack([image, image, image], axis=-1)

# 对每一个颜色通道分别磨砂
   for i in range(3):
       image[:, :, i] = gaussian_filter(
           image[:, :, i], blurRadius) * brightFactor

return image

亚克力纹理

接下来在 QLabel 上面绘制出亮度混合、色调混合和噪声纹理,一般色调混合使用的颜色是图像的主题色,可以用 colorthief 库提取,这里就不赘述了:

class AcrylicTextureLabel(QLabel):
   """ 亚克力纹理标签 """

def __init__(self, tintColor: QColor, luminosityColor: QColor, noiseOpacity=0.03, parent=None):
       """
       Parameters
       ----------
       tintColor: QColor
           RGB 主色调

luminosityColor: QColor
           亮度层颜色

noiseOpacity: float
           噪声层透明度

parent:
           父级窗口
       """
       super().__init__(parent=parent)
       self.tintColor = QColor(tintColor)
       self.luminosityColor = QColor(luminosityColor)
       self.noiseOpacity = noiseOpacity
       self.noiseImage = QImage('resource/noise.png')
       self.setAttribute(Qt.WA_TranslucentBackground)

def setTintColor(self, color: QColor):
       """ 设置主色调 """
       self.tintColor = color
       self.update()

def paintEvent(self, e):
       """ 绘制亚克力纹理 """
       acrylicTexture = QImage(64, 64, QImage.Format_ARGB32_Premultiplied)

# 绘制亮度层
       acrylicTexture.fill(self.luminosityColor)

# 绘制主色调
       painter = QPainter(acrylicTexture)
       painter.fillRect(acrylicTexture.rect(), self.tintColor)

# 绘制噪声
       painter.setOpacity(self.noiseOpacity)
       painter.drawImage(acrylicTexture.rect(), self.noiseImage)

acrylicBrush = QBrush(acrylicTexture)
       painter = QPainter(self)
       painter.fillRect(self.rect(), acrylicBrush)

用到的噪声图像如下图所示:

利用PyQt5中QLabel组件实现亚克力磨砂效果

亚克力标签

最后在 QLabel 上叠加磨砂图像和亚克力纹理,可以通过 Image.toqpixmap() 将 Image 转换为 QPixmap

class AcrylicLabel(QLabel):
   """ 亚克力标签 """

def __init__(self, blurRadius: int, tintColor: QColor, luminosityColor=QColor(255, 255, 255, 0),
                maxBlurSize: tuple = None, parent=None):
       """
       Parameters
       ----------
       blurRadius: int
           磨砂半径

tintColor: QColor
           主色调

luminosityColor: QColor
           亮度层颜色

maxBlurSize: tuple
           最大磨砂尺寸,越小磨砂速度越快

parent:
           父级窗口
       """
       super().__init__(parent=parent)
       self.imagePath = ''
       self.blurPixmap = QPixmap()
       self.blurRadius = blurRadius
       self.maxBlurSize = maxBlurSize
       self.acrylicTextureLabel = AcrylicTextureLabel(
           tintColor, luminosityColor, parent=self)

def setImage(self, imagePath: str):
       """ 设置图片 """
       if imagePath == self.imagePath:
           return

self.imagePath = imagePath
       image = Image.fromarray(gaussianBlur(
           imagePath, self.blurRadius, 0.85, self.maxBlurSize))
       self.blurPixmap = image.toqpixmap()  # type:QPixmap
       self.setPixmap(self.blurPixmap)
       self.adjustSize()

def setTintColor(self, color: QColor):
       """ 设置主色调 """
       self.acrylicTextureLabel.setTintColor(color)

def resizeEvent(self, e):
       super().resizeEvent(e)
       self.acrylicTextureLabel.resize(self.size())
       self.setPixmap(self.blurPixmap.scaled(
           self.size(), Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation))

测试

下面是测试用的埃罗芒阿老师:

利用PyQt5中QLabel组件实现亚克力磨砂效果

代码如下:

# coding:utf-8
import sys

from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QApplication

from acrylic import AcrylicLabel

app = QApplication(sys.argv)
w = AcrylicLabel(20, QColor(105, 114, 168, 102))
w.setImage('resource/ClariS_ヒトリゴト (アニメ盤).jpg')
w.show()
app.exec_()

结果如下:

利用PyQt5中QLabel组件实现亚克力磨砂效果

来源:https://www.cnblogs.com/zhiyiYo/p/15768440.html

标签:PyQt5,QLabel,磨砂
0
投稿

猜你喜欢

  • 使用正则表达式匹配tsql注释语句

    2024-01-18 16:42:50
  • Python读取本地文件并解析网页元素的方法

    2022-01-10 08:06:27
  • asp如何从数据库中删除废旧的电子信箱地址?

    2009-11-15 20:04:00
  • Go语言计算两个经度和纬度之间距离的方法

    2024-04-29 13:06:04
  • MySQL在Linux系统中隐藏命令行中的密码的方法

    2024-01-20 03:38:34
  • Python 实现OpenCV格式和PIL.Image格式互转

    2021-08-03 03:41:42
  • MySQL实现字符串的拼接,截取,替换,查找位置的操作

    2024-01-13 13:17:22
  • Python反爬虫伪装浏览器进行爬虫

    2023-07-05 22:33:38
  • 如何用Python破解wifi密码过程详解

    2021-06-03 05:32:38
  • 使用豆瓣提供的国内pypi源 <font color=red>原创</font>

    2023-05-31 20:39:09
  • Python中if语句的基本格式实例代码

    2023-12-02 14:31:20
  • 如何设置PyCharm中的Python代码模版(推荐)

    2022-12-14 03:56:29
  • Python中反转二维数组的行和列问题

    2021-06-24 13:48:27
  • python实现给微信公众号发送消息的方法

    2021-08-25 23:44:57
  • python3 字符串str和bytes相互转换

    2023-03-31 09:12:47
  • 详解css定位与定位应用

    2007-05-11 16:52:00
  • Python抓取今日头条街拍图片数据

    2021-11-03 12:30:57
  • php将ppt转jpg图片的具体步骤代码

    2023-06-12 21:53:33
  • 显示某日期所在星期的所有日期asp代码

    2008-06-01 16:05:00
  • sqlserver exists,not exists的用法

    2024-01-22 02:13:26
  • asp之家 网络编程 m.aspxhome.com