在精准农业领域,生菜生长周期的自动化监测一直是个技术难点。传统的人工观察方法不仅效率低下,而且难以实现大规模种植场景下的实时监控。为了解决这个问题,我们开发了一套基于YOLOv11深度学习模型的生菜生长周期智能检测系统。
这个系统能够自动识别和分类生菜在不同生长阶段的形态特征,主要检测5个关键类别:'Ready'(成熟期)、'empty_pod'(空栽培槽)、'germination'(发芽期)、'pod'(栽培槽)和'young'(幼苗期)。系统集成了完整的YOLOv11算法实现、专门定制的生菜生长数据集、用户友好的UI操作界面(包含登录注册功能),并提供了完整的Python项目源码和预训练模型。
系统采用模块化设计,主要包含以下几个核心组件:
选择YOLOv11作为核心检测模型主要基于以下考虑:
对于UI框架,我们选择了PyQt5,主要因为:
我们构建了一个专门针对生菜生长周期检测的数据集,具有以下特点:
为了提高模型的泛化能力,我们采用了多种数据增强技术:
数据集配置文件采用标准YOLO格式:
yaml复制train: F:\生菜生长周期检测数据集\images\train
val: F:\生菜生长周期检测数据集\images\val
test: # test images (optional)
# Classes
nc: 5
names: ['Ready', 'empty_pod', 'germination', 'pod', 'young']
我们使用Anaconda创建独立的Python环境,确保依赖隔离:
bash复制conda create -n yolov11 python==3.9
conda activate yolov11
pip install torch torchvision torchaudio
pip install -r requirements.txt
训练脚本主要参数配置如下:
python复制from ultralytics import YOLO
model_path = 'yolo11s.pt'
data_path = 'data.yaml'
if __name__ == '__main__':
model = YOLO(model_path)
results = model.train(data=data_path,
epochs=100,
batch=8,
device='0',
workers=0,
project='runs',
name='exp',
)
关键参数说明:
batch=8:根据GPU显存大小设置,显存不足时可适当减小epochs=100:经过实验验证,100轮训练可以达到较好的收敛效果device='0':指定使用第一块GPU进行训练workers=0:在Windows系统下建议设置为0以避免多进程问题YOLOv11提供了多种预训练模型,可根据实际需求选择:
在我们的应用中,考虑到需要在普通PC上实现实时检测,最终选择了yolov11s作为基础模型。
用户管理模块实现了基本的登录注册功能,核心代码如下:
python复制def handle_login(self):
username = self.username_input.text().strip()
password = self.password_input.text().strip()
if not username or not password:
QMessageBox.warning(self, "警告", "用户名和密码不能为空!")
return
if username in self.accounts and self.accounts[username] == password:
self.accept() # 验证通过
else:
QMessageBox.warning(self, "错误", "用户名或密码错误!")
def handle_register(self):
if len(password) < 6: # 密码长度≥6位
QMessageBox.warning(self, "警告", "密码长度至少为6位!")
系统支持三种检测模式:
检测线程的核心实现:
python复制class DetectionThread(QThread):
frame_received = pyqtSignal(np.ndarray, np.ndarray, list)
finished_signal = pyqtSignal()
def __init__(self, model, source, conf, iou, parent=None):
super().__init__(parent)
self.model = model
self.source = source
self.conf = conf
self.iou = iou
self.running = True
def run(self):
try:
if isinstance(self.source, int) or self.source.endswith(('.mp4', '.avi', '.mov')):
cap = cv2.VideoCapture(self.source)
while self.running and cap.isOpened():
ret, frame = cap.read()
if not ret:
break
original_frame = frame.copy()
results = self.model(frame, conf=self.conf, iou=self.iou)
annotated_frame = results[0].plot()
detections = []
for result in results:
for box in result.boxes:
class_id = int(box.cls)
class_name = self.model.names[class_id]
confidence = float(box.conf)
x, y, w, h = box.xywh[0].tolist()
detections.append((class_name, confidence, x, y))
self.frame_received.emit(
cv2.cvtColor(original_frame, cv2.COLOR_BGR2RGB),
cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB),
detections
)
time.sleep(0.03) # 控制帧率
cap.release()
else:
frame = cv2.imread(self.source)
if frame is not None:
original_frame = frame.copy()
results = self.model(frame, conf=self.conf, iou=self.iou)
annotated_frame = results[0].plot()
detections = []
for result in results:
for box in result.boxes:
class_id = int(box.cls)
class_name = self.model.names[class_id]
confidence = float(box.conf)
x, y, w, h = box.xywh[0].tolist()
detections.append((class_name, confidence, x, y))
self.frame_received.emit(
cv2.cvtColor(original_frame, cv2.COLOR_BGR2RGB),
cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB),
detections
)
except Exception as e:
print(f"Detection error: {e}")
finally:
self.finished_signal.emit()
系统提供了灵活的检测参数配置:
参数同步实现代码:
python复制def update_confidence(self, value):
confidence = value / 100.0
self.confidence_spinbox.setValue(confidence)
self.confidence_label.setText(f"置信度阈值: {confidence:.2f}")
def update_iou(self, value):
iou = value / 100.0
self.iou_spinbox.setValue(iou)
为了避免检测过程中界面卡顿,我们采用了多线程架构:
系统提供了丰富的可视化功能:
可视化核心代码:
python复制def display_image(self, label, image):
q_img = QImage(image.data, w, h, bytes_per_line, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(q_img)
label.setPixmap(pixmap.scaled(label.size(), Qt.KeepAspectRatio))
def add_detection_result(self, class_name, confidence, x, y):
self.results_table.insertRow(row)
items = [
QTableWidgetItem(class_name),
QTableWidgetItem(f"{confidence:.2f}"),
QTableWidgetItem(f"{x:.1f}"),
QTableWidgetItem(f"{y:.1f}")
]
系统采用了现代化的UI设计:
UI样式示例:
python复制def create_button(self, text, color):
return f"""
QPushButton {{
border: 1px solid {color};
color: {color};
border-radius: 6px;
}}
QPushButton:hover {{
background-color: {self.lighten_color(color, 10)};
box-shadow: 0 0 10px {color};
}}
"""
在151张测试集图像上的评估结果:
平均精度(mAP@0.5):达到92.3%
各类别精度:
推理速度:在RTX 3060显卡上达到45FPS
系统已在多个生菜种植基地进行试点应用,主要用途包括:
问题1:训练过程中出现显存不足错误
解决方案:
问题2:模型收敛速度慢
解决方案:
问题1:检测结果不准确
解决方案:
问题2:实时检测卡顿
解决方案:
问题1:无法打开摄像头
解决方案:
问题2:界面显示异常
解决方案:
在实际部署过程中,我们发现光照条件的变化对检测精度影响较大。为此,我们增加了自动白平衡和曝光补偿功能,显著提升了系统在复杂光照环境下的稳定性。另一个实用技巧是在模型训练时,特意加入了不同时段拍摄的图像数据,使模型能够适应一天中不同时间的光照变化。