MaskRCNN可视化界面开发(PyQt5)

2022-07-26,,,

MaskRCNN可视化界面开发(PyQt5)

笔者因毕设要求,需要对maskRCNN进行封装,制作一个可视化界面。


先来展示下效果图:

文章目录

  • MaskRCNN可视化界面开发(PyQt5)
  • 前言
  • 一、PyQt5及Designer、Pyuic插件安装
  • 二、设计UI界面
    • 1.使用Qt Designer来设计界面
    • 2.按钮事件
    • 3.ui文件转py代码
  • 三、编写逻辑代码

前言

本文默认已经实现了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里面会有 PyQt5pyqt5-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

《MaskRCNN可视化界面开发(PyQt5).doc》

下载本文的Word格式文档,以方便收藏与打印。