关于PyQt5信号槽机制的解析
信号槽机制是 Qt 框架中用于对象间通信的核心机制,它基于发布-订阅模式,能够实现松耦合的组件交互。
1. 信号槽机制的基本概念
信号(Signal)
- 信号是对象发出的一种通知,表示某个事件发生了。例如,当用户点击按钮时,按钮会发出一个"点击"信号。
- 信号本身不包含任何逻辑,只是通知其他对象发生了某件事。
槽(Slot)
- 槽是对象中的一个函数,用于响应信号。例如,当按钮发出"点击"信号时,槽函数可以执行导入图片的逻辑。
- 槽函数可以包含具体的业务逻辑。
连接(Connect)
- 通过
connect
函数,将信号与槽关联起来。当信号发出时,槽函数会自动被调用。 - 信号槽的连接是松耦合的,信号发出者不需要知道槽的具体实现。
2. 结合"导入图片"功能
假设我们有一个图片导入功能,用户点击"导入"按钮后,程序会从文件系统中选择一张图片并显示在界面上。我们可以用信号槽机制来实现这个功能。
组件
- 按钮(QPushButton) :
- 发出"点击"信号,表示用户点击了按钮。
- 文件对话框(QFileDialog) :
- 用于选择图片文件。
- 图片显示控件(QLabel) :
- 用于显示导入的图片。
信号槽设计
- 按钮点击信号 :
- 当用户点击"导入"按钮时,按钮发出
clicked()
信号。
- 当用户点击"导入"按钮时,按钮发出
- 文件选择槽 :
- 连接
clicked()
信号到一个槽函数,该槽函数打开文件对话框,让用户选择图片文件。
- 连接
- 图片显示槽 :
- 当用户选择图片文件后,文件对话框发出
fileSelected(QString)
信号,连接该信号到另一个槽函数,该槽函数将图片加载并显示在QLabel
中。
- 当用户选择图片文件后,文件对话框发出
关于功能点的解析
负责算法导入,手动标注功能
权重模型导入
为了适应不同模型的导入,先动态获取权重文件,接着在mainwindow.py初始化主界面的控件块信号与槽函数的连接时,开始预处理模型的加载,当用户点击选择了权重文件后,再将权重文件导入模型,开始加载模型,完成模型的真正导入。其次,前端主界面完成"Segment Angthing"的action设计后,标注软件就开始搭载语义分割时所需要的模型。
此外,在对前端的界面类进行实例化时,通过对segment_any文件夹进行遍历,读取到.pth权重文件,并根据高级函数action.triggered.connect(functools.partial(self.init_segment_anything, model_name))将目标权重作为选项添加到主界面的菜单选择块"算法"当中,具体的核心代码如下:
- model_names = sorted([pth for pth in os.listdir('segment_any') if pth.endswith('.pth') or pth.endswith('.pt')])
- #使用列表推导式获取目录 'segment_any' 下所有以 '.pth' 或 '.pt' 结尾的文件,并将文件名列表进行排序。
- self.pths_actions = {}
- for model_name in model_names:
- action = QtWidgets.QAction(self)
- action.setObjectName("actionZoom_in")
- action.triggered.connect(functools.partial(self.init_segment_anything, model_name))
- #设置functools.partial函数将权重文件添加至算法选项中
- action.setText("{}".format(model_name))
- action.setCheckable(True)
- #根据指定目录下的模型文件,创建对应的 QAction 对象,并将这些对象存储在字典 self.pths_actions 中
当用户选中对应的算法权重后,以权重文件的名称为参数,利用functools.partial()这个高级连接函数,连接init_segment_anything槽函数,开始初始化模型环境。
读取到相应的权重文件的路径后,通过传入权重路径model_path实例化模型对象self.segany=SegAny(model_path),其中SegAny是segment_any.py文件内的类SegAny,在该类的初始化时运行已经导入的文件mini下的train.py文件中的use_net方法,为已经针对红外图像数据优化完毕的MiniSegNet模型,模型加载的代码具体如下:
- net = Yolact() #实例化模型
- net.detect.use_fast_nms = args.fast_nms
- net.detect.use_cross_class_nms = args.cross_class_nms
- #设置 Yolact 模型的检测器的参数,包括是否使用快速非极大值抑制(use_fast_nms)和是否使用跨类别的非极大值抑制(use_cross_class_nms)。
- net.load_weights(weights_path)#加载预训练权重到 Yolact 模型中
- net.eval()#将 Yolact 模型设置为评估(inference)模式
至此模型调入完毕,显示"Use the checkpoint named best"(best为最佳权重文件名称")
单帧手动标注
针对一张图像进行手动绘制多边形标签对象的原理同自动绘制多边形标签对象区别在于修改模式为手动添加标签点,再进行多边形的绘制。
手动绘制多边形是基于鼠标在图像显示窗口内进行了点击操作,由canvas.py内的mousePressEvent,mouseReleaseEvent,mouseMoveEvent三个函数来组成鼠标点击,鼠标释放,以及鼠标移动来实现在图像显示窗口内的设立新标签点,并且拖动鼠标完成多个标签点的新建,再通过canvas.py内的finish_draw函数,进入polygon_mode(绘制模式),从而把已经打好的标签点,记录为新的标签点,来重新绘制新的多边形,最终产生了目标标签对象即分割目标。绘制多边形轮廓,并未完成绘制的效果图