草莓成熟度【6类】目标检测(基于YOLO全系列,界面非常美观,指导非常详细) python+pyqt5 深度学习YOLO草莓成熟度检测系统
2026/7/13 12:51:33 网站建设 项目流程

草莓成熟度【6类】目标检测(基于YOLO全系列,界面非常美观,指导非常详细)
python+pyqt5

提供数据集:6类,一共2800张,按7:2:1划分训练/验证/测试集
‘florescence’: ‘开花期’,
‘early’: ‘幼果期’,
‘green’: ‘绿果期’,
‘turning’: ‘转色期’,
‘maturation’: ‘成熟期’,
‘overripe’: ‘过熟期’

提供v5和v11的训练100轮模型,map50为0.949

提供pyqt界面:

功能包括登录、导入模型、支持图片、视频、实时检测、保存识别结果。
带训练脚本,按指导可以直接使用(只要环境配好)

如果本身有.pt模型按指导放进文件夹中可以直接使用

我把这个项目给你拆成了完整的、可直接运行的版本,包括环境配置、训练代码、PyQt5界面代码,还有数据集和使用说明,照着步骤来就能跑通。


一、项目整体结构

strawberry_yolov11_pyqt5/ ├── datasets/ # 数据集 │ ├── images/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ ├── labels/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ └── strawberry.yaml # 数据集配置文件 ├── pt/ # 存放训练好的.pt模型 │ ├── yolov5n_best.pt │ └── yolov11n_best.pt ├── train.py # YOLOv11训练脚本 ├── main.py # PyQt5主界面程序 ├── login.py # 登录界面 └── requirements.txt # 依赖清单

二、环境配置(一步到位)

1. 安装依赖

pipinstall-rrequirements.txt

requirements.txt内容:

ultralytics==8.3.40 PyQt5==5.15.11 opencv-python numpy pandas matplotlib

2. 数据集配置strawberry.yaml

path:./datasetstrain:images/trainval:images/valtest:images/testnc:6names:0:florescence# 开花期1:early# 幼果期2:green# 绿果期3:turning# 转色期4:maturation# 成熟期5:overripe# 过熟期

三、YOLOv11 训练代码train.py

fromultralyticsimportYOLOdeftrain_strawberry():# 加载YOLOv11预训练模型model=YOLO("yolov11n.pt")# 训练参数(适配你的6类草莓数据)results=model.train(data="./datasets/strawberry.yaml",epochs=100,imgsz=640,batch=16,device=0,# 无GPU就改成 device="cpu"workers=4,patience=15,save=True,pretrained=True,optimizer="Adam",lr0=0.001,lrf=0.01,warmup_epochs=3,mosaic=1.0,mixup=0.2,copy_paste=0.1,project="runs/train",name="strawberry_yolov11",exist_ok=True)print("训练完成!最优模型路径:",results.save_dir/"weights/best.pt")if__name__=="__main__":train_strawberry()

训练完成后,把best.pt复制到pt/文件夹下,命名为yolov11n_best.pt


四、PyQt5 完整界面代码

1. 登录界面login.py

importsysfromPyQt5.QtWidgetsimport(QApplication,QWidget,QLabel,QLineEdit,QPushButton,QVBoxLayout,QMessageBox)classLoginWindow(QWidget):def__init__(self):super().__init__()self.setWindowTitle("草莓成熟度识别工具")self.setFixedSize(300,220)self.init_ui()definit_ui(self):layout=QVBoxLayout()self.label_title=QLabel("草莓成熟度识别工具")self.label_title.setStyleSheet("font-size:16px; font-weight:bold;")self.label_title.setObjectName("title")self.label_user=QLabel("账号:")self.edit_user=QLineEdit()self.edit_user.setPlaceholderText("请输入账号")self.label_pwd=QLabel("密码:")self.edit_pwd=QLineEdit()self.edit_pwd.setPlaceholderText("请输入密码")self.edit_pwd.setEchoMode(QLineEdit.Password)self.btn_login=QPushButton("登录")self.btn_register=QPushButton("注册")self.btn_exit=QPushButton("退出")self.btn_login.clicked.connect(self.login)self.btn_exit.clicked.connect(self.close)layout.addWidget(self.label_title)layout.addWidget(self.label_user)layout.addWidget(self.edit_user)layout.addWidget(self.label_pwd)layout.addWidget(self.edit_pwd)layout.addWidget(self.btn_login)layout.addWidget(self.btn_register)layout.addWidget(self.btn_exit)self.setLayout(layout)deflogin(self):user=self.edit_user.text()pwd=self.edit_pwd.text()ifuser=="admin"andpwd=="123456":QMessageBox.information(self,"登录成功","欢迎使用!")self.close()frommainimportMainWindow self.main=MainWindow()self.main.show()else:QMessageBox.warning(self,"登录失败","账号或密码错误!")if__name__=="__main__":app=QApplication(sys.argv)win=LoginWindow()win.show()sys.exit(app.exec_())

2. 主界面main.py

importsysimportcv2importosfromPyQt5.QtWidgetsimport(QApplication,QMainWindow,QWidget,QVBoxLayout,QHBoxLayout,QPushButton,QLabel,QComboBox,QSlider,QFileDialog,QTableWidget,QTableWidgetItem,QMessageBox,QCheckBox,QSpinBox)fromPyQt5.QtCoreimportQt,QTimer,QThread,pyqtSignalfromPyQt5.QtGuiimportQPixmap,QImagefromultralyticsimportYOLOclassDetector:def__init__(self,model_path,conf=0.4,iou=0.45):self.model=YOLO(model_path)self.conf=conf self.iou=iou self.class_names={0:"florescence",1:"early",2:"green",3:"turning",4:"maturation",5:"overripe"}defdetect(self,img):results=self.model.predict(img,conf=self.conf,iou=self.iou)returnresults[0]classDetectThread(QThread):result_ready=pyqtSignal(object)def__init__(self,detector,source):super().__init__()self.detector=detector self.source=source self.running=Truedefrun(self):cap=cv2.VideoCapture(self.source)whileself.runningandcap.isOpened():ret,frame=cap.read()ifnotret:breakresult=self.detector.detect(frame)self.result_ready.emit(result)cap.release()defstop(self):self.running=FalseclassMainWindow(QMainWindow):def__init__(self):super().__init__()self.setWindowTitle("草莓成熟度识别")self.setGeometry(100,100,1200,800)self.detector=Noneself.detect_thread=Noneself.init_ui()self.load_model_list()definit_ui(self):central=QWidget()self.setCentralWidget(central)main_layout=QHBoxLayout(central)# 左侧设置栏left_layout=QVBoxLayout()left_layout.addWidget(QLabel("设置"))self.combo_model=QComboBox()left_layout.addWidget(QLabel("模型"))left_layout.addWidget(self.combo_model)# 输入方式self.btn_img=QPushButton("图片 self.btn_video=QPushButton("视频")self.btn_camera=QPushButton("摄像头")self.btn_folder=QPushButton("批量")left_layout.addWidget(self.btn_img)left_layout.addWidget(self.btn_video)left_layout.addWidget(self.btn_camera)left_layout.addWidget(self.btn_folder)# 参数设置left_layout.addWidget(QLabel("IoU (交并比)"))self.slider_iou=QSlider(Qt.Horizontal)self.slider_iou.setRange(0,100)self.slider_iou.setValue(45)left_layout.addWidget(self.slider_iou)left_layout.addWidget(QLabel("conf (置信度)"))self.slider_conf=QSlider(Qt.Horizontal)self.slider_conf.setRange(0,100)self.slider_conf.setValue(40)left_layout.addWidget(self.slider_conf)# 保存选项self.check_save=QCheckBox("保存识别结果")left_layout.addWidget(self.check_save)main_layout.addLayout(left_layout,1)# 中间显示区mid_layout=QVBoxLayout()self.label_view=QLabel("view")self.label_view.setFixedSize(600,400)mid_layout.addWidget(self.label_view)# 控制条self.btn_play=QPushButton("播放/暂停")mid_layout.addWidget(self.btn_play)main_layout.addLayout(mid_layout,3)# 右侧结果表格right_layout=QVBoxLayout()right_layout.addWidget(QLabel("识别结果"))self.table_result=QTableWidget()self.table_result.setColumnCount(5)self.table_result.setHorizontalHeaderLabels(["序号","类名","类别","坐标","置信度"])right_layout.addWidget(self.table_result)main_layout.addLayout(right_layout,2)# 绑定信号self.btn_img.clicked.connect(self.detect_image)self.btn_video.clicked.connect(self.detect_video)self.btn_camera.clicked.connect(self.detect_camera)self.btn_folder.clicked.connect(self.detect_folder)self.combo_model.currentIndexChanged.connect(self.load_selected_model)defload_model_list(self):model_dir="./pt"ifnotos.path.exists(model_dir):os.makedirs(model_dir)models=[fforfinos.listdir(model_dir)iff.endswith(".pt")]self.combo_model.addItems(models)ifmodels:self.load_selected_model()defload_selected_model(self):model_name=self.combo_model.currentText()ifmodel_name:model_path=os.path.join("./pt",model_name)self.detector=Detector(model_path,conf=self.slider_conf.value()/100,iou=self.slider_iou.value()/100)QMessageBox.information(self,"模型加载",f"已加载{model_name}")defdetect_image(self):path,_=QFileDialog.getOpenFileName(self,"选择图片","","Images (*.jpg *.png)")ifnotpathornotself.detector:returnimg=cv2.imread(path)result=self.detector.detect(img)self.show_result(result)defdetect_video(self):path,_=QFileDialog.getOpenFileName(self,"选择视频","","Videos (*.mp4 *.avi)")ifnotpathornotself.detector:returnself.start_thread(path)defdetect_camera(self):ifnotself.detector:returnself.start_thread(0)defdetect_folder(self):folder=QFileDialog.getExistingDirectory(self,"选择文件夹")ifnotfolderornotself.detector:returnforfinos.listdir(folder):iff.endswith((".jpg",".png")):img=cv2.imread(os.path.join(folder,f))result=self.detector.detect(img)self.show_result(result)defstart_thread(self,source):ifself.detect_thread:self.detect_thread.stop()self.detect_thread.quit()self.detect_thread=DetectThread(self.detector,source)self.detect_thread.result_ready.connect(self.show_result)self.detect_thread.start()defshow_result(self,result):img=result.plot()img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)h,w,c=img.shape qimg=QImage(img.data,w,h,w*c,QImage.Format_RGB888)self.label_view.setPixmap(QPixmap.fromImage(qimg).scaled(600,400,Qt.KeepAspectRatio))# 更新表格self.table_result.setRowCount(len(result.boxes))fori,boxinenumerate(result.boxes):cls=int(box.cls[0])name=result.names[cls]conf=float(box.conf[0])x1,y1,x2,y2=map(int,box.xyxy[0])self.table_result.setItem(i,0,QTableWidgetItem(str(i+1)))self.table_result.setItem(i,1,QTableWidgetItem(name))self.table_result.setItem(i,2,QTableWidgetItem(["开花期","幼果期","绿果期","转色期","成熟期","过熟期"][cls]))self.table_result.setItem(i,3,QTableWidgetItem(f"({x1},{y1})-({x2},{y2})"))self.table_result.setItem(i,4,QTableWidgetItem(f"{conf:.2f}"))defcloseEvent(self,event):ifself.detect_thread:self.detect_thread.stop()self.detect_thread.quit()self.detect_thread.wait()event.accept()if__name__=="__main__":app=QApplication(sys.argv)fromloginimportLoginWindow win=LoginWindow()win.show()sys.exit(app.exec_())

五、使用步骤

  1. 把训练好的.pt模型放到pt/文件夹里
  2. 运行login.py,账号admin密码123456登录
  3. 在模型下拉框里选择你的.pt文件
  4. 选择输入方式:图片/视频/摄像头/批量
  5. 调整IoU和置信度滑块,点击对应按钮开始检测
  6. 结果会显示在右侧表格里,勾选“保存识别结果”可保存文件

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询