MaskRCNN可视化界面开发(PyQt5)
MaskRCNN可视化界面开发(PyQt5)
笔者因毕设要求,需要对maskRCNN进行封装,制作一个可视化界面。
先来展示下效果图:
文章目录
前言
本文默认已经实现了MaskRCNN的训练和测试,现在测试的基础上加一个UI界面。 本文使用PyQt5进行界面开发。提示:以下是本篇文章正文内容,下面案例可供参考
一、PyQt5及Designer、Pyuic插件安装
1.激活maskRCNN虚拟环境,安装PyQt5:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package PyQt5
清华的镜像地址,加速下载,推荐使用
PyQt5 测试
import sys
from PyQt5 import QtWidgets
app = QtWidgets.QApplication(sys.argv)
widget = QtWidgets.QWidget()
widget.resize(360, 360)
widget.setWindowTitle("Hello, PyQt5")
widget.show()
sys.exit(app.exec_())
2.安装Qt的工具包
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package PyQt5-tools
安装成功打开python的安装目录的Lib
目录下,site-packages
里面会有 PyQt5
和 pyqt5-tools
两个目录
配置PyChram,安装QtDesigner:
2.1打开PyCharm,File > Settings > Tools > External Tools
2.2点击 + 号创建
Name: Designer
Group: Qt
Program: designer.exe
所在目录
Working directory: $ProjectFileDir$
2.3安装Pyuic
打开PyCharm,File > Settings > Tools > External Tools
点击 + 号创建
Name: Pyuic
Group: Qt
Program: python.exe
所在目录
Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py
Working directory: $FileDir$
二、设计UI界面
1.使用Qt Designer来设计界面
注意本过程需在maskRCNN源码的同一目录下进行。
按照我们之前的界面构思
我们需要从3个PushButton按键,2个label用于展示和1个textBrowser用于状态显示。
控件上显示的文字 text 属性和控件的名字 objectName 属性需要修改,便于显示和代码调用。可以按照下面我推荐的命名:
控件 | 显示内容text | 控件名objectName |
---|---|---|
PushButton | 导入图片 | btnInput |
PushButton | 检测 | btnTest |
PushButton | 保存 | btnSave |
Label | 输入图片 | labelinput |
Label | 结果图片 | labelresult |
TextBrowser | textBrowser |
2.按钮事件
我们知道GUI是通过事件驱动的,什么意思呢?比如前面我们已经设计好了界面,接下来就需要实现”导入图片”到”保存”这3个按钮的功能,也就是给每个按钮指定一个”函数”,逻辑代码写在这个函数里面。这种函数就称为事件,Qt中称为槽连接。
点击Designer工具栏的”Edit Signals/Slots”按钮,进入槽函数编辑界面,点击旁边的”Edit Widgets”可以恢复正常视图:
进入槽函数编辑界面后,然后点击按钮并拖动,当产生类似于电路中的接地符号时释放鼠标,参看下图:
到此,我们就完成了界面设计的所有工作,按下Ctrl+S保存当前窗口为.ui文件。
3.ui文件转py代码
运行PyUIC后,会生成UI个.py文件,打开.py就是我们需要的界面模板。注意不要直接在.py文件里编码,因为每一次运行PyUIC,生成的.py文件都会更新,添加的代码不会保存。
三、编写逻辑代码
在同一工作目录下新建一个”UI_main.py”的文件,存放逻辑代码。代码中的每部分我都写得比较独立,没有封装成函数,便于理解。代码看上去很长,但很简单,可以每个模块单独看。
我整体的思路比较简单:
1.当按下导入图片按键时,要导入的图片显示在待显示的label区域;
2.当按下导入检测按键时,运行原来的maskRCNN的测试部分的代码,并将测试部分的结果图片保存为temp.png,并显示在结果显示的label区域;
3.当按下导入保存按键时,读取temp.png图片,保存到指定位置。
4.以上三部步都会产生反馈状态,将反馈状态显示在textBrowser区域。
下面直接上代码:
import sys
import cv2 as cv
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
# from PyQt5.QtWidgets import QFileDialog, QMainWindow
from PyQt5.QtWidgets import QFileDialog, QMainWindow, QApplication
from untitled import Ui_MainWindow
class PyQtMainEntry(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.setWindowTitle("路面缺陷检测软件V1.0")
self.labelinput.setAlignment(Qt.AlignCenter)
self.labelinput.setStyleSheet("QLabel{background:gray;}"
"QLabel{color:rgba(255,255,255,150);"
"font-size:20px;"
"font-weight:bold;"
"font-family:Roman times;}")
self.labelresult.setAlignment(Qt.AlignCenter)
self.labelresult.setStyleSheet("QLabel{background:gray;}"
"QLabel{color:rgba(255,255,255,150);"
"font-size:20px;"
"font-weight:bold;"
"font-family:Roman times;}")
def btnTest_Pressed(self):
if not hasattr(self, "captured"):
# print("没有输入图像")
# self.textBrowser.setPlainText("没有输入图像")
return
self.textBrowser.append("图像检测中...")
def btnInput_Clicked(self):
'''
从本地读取图片
'''
global fname
# 打开文件选取对话框
filename, _ = QFileDialog.getOpenFileName(self, '打开图片', "", "*.jpg;;*.png;;All Files(*)")
if filename:
self.captured = cv.imread(str(filename))
# OpenCV图像以BGR通道存储,显示时需要从BGR转到RGB
self.captured = cv.cvtColor(self.captured, cv.COLOR_BGR2RGB)
rows, cols, channels = self.captured.shape
bytesPerLine = channels * cols
QImg = QImage(self.captured.data, cols, rows, bytesPerLine, QImage.Format_RGB888)
self.labelinput.setPixmap(QPixmap.fromImage(QImg).scaled(
self.labelinput.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
fname = filename
print(fname)
self.textBrowser.setPlainText("成功打开图片")
def btnTest_Clicked(self):
'''
test
'''
global fname
# 如果没有捕获图片,则不执行操作
if not hasattr(self, "captured"):
print("没有输入图像")
self.textBrowser.setPlainText("没有输入图像")
return
print("start")
print(fname.split("/")[-1])
# -*- coding: utf-8 -*-
import os
import sys
import skimage.io
import matplotlib
matplotlib.rcParams['font.sans-serif'] = ['KaiTi']
matplotlib.rcParams['font.serif'] = ['KaiTi']
from mrcnn.config import Config
from datetime import datetime
# Root directory of the project
ROOT_DIR = os.getcwd()
# Import Mask RCNN
sys.path.append(ROOT_DIR) # To find local version of the library
from mrcnn import utils
import mrcnn.model as modellib
from mrcnn import visualize
# Import COCO config
# sys.path.append(os.path.join(ROOT_DIR, "samples/coco/")) # To find local version
# from samples.coco import coco
# Directory to save logs and trained model
MODEL_DIR = os.path.join(ROOT_DIR, "logs")
# Local path to trained weights file
# todo:模型位置
COCO_MODEL_PATH = "E:\\maskrcnn_pycharm\\Mask_RCNN\\logs\\mask_rcnn_shapes_1000.h5" # 模型保存目录
# Download COCO trained weights from Releases if needed
if not os.path.exists(COCO_MODEL_PATH):
utils.download_trained_weights(COCO_MODEL_PATH)
print("cuiwei***********************")
# Directory of images to run detection on
# todo:测试图片位置
# IMAGE_DIR = os.path.join(ROOT_DIR, "picRGB")
IMAGE_DIR = fname
print(IMAGE_DIR)
class ShapesConfig(Config):
"""Configuration for training on the toy shapes dataset.
Derives from the base Config class and overrides values specific
to the toy shapes dataset.
"""
# Give the configuration a recognizable name
NAME = "shapes"
# Train on 1 GPU and 8 images per GPU. We can put multiple images on each
# GPU because the images are small. Batch size is 8 (GPUs * images/GPU).
GPU_COUNT = 1
IMAGES_PER_GPU = 1
# Number of classes (including background)
NUM_CLASSES = 1 + 6 # background + 3 shapes
# Use small images for faster training. Set the limits of the small side
# the large side, and that determines the image shape.
IMAGE_MIN_DIM = 320
IMAGE_MAX_DIM = 512
# Use smaller anchors because our image and objects are small
RPN_ANCHOR_SCALES = (8 * 6, 16 * 6, 32 * 6, 64 * 6, 128 * 6) # anchor side in pixels
# Reduce training ROIs per image because the images are small and have
# few objects. Aim to allow ROI sampling to pick 33% positive ROIs.
TRAIN_ROIS_PER_IMAGE = 100
# Use a small epoch since the data is simple
STEPS_PER_EPOCH = 100
# use small validation steps since the epoch is small
VALIDATION_STEPS = 50
# import train_tongue
# class InferenceConfig(coco.CocoConfig):
class InferenceConfig(ShapesConfig):
# Set batch size to 1 since we'll be running inference on
# one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU
GPU_COUNT = 1
IMAGES_PER_GPU = 1
config = InferenceConfig()
# Create model object in inference mode.
model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
# Load weights trained on MS-COCO
model.load_weights(COCO_MODEL_PATH, by_name=True)
# COCO Class names
# Index of the class in the list is its ID. For example, to get ID of
# the teddy bear class, use: class_names.index('teddy bear')
# class_names = ['BG', '隐裂'] # 注意修改类别名称
class_names = ['BG', '灌缝修补', '横向裂缝', '块状裂缝', '块状修补', '纵向裂缝', '坑槽']
# Load a random image from the images folder
# file_names = next(os.walk(IMAGE_DIR))[2]
# image = skimage.io.imread("E:\\maskrcnn_pycharm\\Mask_RCNN\\picRGB\\62.png") # 你想要测试的图片
image = skimage.io.imread(fname) # 你想要测试的图片
a = datetime.now()
# Run detection
results = model.detect([image], verbose=1)
# print("result:",results)
b = datetime.now()
# Visualize results
# print("检测用时", (b - a).seconds)
time = (b - a).seconds
self.textBrowser.append("检测用时:" + str(time) + "s")
r = results[0]
visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'],
class_names, r['scores'])
class_ids = r['class_ids']
class_dict = {}
for index, i in enumerate(class_ids):
if i in class_dict:
class_dict[i] += 1
else:
class_dict[i] = 1
output_dict = {}
for key, value in class_dict.items():
label = class_names[key]
output_dict[label] = value
print(output_dict)
self.textBrowser.append("本张路面图片包含:" )
for key, value in output_dict.items():
self.textBrowser.append(str(value)+"处"+str(key))
self.captured = cv.imread(r"temp.png")
# OpenCV图像以BGR通道存储,显示时需要从BGR转到RGB
self.captured = cv.cvtColor(self.captured, cv.COLOR_BGR2RGB)
rows, cols, channels = self.captured.shape
bytesPerLine = channels * cols
QImg = QImage(self.captured.data, cols, rows, bytesPerLine, QImage.Format_RGB888)
self.labelresult.setPixmap(QPixmap.fromImage(QImg).scaled(
self.labelresult.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
self.textBrowser.append("检测完成")
def btnSave_Clicked(self):
'''
保存
'''
global fname
if not hasattr(self, "captured"):
print("没有输入图像")
self.textBrowser.setPlainText("没有输入图像")
return
tmp = fname.split('/')[-1]
img = cv.imread("temp.png")
fd, type = QFileDialog.getSaveFileName(self,
"保存图片", tmp)
print(fd)
cv.imwrite(fd, img)
# self.textBrowser.setPlainText("保存成功")
self.textBrowser.append("保存成功") # textedit是文本框的名称
print("保存成功")
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = PyQtMainEntry()
window.show()
sys.exit(app.exec_())
今天就先写到这边,后续有想法再补充!
如果阅读本文对你有用,欢迎点赞评论收藏呀!!!
2020年12月8日15:32:30
本文地址:https://blog.csdn.net/JulyLi2019/article/details/110850627