水上船只识别系统(YOLOv5+QT界面设计)Python
本篇博客将实现水上船只识别系统设计,项目代码包括YOLOv5模型训练,用户QT界面设计以及最后整体船只识别系统设计。
先看一下最后界面整体呈现效果:
系统支持菜单栏选择检测方式(图片,视频和摄像头)和检测对象。
1.YOLOv5模型训练
1.1数据集准备
将标注标签的海上船只数据集SeaShip按照5:1:1划分为训练集(train),验证集(val),测试集(test),并按照对应进行标签txt文件划分。
1.2yaml文件配置
在COCO128.yaml文件将path修改为数据集SeaShip在电脑中路径,train,val,test分别修改路径为其在电脑中的路径。如图:
1.3模型训练
本文选取yolo5s.pt和yolo5l.pt分别作为初始权重进行网络训练,超参数配置文件选择hyp.scratch-high.yaml,使用GPU NVIDIA A4000,分别训练轮数100轮和训练轮数200轮,最终得到训练权重best.pt。
2.界面设计
2.1环境搭建
安装PyQt5和PyQt5-tools,以及在在 PyCharm 下开发配置参考下面博客:
2.2用户界面设计
存储背景图片的资源文件Qrc文件,文件名后缀为.qrc:
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource prefix="/">
<file>picture.jpg</file>
</qresource>
</RCC>
如果需要更改图片,将picture.jpg修改为自己图片路径即可。
在Pycham中打开外部工具QTDesigner
在Designer中用组件ListView作为背景图的承载空间
在ListView中添加组件Qlable,用于显示检测后图像的信息(检测前图像,检测后图像),以及检测时间,目标数目,类别,置信度等信息。通过在菜单栏选择检测方式和检测对对象,最后通过开始和退出两个PushButton来开始检测和退出检测。UI界面如图:
上面是本文设计的界面,读者可以自行设计自己想要的图标更加丰富,功能更加齐全的界面。
设计完界面后。通过外部工具PyUIC将生成的project.ui转成python文件project.py。
Qrc文件通过在终端命令:
pyrcc5 resource.qrc -o resource_rc.py
Qrc文件转Py文件参考下面博客:
3.船只识别系统设计
系统由GUI模块,目标检测模块和线程管理模块三个模块组成。
3.1 GUI模块
系统首先需要对检测模式,检测对象,模型,设备,线程等进行初始化,并且连接菜和按钮点击信号到槽函数。
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
# 初始化检测模式和对象
self.detection_mode = None
self.detection_object = None
# 初始化模型和设备
self.model = None
self.device = None
# 加载 YOLOv5 模型
self.load_model()
# 连接菜单动作到槽函数
self.action_3.triggered.connect(lambda: self.set_detection_mode("图片检测"))
self.action_4.triggered.connect(lambda: self.set_detection_mode("视频检测"))
self.action_5.triggered.connect(lambda: self.set_detection_mode("摄像头检测"))
self.actionbridge.triggered.connect(lambda: self.set_detection_object("bridge"))
self.actionboat.triggered.connect(lambda: self.set_detection_object("boat"))
self.actionship.triggered.connect(lambda: self.set_detection_object("ship"))
self.actionrubbish.triggered.connect(lambda: self.set_detection_object("buoy"))
# 连接按钮的点击信号到槽函数
self.pushButton.clicked.connect(self.exit_app) # "退出"按钮
self.pushButton_2.clicked.connect(self.start_detection) # "开始"按钮
# 初始化检测线程
self.thread = None
3.2 目标检测模块
首先,我们需要将输入的图像处理成YOLOv5模型所需要的尺寸(640x640像素),并进行颜色转换(从BGR到RGB)。然后将图像转换为PyTorch的张量并进行归一化。接下来,我们将预处理后的图像传入YOLOv5模型进行推理,得到检测结果。
# 图像预处理
img = cv2.resize(frame, (640, 640)) # 调整为模型输入尺寸
img = img[:, :, ::-1].transpose(2, 0, 1) # BGR to RGB, to 3x640x640
img = np.ascontiguousarray(img)
img = torch.from_numpy(img).to(self.device)
img = img.float() / 255.0 # 归一化
if img.ndimension() == 3:
img = img.unsqueeze(0)
YOLOv5的检测结果是多个边界框,每个框都有一个置信度得分。为了过滤掉冗余的框,我们使用非最大抑制(NMS)来选择最有可能的框。
# 非最大抑制去除冗余框
pred = non_max_suppression(pred, 0.25, 0.45)
检测到的目标会用边界框标记出来,我们还会绘制目标的标签和置信度信息。这里,我们使用OpenCV的 cv2.rectangle 绘制矩形框,cv2.putText 绘制文本标签。
# 绘制边界框和标签
for *xyxy, conf, cls in reversed(det):
label = f'{self.model.names[int(cls)]} {conf:.2f}'
plot_one_box(xyxy, frame, label=label, color=self.model.colors[int(cls)], line_thickness=2)
3.3 线程管理模块
为了实现实时视频或摄像头检测,我们使用了PyQt5的QThread来创建一个检测线程。该线程负责不断地从视频流中读取图像,进行目标检测,并将检测结果通过信号传递到主界面,更新图像和检测信息。
# 检测线程
class DetectionThread(QThread):
change_pixmap_signal = pyqtSignal(np.ndarray)
update_info_signal = pyqtSignal(float, int, list, list) # 检测时间, 目标数目, 类别, 置信度
def run(self):
cap = cv2.VideoCapture(self.source)
while self._run_flag:
ret, frame = cap.read()
if ret:
# 目标检测代码
self.change_pixmap_signal.emit(frame) # 更新图像
self.update_info_signal.emit(detection_time, num_targets, classes, confidences) # 更新信息