前言
本文主要实现图像转素描,支持相机取图或者载入图像取图
环境配置:
python3.6 64位
paddlepaddle2.3.1
chainer7.8.1
cupy-cuda==7.8
halcon12.0
visualstudio code
视频演示
基于pyqt+深度学习,实现图像转素描并得到一系列坐标点
一、ui配置
本文的UI配置因为比较简单,因此基本是纯代码写界面
本工程ui配置的文件如下:
1.left_button.py源码
首先左边侧边栏按钮代码:
import os
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
class PyPushButton(QPushButton):
def __init__(self, text = "", height = 40, minimum_width = 50, text_padding = 55,icon_path = "",is_active = False,
text_color = "#c3ccdf", icon_color = "#c3ccdf", btn_color = "#44475a", btn_hover = "#4f5368", btn_pressed = "#282a36"
):
super().__init__()
self.setText(text)
self.setMaximumHeight(height)
self.setMinimumHeight(height)
self.setCursor(Qt.PointingHandCursor)
self.minimum_width = minimum_width
self.text_padding = text_padding
self.text_color = text_color
self.icon_path = icon_path
self.icon_color = icon_color
self.btn_color = btn_color
self.btn_hover = btn_hover
self.btn_pressed = btn_pressed
self.is_active = is_active
self.set_style(
text_padding = self.text_padding,
text_color = self.text_color,
btn_color = self.btn_color,
btn_hover = self.btn_hover,
btn_pressed = self.btn_pressed,
is_active = self.is_active
)
def set_style(
self,
text_padding = 55,
text_color = "#c3ccdf",
btn_color = "#44475a",
btn_hover = "#4f5368",
btn_pressed = "#282a36",
is_active = False
):
style = f"""
QPushButton {{
color: {text_color};
background-color: {btn_color};
padding-left: {text_padding}px;
text-align: left;
border: none;
}}
QPushButton:hover {{
background-color: {btn_hover};
}}
QPushButton:pressed {{
background-color: {btn_pressed};
}}
"""
active_style = f"""
QPushButton {{
background-color: {btn_hover};
border-right: 5px solid #282a36;
}}
"""
if not is_active:
self.setStyleSheet(style)
else:
self.setStyleSheet(style + active_style)
def set_active(self, is_active_menu):
self.set_style(
text_padding = self.text_padding,
text_color = self.text_color,
btn_color = self.btn_color,
btn_hover = self.btn_hover,
btn_pressed = self.btn_pressed,
is_active = is_active_menu
)
def paintEvent(self, event):
QPushButton.paintEvent(self, event)
qp = QPainter()
qp.begin(self)
qp.setRenderHint(QPainter.Antialiasing)
qp.setPen(Qt.NoPen)
rect = QRect(0,0, self.minimum_width, self.height())
self.draw_icon(qp, self.icon_path, rect, self.icon_color)
qp.end()
def draw_icon(self, qp, image, rect, color):
app_path = os.path.abspath(os.getcwd())
icon_path = os.path.normpath(image)
icon = QPixmap(icon_path)
painter = QPainter(icon)
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
painter.fillRect(icon.rect(), color)
qp.drawPixmap(
(rect.width() - icon.width()) / 2,
(rect.height() - icon.height()) / 2,
icon
)
painter.end()
2.switch_btn.py源码
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
class SwitchButton(QWidget):
#信号
checkedChanged = Signal (bool)
def __init__(self,parent=None,width=60,height=20):
super(SwitchButton, self).__init__(parent)
self.checked = False
self.bgColorOff = QColor(255, 255, 255)
self.bgColorOn = QColor(0, 0, 0)
self.sliderColorOff = QColor(100, 100, 100)
self.sliderColorOn = QColor(100, 184, 255)
self.textColorOff = QColor(143, 143, 143)
self.textColorOn = QColor(255, 255, 255)
self.textOff = "OFF"
self.textOn = "ON"
self.space = 2
self.rectRadius = 5
self.step = self.width() / 50
self.startX = 0
self.endX = 0
self.timer = QTimer(self) # 初始化一个定时器
self.timer.timeout.connect(self.updateValue) # 计时结束调用operate()方法
#self.timer.start(5) # 设置计时间隔并启动
self.setFont(QFont("Microsoft Yahei", 10))
#self.resize(55,22)
self.setMinimumWidth(width)
self.setMaximumWidth(width)
self.setMinimumHeight(height)
self.setMaximumHeight(height)
def updateValue(self):
if self.checked:
if self.startX < self.endX:
self.startX = self.startX + self.step
else:
self.startX = self.endX
self.timer.stop()
else:
if self.startX > self.endX:
self.startX = self.startX - self.step
else:
self.startX = self.endX
self.timer.stop()
self.update()
def mousePressEvent(self,event):
self.checked = not self.checked
#发射信号
self.checkedChanged.emit(self.checked)
# 每次移动的步长为宽度的50分之一
self.step = self.width() / 50
#状态切换改变后自动计算终点坐标
if self.checked:
self.endX = self.width() - self.height()
else:
self.endX = 0
self.timer.start(5)
def paintEvent(self, evt):
#绘制准备工作, 启用反锯齿
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing)
#绘制背景
self.drawBg(evt, painter)
#绘制滑块
self.drawSlider(evt, painter)
#绘制文字
self.drawText(evt, painter)
painter.end()
def drawText(self, event, painter):
painter.save()
if self.checked:
painter.setPen(self.textColorOn)
painter.drawText(0, 0, self.width() / 2 + self.space * 2, self.height(), Qt.AlignCenter, self.textOn)
else:
painter.setPen(self.textColorOff)
painter.drawText(self.width() / 2, 0,self.width() / 2 - self.space, self.height(), Qt.AlignCenter, self.textOff)
painter.restore()
def drawBg(self, event, painter):
painter.save()
painter.setPen(Qt.NoPen)
if self.checked:
painter.setBrush(self.bgColorOn)
else:
painter.setBrush(self.bgColorOff)
rect = QRect(0, 0, self.width(), self.height())
#半径为高度的一半
radius = rect.height() / 2
#圆的宽度为高度
circleWidth = rect.height()
path = QPainterPath()
path.moveTo(radius, rect.left())
path.arcTo(QRectF(rect.left(), rect.top(), circleWidth, circleWidth), 90, 180)
path.lineTo(rect.width() - radius, rect.height())
path.arcTo(QRectF(rect.width() - rect.height(), rect.top(), circleWidth, circleWidth), 270, 180)
path.lineTo(radius, rect.top())
painter.drawPath(path)
painter.restore()
def drawSlider(self, event, painter):
painter.save()
if self.checked:
painter.setBrush(self.sliderColorOn)
else:
painter.setBrush(self.sliderColorOff)
rect = QRect(0, 0, self.width(), self.height())
sliderWidth = rect.height() - self.space * 2
sliderRect = QRect(self.startX + self.space, self.space, sliderWidth, sliderWidth)
painter.drawEllipse(sliderRect)
painter.restore()
3.主页面重要代码
if not parent.objectName():
parent.setObjectName("MainWindow")
self.img_path = img_path
parent.resize(1280, 680)
parent.setMinimumSize(1280, 680)
#主页frame - 主
self.central_frame = QFrame()
self.main_layout = QHBoxLayout(self.central_frame)
self.main_layout.setContentsMargins(0,0,0,0)
self.main_layout.setSpacing(0)
#主页frame - 中间页面
self.content = QFrame()
self.content.setStyleSheet("background-color: #282a36")
self.content_layout = QVBoxLayout(self.content)
self.content_layout.setContentsMargins(0, 0, 0, 0)
self.content_layout.setSpacing(0)
# 主页frame - 上方标题栏
self.top_bar = QFrame()
self.top_bar.setMinimumHeight(30)
self.top_bar.setMaximumHeight(30)
self.top_bar.setStyleSheet("background-color: #21232d; color: #6272a4")
self.top_bar_layout = QHBoxLayout(self.top_bar)
self.top_bar_layout.setContentsMargins(10, 0, 10, 0)
# 主页frame - 下方状态栏
self.bottom_bar = QFrame()
self.bottom_bar.setMinimumHeight(30)
self.bottom_bar.setMaximumHeight(30)
self.bottom_bar.setStyleSheet("background-color: #21232d; color: #6272a4")
self.bottom_bar_layout = QHBoxLayout(self.bottom_bar)
self.bottom_bar_layout.setContentsMargins(10, 0, 10, 0)
# 侧边栏-主
self.left_menu = QFrame()
self.left_menu.setStyleSheet("background-color: #44475a")
self.left_menu.setMaximumWidth(50)
self.left_menu.setMinimumWidth(50)
self.left_menu_layout = QVBoxLayout(self.left_menu)
self.left_menu_layout.setContentsMargins(0,0,0,0)
self.left_menu_layout.setSpacing(0)
# 侧边栏- 按钮
self.left_menu_top_frame = QFrame()
self.left_menu_top_frame.setMinimumHeight(40)
self.left_menu_top_frame.setObjectName("left_menu_top_frame")
self.left_menu_top_layout = QVBoxLayout(self.left_menu_top_frame)
self.left_menu_top_layout.setContentsMargins(0,0,0,0)
self.left_menu_top_layout.setSpacing(0)
# 侧边栏- 下方设置
self.left_menu_bottom_frame = QFrame()
self.left_menu_bottom_frame.setMinimumHeight(40)
self.left_menu_bottom_frame.setObjectName("left_menu_bottom_frame")
self.left_menu_bottom_layout = QVBoxLayout(self.left_menu_bottom_frame)
self.left_menu_bottom_layout.setContentsMargins(0, 0, 0, 0)
self.left_menu_bottom_layout.setSpacing(0)
二、界面功能
1.初始化模型
def InitModel(modelPath):
global ctu_seg, ctu_remark, ctu_draw,LoadModelFinish
try:
ctu_seg = Ctu_SegAI(USEGPU='0', image_size=513, Model_Path=modelPath)
except:
ctu_seg = None
try:
ctu_remark = Ctu_FaceRemark(modelPath)
except:
ctu_remark = None
ctu_draw = Ctu_LineDrawing(USEGPU=-1, image_size=512)
ctu_draw.LoadModel(modelPath)
LoadModelFinish=True
2.初始化模型
深度学习模型检测
def DL_Check(check_cut_AI,check_remark):
global ctu_seg,ctu_draw,ctu_remark,cv_img_show,cv_img_show_o,DLCheckFinish,DLCheckFinish_Camera
origin_img = cv_img_show_o.copy()
cv2_img_remark = None
try:
if check_cut_AI:
origin_img = ctu_seg.predict_cut(origin_img)
except:
pass
if ctu_draw is not None:
origin_img,cv2_img_remark = ctu_draw.predict(origin_img)
try:
if check_remark and cv2_img_remark is not None:
remark = ctu_remark.predict(cv2_img_remark)
for key,value_face in remark.items():
origin_img = cv2.rectangle(origin_img, value_face['face'][0],value_face['face'][1], color=(0,0,0), thickness=1)
for each_point in value_face['point']:
cv2.circle(origin_img, each_point, 1, color=(0, 255, 0))
if cv2_img_remark is not None:
del cv2_img_remark
except:
pass
cv_img_show = origin_img.copy()
del origin_img
DLCheckFinish=True
DLCheckFinish_Camera=True
3.相机采图
def get_Image(cap):
global cv_img_show_o,get_image_Flag
while get_image_Flag:
try:
_, cv_img_show_o = cap.read()
cv2.waitKey(30)
except:
pass
4.获取坐标点
def get_result_DL(file_name, Px_list, Py_list,Qx_list,Qy_list, use_HmatFlag, base_file,chara_split):
global result_data_list_json,result_data_list_str,DLGetResultFinish
try:
result_data_list_json,result_data_list_str = get_result(file_name, Px_list, Py_list,Qx_list,Qy_list, use_HmatFlag, base_file,chara_split)
except:
result_data_list_json = result_data_list_str = ''
DLGetResultFinish = True
总结
因代码篇幅过长,感兴趣的可以私聊沟通一起