Python+PyQT5实现手绘图片生成器
作者:Python 发布时间:2022-03-11 11:57:21
标签:Python,PyQT5,图片
手绘图片生成器可以将导入的彩色图片通过python分析光源、灰度等操作生成手绘图片。
UI界面的整体部分代码块,UI界面的设计比较简单。效果在上面的图片展示。
class HandImage(QWidget):
def __init__(self):
super(HandImage, self).__init__()
self.init_ui()
def init_ui(self):
'''
UI界面组件及布局
:return:
'''
self.setWindowTitle('手绘图片生成器 公众号:[Python 集中营]')
self.setWindowIcon(QIcon('手绘图标.ico'))
self.setFixedWidth(500)
self.sou_im_path = QLineEdit()
self.sou_im_path.setReadOnly(True)
self.sou_im_path_btn = QPushButton()
self.sou_im_path_btn.setText('源图片')
self.sou_im_path_btn.clicked.connect(self.sou_im_path_btn_clk)
self.dir_path = QLineEdit()
self.dir_path.setReadOnly(True)
self.dir_path_btn = QPushButton()
self.dir_path_btn.setText('存储')
self.dir_path_btn.clicked.connect(self.dir_path_btn_clk)
self.start_btn = QPushButton()
self.start_btn.setText('开始绘制图像')
self.start_btn.clicked.connect(self.start_btn_clk)
grid = QGridLayout()
grid.addWidget(self.sou_im_path, 0, 0, 1, 1)
grid.addWidget(self.sou_im_path_btn, 0, 1, 1, 1)
grid.addWidget(self.dir_path, 1, 0, 1, 1)
grid.addWidget(self.dir_path_btn, 1, 1, 1, 1)
grid.addWidget(self.start_btn, 2, 0, 1, 2)
self.thread_ = WorkThread(self)
self.thread_.finished.connect(self.finished)
self.setLayout(grid)
# UI界面上的槽函数
def sou_im_path_btn_clk(self):
'''
选择源图片并设置路径
:return:
'''
im_path = QFileDialog.getOpenFileName(self, os.getcwd(), '打开图片', 'Image File(*.jpg);;Image File(*.png)')
self.sou_im_path.setText(im_path[0])
def dir_path_btn_clk(self):
'''
选择存储路径并设置路径
:return:
'''
dir_path = QFileDialog.getExistingDirectory(self, os.getcwd(), '选择路径')
self.dir_path.setText(dir_path)
def start_btn_clk(self):
'''
开始按钮绑定的槽函数
:return:
'''
self.start_btn.setEnabled(False)
self.thread_.start()
def finished(self, finished):
'''
用于子线程传递完成信号的槽函数
:param finished: 信号变量
:return:
'''
if finished is True:
self.start_btn.setEnabled(True)
其中绘图用到的第三方库只有两个,主要的还是Pillow图像处理库,还有就是numpy科学计算库用于一些数组计算等的操作。
将第三方的处理库导入到代码块中
from PIL import Image # 图像处理模块
import numpy as np # 科学计算库
# PyQt5界面制作及样式、核心组件
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
# 应用基础操作相关
import sys
import os
创建用于专门手绘图像的子线程类,将UI界面的处理逻辑和生成图像的处理逻辑分开不至于产生无响应的卡死状态。
class WorkThread(QThread):
finished = pyqtSignal(bool)
def __init__(self, parent=None):
super(WorkThread, self).__init__(parent)
self.parent = parent
self.working = True
def __del__(self):
self.working = False
self.wait()
def run(self):
# 源图片路径
sou_im_path = self.parent.sou_im_path.text().strip()
# 存储路径
dir_path = self.parent.dir_path.text().strip()
if sou_im_path == '' or dir_path == '':
self.finished.emit(True)
return
# 打开需要进行转的图像,并进行参数设置,取出来的参数主要图像的一些梯度值。最后进行数组保存。
vals = np.asarray(Image.open(sou_im_path).convert('L')).astype('float')
'''图像参数处理'''
depth = 12.0 # 设置初始化深度
gray_vals = np.gradient(vals) # 提取图像灰度的梯度值
gray_x, gray_y = gray_vals # 单独提取横坐标与纵坐标的灰度值
print('当前横坐标的灰度值:', gray_x)
print('当前纵坐标的灰度值:', gray_y)
# 重新设置横坐标合纵坐标的灰度值
gray_x = gray_x * depth / 100.0
gray_y = gray_y * depth / 100.0
# 根据numpy.sqrt()函数计算横坐标和纵坐标灰度值的平方根
gray_sqrt = np.sqrt(gray_x ** 2 + gray_y ** 2 + 1.0)
# 重新计算X轴、Y轴、Z轴的光源
light_x = gray_x / gray_sqrt
light_y = gray_y / gray_sqrt
light_z = 1.0 / gray_sqrt
# 计算光源的方位角度、俯视角度
agnle_el = np.pi / 2.2 # 俯视角度
agnle_az = np.pi / 4. # 方位角度
# 分别计算光源对X轴、Y轴、Z轴的影响
dx = np.cos(agnle_el) * np.cos(agnle_az) # 光源对x 轴的影响
dy = np.cos(agnle_el) * np.sin(agnle_az) # 光源对y 轴的影响
dz = np.sin(agnle_el) # 光源对z 轴的影响
# 设置光源归一化处理
light = 255 * (dx * light_x + dy * light_y + dz * light_z)
light = light.clip(0, 255)
# 重新构建图像
image = Image.fromarray(light.astype('uint8'))
image.save(dir_path + '/手绘图像.jpg')
self.finished.emit(True)
print('手绘图像绘制完成!')
主要代码块实现都在上面了,下面将展示完整的代码
完整代码
# -*- coding:utf-8 -*-
# @author Python 集中营
# @date 2022/2/10
# @file test2.py
# done
# 手绘图片生成器:以雪容融为例一键生成...
# 手绘图片生成器可以将导入的彩色图片通过python分析光源、灰度等操作生成手绘图片。
# 其中绘图用到的第三方库只有两个,主要的还是Pillow图像处理库,还有就是numpy科学计算库用于一些数组计算等的操作。
# 将第三方的处理库导入到代码块中
from PIL import Image # 图像处理模块
import numpy as np # 科学计算库
# PyQt5界面制作及样式、核心组件
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
# 应用基础操作相关
import sys
import os
# 创建用于专门手绘图像的子线程类,将UI界面的处理逻辑和生成图像的处理逻辑分开不至于产生无响应的卡死状态。
class WorkThread(QThread):
finished = pyqtSignal(bool)
def __init__(self, parent=None):
super(WorkThread, self).__init__(parent)
self.parent = parent
self.working = True
def __del__(self):
self.working = False
self.wait()
def run(self):
# 源图片路径
sou_im_path = self.parent.sou_im_path.text().strip()
# 存储路径
dir_path = self.parent.dir_path.text().strip()
if sou_im_path == '' or dir_path == '':
self.finished.emit(True)
return
# 打开需要进行转的图像,并进行参数设置,取出来的参数主要图像的一些梯度值。最后进行数组保存。
vals = np.asarray(Image.open(sou_im_path).convert('L')).astype('float')
'''图像参数处理'''
depth = 12.0 # 设置初始化深度
gray_vals = np.gradient(vals) # 提取图像灰度的梯度值
gray_x, gray_y = gray_vals # 单独提取横坐标与纵坐标的灰度值
print('当前横坐标的灰度值:', gray_x)
print('当前纵坐标的灰度值:', gray_y)
# 重新设置横坐标合纵坐标的灰度值
gray_x = gray_x * depth / 100.0
gray_y = gray_y * depth / 100.0
# 根据numpy.sqrt()函数计算横坐标和纵坐标灰度值的平方根
gray_sqrt = np.sqrt(gray_x ** 2 + gray_y ** 2 + 1.0)
# 重新计算X轴、Y轴、Z轴的光源
light_x = gray_x / gray_sqrt
light_y = gray_y / gray_sqrt
light_z = 1.0 / gray_sqrt
# 计算光源的方位角度、俯视角度
agnle_el = np.pi / 2.2 # 俯视角度
agnle_az = np.pi / 4. # 方位角度
# 分别计算光源对X轴、Y轴、Z轴的影响
dx = np.cos(agnle_el) * np.cos(agnle_az) # 光源对x 轴的影响
dy = np.cos(agnle_el) * np.sin(agnle_az) # 光源对y 轴的影响
dz = np.sin(agnle_el) # 光源对z 轴的影响
# 设置光源归一化处理
light = 255 * (dx * light_x + dy * light_y + dz * light_z)
light = light.clip(0, 255)
# 重新构建图像
image = Image.fromarray(light.astype('uint8'))
image.save(dir_path + '/手绘图像.jpg')
self.finished.emit(True)
print('手绘图像绘制完成!')
# UI界面的整体部分代码块,UI界面的设计比较简单。效果在下面的图片展示。
class HandImage(QWidget):
def __init__(self):
super(HandImage, self).__init__()
self.init_ui()
def init_ui(self):
'''
UI界面组件及布局
:return:
'''
self.setWindowTitle('手绘图片生成器 公众号:[Python 集中营]')
self.setWindowIcon(QIcon('手绘图标.ico'))
self.setFixedWidth(500)
self.sou_im_path = QLineEdit()
self.sou_im_path.setReadOnly(True)
self.sou_im_path_btn = QPushButton()
self.sou_im_path_btn.setText('源图片')
self.sou_im_path_btn.clicked.connect(self.sou_im_path_btn_clk)
self.dir_path = QLineEdit()
self.dir_path.setReadOnly(True)
self.dir_path_btn = QPushButton()
self.dir_path_btn.setText('存储')
self.dir_path_btn.clicked.connect(self.dir_path_btn_clk)
self.start_btn = QPushButton()
self.start_btn.setText('开始绘制图像')
self.start_btn.clicked.connect(self.start_btn_clk)
grid = QGridLayout()
grid.addWidget(self.sou_im_path, 0, 0, 1, 1)
grid.addWidget(self.sou_im_path_btn, 0, 1, 1, 1)
grid.addWidget(self.dir_path, 1, 0, 1, 1)
grid.addWidget(self.dir_path_btn, 1, 1, 1, 1)
grid.addWidget(self.start_btn, 2, 0, 1, 2)
self.thread_ = WorkThread(self)
self.thread_.finished.connect(self.finished)
self.setLayout(grid)
# UI界面上的槽函数
def sou_im_path_btn_clk(self):
'''
选择源图片并设置路径
:return:
'''
im_path = QFileDialog.getOpenFileName(self, os.getcwd(), '打开图片', 'Image File(*.jpg);;Image File(*.png)')
self.sou_im_path.setText(im_path[0])
def dir_path_btn_clk(self):
'''
选择存储路径并设置路径
:return:
'''
dir_path = QFileDialog.getExistingDirectory(self, os.getcwd(), '选择路径')
self.dir_path.setText(dir_path)
def start_btn_clk(self):
'''
开始按钮绑定的槽函数
:return:
'''
self.start_btn.setEnabled(False)
self.thread_.start()
def finished(self, finished):
'''
用于子线程传递完成信号的槽函数
:param finished: 信号变量
:return:
'''
if finished is True:
self.start_btn.setEnabled(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = HandImage()
main.show()
sys.exit(app.exec_())
来源:https://www.cnblogs.com/lwsbc/p/15884774.html
0
投稿
猜你喜欢
- modf()方法返回两个项的元组x的整数小数部分。这两个元组具有相同x符号。则返回一个浮点数的整数部分。语法以下是modf()方
- Python 通过微信邮件实现电脑关机,供大家参考,具体内容如下通过手机微信发送QQ邮件给sina邮箱,然后利用python的pop3定时检
- 这段时间微信跳一跳这个游戏非常火爆,但是上分又非常的难,对于程序员来说第一个念头就是通过写一个辅助脚本 * 让上分变的容易,python现在比
- 关键字:js验证表单大全,用JS控制表单提交 ,javascript提交表单:目录:1:js 字符串长度限制、判断字符长度 、js限制输入、
- 本文实例讲述了Python多线程结合队列下载百度音乐的方法。分享给大家供大家参考。具体如下:一直想做个下载音乐的脚本,后来决定就拿百度音乐开
- CSS网页布局应该避免滥用div元素一直是我们倡导的,以合适的HTML标签组织文档是CSS网页布局的基础。页面中div与span元素的使用是
- delete这个操作符呢,在javascript中不是很常用,但是他的特性的确很诡异。1,删除对象的属性,代码:var o = { 
- 使用Qt Creator创建默认的窗体程序后,主窗口QMainWindow有statusBar状态栏,在此状态栏实时显示时间可以使用下面方法
- 一、效果快放10倍总共分为三部分,左上角的正文,下方的心形和右下角的署名特别需要注意的一点是这种东西不但要装Python,还与分辨率有关(换
- 复制 复制是从一个MySQL服务器(master)将数据拷贝到另外一台或多台MySQL服务器
- 线性逻辑回归本文用代码实现怎么利用sklearn来进行线性逻辑回归的计算,下面先来看看用到的数据。这是有两行特征的数据,然后第三行是数据的标
- 使用Python的内置方法dir,可以范围一个模块中定义的名字的列表。官方解释是:Docstring:dir([object]) ->
- 目录01 — Pytest核心功能02 — 创建测试项目03 — 编写测试用例04 — 执行测试用例05 — 数据与脚本分离06 — 参数化
- 摘要: 简介 asyncio可以实现单线程并发IO操作,是Python中常用的异步处理模块。关于asyncio模块的介绍,笔者会在后续的文章
- MyISAM和MEMORY采用表级锁(table-level locking)BDB采用页面锁(page-leve locking)或表级锁
- // 去掉字符串的头空格(左空格) function LTrim(str){ var i; for(i=0;i<str.length;
- 本文实例讲述了PHP日志LOG类定义与用法。分享给大家供大家参考,具体如下:<?php/*** PHP log 类 */class C
- Array可以使用下标,Map和Set不能使用下标,ES6引入了iterable类型,Array,Map,Set都属于iterable类型,
- //定义编码header( 'Content-Type:text/html;charset=utf-8 ');//Atomh
- 如下所示:>>> import numpy as np>>> x = np.array([1, 2])&