深度学习目标检测算法yolov8训练水果检测数据集 建立基于YOLOv8的水果检测识别系统pyqt5界面文章目录深度学习目标检测算法yolov8训练水果检测数据集 建立基于YOLOv8的水果检测识别系统pyqt5界面1. 安装依赖2. 数据准备3. 训练模型4. GUI设计与推理逻辑5. SE注意力机制**1. SE模块的实现****2. 修改YOLOv8主干网络****2.1 找到目标卷积层****2.2 修改YOLOv8源码****3. 配置训练脚本****4. 验证改进效果****5. 总结****注意事项**以官方yolov8为主干实现对市面常见水果的检测识别OpenCV实现对水果的检测训练的分类模型识别对水果品种类别的检测且利用PyQt5设计了简约的系统UI界面。可选择添加SE注意力机制的主干模型您还可以更换自己训练的主干模型进行自己数据的检测。1基于YOLOv8的水果检测识别系统该系统支持外接摄像头实时检测、常见水果品种的识别且利用PyQt5设计简约的UI界面。以下是详细的实现步骤和代码示例。1. 安装依赖首先确保安装了必要的库pipinstallultralytics opencv-python pyqt5 pandas torch torchvision2. 数据准备假设你的数据集目录结构如下dataset/ ├── images/ │ ├── train/ │ │ ├── img1.jpg │ │ └── ... │ └── val/ │ ├── img1.jpg │ └── ... └── labels/ ├── train/ │ ├── img1.txt │ └── ... └── val/ ├── img1.txt └── ...每个标签文件是.txt格式每一行表示一个目标格式为class_id x_center y_center width height创建一个data.yaml文件用于定义数据集路径和类别名称train:./dataset/images/trainval:./dataset/images/valnc:5# 类别数量names:[apple,banana,orange,grape,strawberry]# 常见水果类别名称3. 训练模型编写训练代码使用YOLOv8进行训练fromultralyticsimportYOLOdeftrain_model():# 加载预训练模型modelYOLO(yolov8n.pt)# 使用YOLOv8 Nano预训练模型# 开始训练model.train(datadata.yaml,# 数据集配置文件epochs100,# 训练轮数imgsz640,# 输入图片尺寸batch16,# 批次大小devicecuda,# 使用 GPUworkers8,# 数据加载线程数projectruns/train,# 训练结果保存路径nameexp# 实验名称)if__name____main__:train_model()4. GUI设计与推理逻辑使用PyQt5设计GUI并集成YOLOv8进行推理fromPyQt5.QtWidgetsimportQApplication,QMainWindow,QPushButton,QLabel,QVBoxLayout,QWidget,QFileDialog,QMessageBox,QComboBoxfromPyQt5.QtGuiimportQImage,QPixmapfromPyQt5.QtCoreimportQTimerfromultralyticsimportYOLOimportcv2importpandasaspdimportosclassFruitDetector(QMainWindow):def__init__(self):super().__init__()self.setWindowTitle(水果检测识别系统)self.setGeometry(100,100,800,600)self.modelYOLO(runs/train/exp/weights/best.pt)# 加载训练好的模型self.class_names[apple,banana,orange,grape,strawberry]self.current_classNoneself.labelQLabel(self)self.label.setGeometry(50,50,700,400)self.btn_imageQPushButton(选择图片,self)self.btn_videoQPushButton(选择视频,self)self.btn_cameraQPushButton(打开摄像头,self)self.btn_exportQPushButton(导出结果,self)self.combo_classesQComboBox(self)self.btn_image.setGeometry(50,500,150,40)self.btn_video.setGeometry(220,500,150,40)self.btn_camera.setGeometry(390,500,150,40)self.btn_export.setGeometry(560,500,150,40)self.combo_classes.setGeometry(320,550,150,40)self.btn_image.clicked.connect(self.detect_single_image)self.btn_video.clicked.connect(self.detect_video)self.btn_camera.clicked.connect(self.open_camera)self.btn_export.clicked.connect(self.export_results)self.combo_classes.addItems([All]self.class_names)self.combo_classes.currentTextChanged.connect(self.switch_class)self.capNoneself.timerQTimer()self.timer.timeout.connect(self.update_frame)self.results_data[]defdetect_single_image(self):检测单张图片file_path,_QFileDialog.getOpenFileName(self,选择图片,,Images (*.jpg *.png))iffile_path:self.process_image(file_path)defdetect_video(self):检测视频文件file_path,_QFileDialog.getOpenFileName(self,选择视频,,Videos (*.mp4 *.avi))iffile_path:self.capcv2.VideoCapture(file_path)self.timer.start(30)defopen_camera(self):打开摄像头进行实时检测self.capcv2.VideoCapture(0)self.timer.start(30)defupdate_frame(self):更新视频帧或摄像头捕获的画面ret,frameself.cap.read()ifret:self.process_image(frameframe,is_videoTrue)defprocess_image(self,file_pathNone,frameNone,is_videoFalse):处理图片并显示结果ifnotis_video:framecv2.imread(file_path)# 使用 YOLOv8 进行检测resultsself.model(frame)# 统计目标数量counts{cls:0forclsinself.class_names}forresultinresults:boxesresult.boxes.xyxy.cpu().numpy()classesresult.boxes.cls.cpu().numpy()confidencesresult.boxes.conf.cpu().numpy()forbox,cls,confinzip(boxes,classes,confidences):class_nameself.model.names[int(cls)]counts[class_name]1ifself.current_classAllorclass_nameself.current_class:x1,y1,x2,y2map(int,box)labelf{class_name}{conf:.2f}cv2.rectangle(frame,(x1,y1),(x2,y2),(0,255,0),2)cv2.putText(frame,label,(x1,y1-10),cv2.FONT_HERSHEY_SIMPLEX,0.9,(0,255,0),2)ifnotis_video:self.results_data.append({file:file_path,**counts,detection_time:pd.Timestamp.now()})# 显示结果ifis_video:self.display_frame(frame)else:self.display_image(frame)defdisplay_image(self,frame):显示图片framecv2.cvtColor(frame,cv2.COLOR_BGR2RGB)height,width,channelframe.shape bytes_per_line3*width q_imgQImage(frame.data,width,height,bytes_per_line,QImage.Format_RGB888)self.label.setPixmap(QPixmap.fromImage(q_img))defdisplay_frame(self,frame):显示视频帧framecv2.cvtColor(frame,cv2.COLOR_BGR2RGB)height,width,channelframe.shape bytes_per_line3*width q_imgQImage(frame.data,width,height,bytes_per_line,QImage.Format_RGB888)self.label.setPixmap(QPixmap.fromImage(q_img))defswitch_class(self,class_name):切换目标类别self.current_classclass_nameifclass_name!AllelseNonedefexport_results(self):导出检测结果为 Excel 或 CSV 文件ifnotself.results_data:QMessageBox.warning(self,警告,没有检测结果可导出)returnfile_path,_QFileDialog.getSaveFileName(self,保存结果,,Excel Files (*.xlsx);;CSV Files (*.csv))iffile_path:dfpd.DataFrame(self.results_data)iffile_path.endswith(.xlsx):df.to_excel(file_path,indexFalse)eliffile_path.endswith(.csv):df.to_csv(file_path,indexFalse)QMessageBox.information(self,成功,结果已导出)if__name____main__:appQApplication([])windowFruitDetector()window.show()app.exec_()5. SE注意力机制添加SESqueeze-and-Excitation注意力机制到主干网络中你需要在训练之前修改YOLOv8的架构。这通常涉及到自定义YOLOv8模型或使用一些第三方扩展包。在YOLOv8中添加SESqueeze-and-Excitation注意力机制可以增强模型对特征的表示能力从而提高检测性能。SE模块的核心思想是通过全局平均池化Global Average Pooling, GAP来获取通道级的上下文信息并通过一个小型全连接网络重新校准每个通道的重要性。以下是将SE模块集成到YOLOv8主干网络中的步骤和代码实现1. SE模块的实现首先我们需要定义一个通用的SE模块。以下是PyTorch实现的SE模块代码importtorchimporttorch.nnasnnclassSEBlock(nn.Module):def__init__(self,channel,reduction16):super(SEBlock,self).__init__()self.fc1nn.Linear(channel,channel//reduction,biasFalse)self.relunn.ReLU(inplaceTrue)self.fc2nn.Linear(channel//reduction,channel,biasFalse)self.sigmoidnn.Sigmoid()defforward(self,x):# Global Average Poolingb,c,_,_x.size()yx.view(b,c,-1).mean(dim2)# [b, c]# Fully Connected Layers for Channel-wise Attentionyself.fc1(y)# [b, c // reduction]yself.relu(y)yself.fc2(y)# [b, c]yself.sigmoid(y).view(b,c,1,1)# [b, c, 1, 1]# Scale the feature mapreturnx*y.expand_as(x)2. 修改YOLOv8主干网络YOLOv8的主干网络基于CSPDarknet架构。为了插入SE模块我们需要找到合适的卷积层并将其与SE模块结合。2.1 找到目标卷积层YOLOv8的主干网络通常由多个Conv模块组成这些模块包含卷积层、批归一化层BatchNorm和激活函数SiLU。我们可以在每个Conv模块后添加SE模块。2.2 修改YOLOv8源码假设你已经克隆了YOLOv8的官方仓库ultralytics我们将修改其主干网络代码。找到主干网络文件YOLOv8的主干网络代码通常位于ultralytics/nn/modules/backbone.py文件中。修改Conv模块在Conv类的基础上扩展加入SE模块fromultralytics.nn.modulesimportConvclassSEConv(Conv):def__init__(self,c1,c2,k1,s1,pNone,g1,actTrue,reduction16):super().__init__(c1,c2,k,s,p,g,act)self.seSEBlock(c2,reduction)defforward(self,x):xsuper().forward(x)# 原始卷积操作xself.se(x)# 添加SE模块returnx替换原始Conv模块在主干网络中用SEConv替换原来的Conv模块。例如在C3模块或Bottleneck模块中fromultralytics.nn.modulesimportBottleneckclassSEBottleneck(Bottleneck):def__init__(self,c1,c2,shortcutTrue,g1,e0.5,reduction16):super().__init__(c1,c2,shortcut,g,e)c_int(c2*e)# 隐藏层通道数self.cv1SEConv(c1,c_,1,1,reductionreduction)self.cv2SEConv(c_,c2,3,1,reductionreduction)更新主干网络将所有使用Conv的地方替换为SEConv或者只在关键位置如瓶颈层添加SE模块。3. 配置训练脚本在训练脚本中加载修改后的模型进行训练fromultralyticsimportYOLOdeftrain_model():# 加载自定义模型已添加SE模块modelYOLO(yolov8n.yaml)# 确保yaml文件指向修改后的主干网络# 开始训练model.train(datadata.yaml,# 数据集配置文件epochs100,# 训练轮数imgsz640,# 输入图片尺寸batch16,# 批次大小devicecuda,# 使用 GPUworkers8,# 数据加载线程数projectruns/train,# 训练结果保存路径nameexp-se# 实验名称)if__name____main__:train_model()4. 验证改进效果完成训练后使用验证代码评估添加SE模块后的模型性能fromultralyticsimportYOLOdefevaluate_model():modelYOLO(runs/train/exp-se/weights/best.pt)# 加载训练好的模型metricsmodel.val()# 在验证集上评估模型print(metrics)if__name____main__:evaluate_model()5. 总结将SE注意力机制集成到了YOLOv8的主干网络中。SE模块通过对通道特征的动态加权增强了模型对重要特征的关注从而提高了检测性能。注意事项计算开销SE模块会增加少量计算开销但通常是可以接受的。超参数调整reduction参数控制SE模块的压缩比例可以根据任务需求调整。实验验证确保在实际应用中对比带SE模块和不带SE模块的模型性能以验证其有效性。