掘金 人工智能 21小时前
基于YOLOv8深度学习的昆虫识别检测系统(YOLOv8+YOLO数据集+UI界面+Python项目源码+模型)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本项目基于YOLOv8深度学习框架,开发了一款智能检测系统,用于识别10类重要农业害虫。系统采用专业数据集训练,可在多种设备上部署,实现对田间害虫的实时监测和预警。通过精准识别,该系统有助于农户科学制定防治策略,减少农药使用,保障粮食安全。

🐛 准确识别:系统能够精确识别包括粘虫、稻飞虱等在内的10种常见农业害虫,为精准防控提供基础。

🌿 减少农药使用:通过精确识别害虫种类,指导农户在最佳时机选择针对性药剂,预计可减少30-50%的农药使用量,降低成本并减少环境污染。

💡 智能预警:系统可结合物联网设备和气象数据,预测虫害发生趋势,实现主动预防,为农业部门提供决策支持。

🌱 促进绿色农业:通过精准识别,支持生物防治等绿色防控技术,减少化学农药依赖,推动农业可持续发展。

📱 适应小农户需求:系统可在智能手机上运行,操作简便,特别适合小规模农户使用,有助于缩小数字鸿沟。

 一、项目介绍

摘要

本项目基于YOLOv8深度学习框架,开发了一套专门针对农业害虫的智能检测系统,能够准确识别10类重要农业害虫,包括'army worm'(粘虫)、'legume blister beetle'(豆芫菁)、'red spider'(红蜘蛛)、'rice gall midge'(稻瘿蚊)、'rice leaf roller'(稻纵卷叶螟)、'rice leafhopper'(稻飞虱)、'rice water weevil'(稻水象甲)、'wheat phloeothrips'(麦管蓟马)、'white backed plant hopper'(白背飞虱)和'yellow rice borer'(二化螟)。系统采用696张训练图像、199张验证图像和100张测试图像构建的专业数据集进行训练和优化,实现了对田间害虫的高精度识别。

该系统可部署于农业无人机、智能虫情测报灯、移动终端等多种设备平台,为农业生产提供实时虫情监测和预警服务。通过自动识别田间害虫种类和数量,系统能够帮助农技人员和种植户及时掌握虫害发生动态,科学制定防治策略,减少农药滥用,提高防治效果,保障粮食安全生产。

项目意义

1. 推动农业害虫智能化监测

传统害虫监测主要依靠人工田间调查,效率低下且主观性强。本系统通过计算机视觉技术实现害虫自动识别,每分钟可处理数百张图像,大幅提高监测效率。系统特别针对水稻、小麦等主粮作物的主要害虫进行优化,如准确区分'rice leafhopper'(稻飞虱)和'white backed plant hopper'(白背飞虱)等形态相似的害虫,为精准防控提供可靠依据。

2. 实现精准科学用药

不同害虫需要不同的防治策略,如'yellow rice borer'(二化螟)和'rice water weevil'(稻水象甲)的防治适期和用药种类各不相同。系统的精确识别能力可避免盲目施药,指导农户在最佳防治时期选择针对性药剂,预计可减少30-50%的农药使用量,降低生产成本和环境污染。

3. 提升病虫害预警能力

系统可整合物联网设备,构建智能虫情监测网络。通过分析害虫发生规律(如'army worm'(粘虫)的迁飞特性),结合气象数据,实现虫害发生趋势预测,为农业部门提供决策支持,变被动防治为主动预防。

4. 促进绿色农业发展

精准识别害虫种类和发生程度,有助于推广生物防治等绿色防控技术。例如针对'rice leaf roller'(稻纵卷叶螟)可优先采用性诱剂,对'red spider'(红蜘蛛)可释放捕食螨,减少化学农药依赖,推动农业可持续发展。

5. 服务农业科研与教育

系统积累的害虫图像数据可为农业科研提供宝贵资料,用于研究害虫发生规律、抗药性监测等。同时,系统可视化的识别结果可作为农业院校教学工具,帮助学生和农技人员快速掌握害虫识别技能。

6. 助力数字农业建设

作为数字农业的重要组成部分,本系统可与无人机巡田、智能灌溉等其他智慧农业系统集成,构建完整的农作物健康管理平台。害虫监测数据可自动生成虫情分布图,为精准农业实施提供数据支撑。

7. 提高农产品质量安全

通过及时准确的虫情监测,避免因防治不及时导致的农产品品质下降。科学用药指导还能减少农药残留,提高稻米等农产品的质量安全水平,增强市场竞争力。

8. 适应小农户需求

系统优化后可在普通智能手机上运行,操作简单,识别快速,特别适合我国小规模农户使用,有助于缩小数字鸿沟,让先进技术惠及普通农民。

本昆虫检测系统的开发应用,将传统农业害虫识别经验转化为可标准化、规模化的智能解决方案,不仅提高了病虫害防治的时效性和准确性,也为实现农药减量增效、保障粮食安全提供了技术支撑。随着系统的不断完善和推广应用,预计将在提高农业生产效率、保护农业生态环境、增加农民收入等方面发挥重要作用,具有良好的社会效益和经济效益。未来,系统可通过增加害虫种类识别范围、优化模型轻量化程度等方式,进一步扩大应用场景,服务更广泛的农业生产需求。


视频下方简介内有项目源码和数据集

基于深度学习的昆虫识别检测系统(YOLOv8+YOLO数据集+UI界面+Python项目源码+模型)_哔哩哔哩_bilibili

基于深度学习的昆虫识别检测系统(YOLOv8+YOLO数据集+UI界面+Python项目源码+模型)

二、项目功能展示

系统功能

图片检测:可对单张图片进行检测,返回检测框及类别信息。
批量图片检测:支持文件夹输入,一次性检测多张图片,生成批量检测结果。
视频检测:支持视频文件输入,检测视频中每一帧的情况。
摄像头实时检测:连接USB 摄像头,实现实时监测,

        该功能允许用户通过单张图片进行目标检测。输入一张图片后,YOLO模型会实时分析图像,识别出其中的目标,并在图像中框出检测到的目标,输出带有目标框的图像。批量图片检测

        用户可以一次性上传多个图片进行批量处理。该功能支持对多个图像文件进行并行处理,并返回每张图像的目标检测结果,适用于需要大规模处理图像数据的应用场景。

        视频检测功能允许用户将视频文件作为输入。YOLO模型将逐帧分析视频,并在每一帧中标记出检测到的目标。最终结果可以是带有目标框的视频文件或实时展示,适用于视频监控和分析等场景。

        该功能支持通过连接摄像头进行实时目标检测。YOLO模型能够在摄像头拍摄的实时视频流中进行目标检测,实时识别并显示检测结果。此功能非常适用于安防监控、无人驾驶、智能交通等应用,提供即时反馈。

核心特点:

三、数据集介绍

本系统的数据集包含以下三部分:

    训练集:696张图像

      训练集用于训练YOLOv8模型,包含10类昆虫的标注数据。每张图像都经过精确标注,标注信息包括昆虫的类别和边界框(bounding box)。数据集中涵盖了不同光照条件、背景复杂度和昆虫姿态的图像,以确保模型的泛化能力。

    验证集:199张图像

      验证集用于在训练过程中评估模型的性能,帮助调整超参数和防止过拟合。验证集的图像分布与训练集相似,但数据独立,以确保评估结果的可靠性。

    测试集:100张图像

      测试集用于最终评估模型的性能,反映模型在真实场景中的表现。测试集的图像未参与训练和验证过程,确保评估结果的客观性。
数据集特点:

训练集

测试集

验证集

数据集配置文件data.yaml

train: \datasets\images\trainval: \datasets\images\valtest: \datasets\images\testnc: 10names: ['army worm', 'legume blister beetle', 'red spider', 'rice gall midge', 'rice leaf roller', 'rice leafhopper', 'rice water weevil', 'wheat phloeothrips', 'white backed plant hopper', 'yellow rice borer'],

数据集制作流程

四、项目环境配置

创建虚拟环境

首先新建一个Anaconda环境,每个项目用不同的环境,这样项目中所用的依赖包互不干扰。

终端输入

conda create -n yolov8 python==3.9

编辑

激活虚拟环境

conda activate yolov8

编辑

安装cpu版本pytorch

pip install torch torchvision torchaudio

编辑

pycharm中配置anaconda

编辑

编辑

安装所需要库

pip install -r requirements.txt

编辑

五、模型训练

训练代码

from ultralytics import YOLOmodel_path = 'yolov8s.pt'data_path = 'datasets/data.yaml'if __name__ == '__main__':    model = YOLO(model_path)    results = model.train(data=data_path,                          epochs=500,                          batch=64,                          device='0',                          workers=0,                          project='runs/detect',                          name='exp',                          )

根据实际情况更换模型yolov8n.yaml (nano):轻量化模型,适合嵌入式设备,速度快但精度略低。yolov8s.yaml (small):小模型,适合实时任务。yolov8m.yaml (medium):中等大小模型,兼顾速度和精度。yolov8b.yaml (base):基本版模型,适合大部分应用场景。yolov8l.yaml (large):大型模型,适合对精度要求高的任务。

训练结果

六、核心代码

编辑

# -*- coding: utf-8 -*-import osimport sysimport timeimport cv2import numpy as npfrom PIL import ImageFontfrom PyQt5.QtCore import Qt, QTimer, QThread, pyqtSignal, QCoreApplicationfrom PyQt5.QtWidgets import (QApplication, QMainWindow, QFileDialog,                             QMessageBox, QWidget, QHeaderView,                             QTableWidgetItem, QAbstractItemView)from ultralytics import YOLO# 自定义模块导入sys.path.append('UIProgram')from UIProgram.UiMain import Ui_MainWindowfrom UIProgram.QssLoader import QSSLoaderfrom UIProgram.precess_bar import ProgressBarimport detect_tools as toolsimport Configclass DetectionApp(QMainWindow):    def __init__(self, parent=None):        super().__init__(parent)        self.ui = Ui_MainWindow()        self.ui.setupUi(self)        # 初始化应用        self._setup_ui()        self._connect_signals()        self._load_stylesheet()        # 模型和资源初始化        self._init_detection_resources()    def _setup_ui(self):        """初始化UI界面设置"""        self.display_width = 700        self.display_height = 500        self.source_path = None        self.camera_active = False        self.video_capture = None        # 配置表格控件        table = self.ui.tableWidget        table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)        table.verticalHeader().setDefaultSectionSize(40)        table.setColumnWidth(0, 80)  # ID列        table.setColumnWidth(1, 200)  # 路径列        table.setColumnWidth(2, 150)  # 类别列        table.setColumnWidth(3, 90)  # 置信度列        table.setColumnWidth(4, 230)  # 位置列        table.setSelectionBehavior(QAbstractItemView.SelectRows)        table.verticalHeader().setVisible(False)        table.setAlternatingRowColors(True)    def _connect_signals(self):        """连接按钮信号与槽函数"""        self.ui.PicBtn.clicked.connect(self._handle_image_input)        self.ui.comboBox.activated.connect(self._update_selection)        self.ui.VideoBtn.clicked.connect(self._handle_video_input)        self.ui.CapBtn.clicked.connect(self._toggle_camera)        self.ui.SaveBtn.clicked.connect(self._save_results)        self.ui.ExitBtn.clicked.connect(QCoreApplication.quit)        self.ui.FilesBtn.clicked.connect(self._process_image_batch)    def _load_stylesheet(self):        """加载CSS样式表"""        style_file = 'UIProgram/style.css'        qss = QSSLoader.read_qss_file(style_file)        self.setStyleSheet(qss)    def _init_detection_resources(self):        """初始化检测相关资源"""        # 加载YOLOv8模型        self.detector = YOLO('runs/detect/exp/weights/best.pt', task='detect')        self.detector(np.zeros((48, 48, 3)))  # 预热模型        # 初始化字体和颜色        self.detection_font = ImageFont.truetype("Font/platech.ttf", 25, 0)        self.color_palette = tools.Colors()        # 初始化定时器        self.frame_timer = QTimer()        self.save_timer = QTimer()    def _handle_image_input(self):        """处理单张图片输入"""        self._stop_video_capture()        file_path, _ = QFileDialog.getOpenFileName(            self, '选择图片', './', "图片文件 (*.jpg *.jpeg *.png)")        if not file_path:            return        self._process_single_image(file_path)    def _process_single_image(self, image_path):        """处理并显示单张图片的检测结果"""        self.source_path = image_path        self.ui.comboBox.setEnabled(True)        # 读取并检测图片        start_time = time.time()        detection_results = self.detector(image_path)[0]        processing_time = time.time() - start_time        # 解析检测结果        boxes = detection_results.boxes.xyxy.tolist()        self.detection_boxes = [list(map(int, box)) for box in boxes]        self.detection_classes = detection_results.boxes.cls.int().tolist()        confidences = detection_results.boxes.conf.tolist()        self.confidence_scores = [f'{score * 100:.2f}%' for score in confidences]        # 更新UI显示        self._update_detection_display(detection_results, processing_time)        self._update_object_selection()        self._show_detection_details()        self._display_results_table(image_path)    def _update_detection_display(self, results, process_time):        """更新检测结果显示"""        # 显示处理时间        self.ui.time_lb.setText(f'{process_time:.3f} s')        # 获取带标注的图像        annotated_img = results.plot()        self.current_result = annotated_img        # 调整并显示图像        width, height = self._calculate_display_size(annotated_img)        resized_img = cv2.resize(annotated_img, (width, height))        qimage = tools.cvimg_to_qpiximg(resized_img)        self.ui.label_show.setPixmap(qimage)        self.ui.label_show.setAlignment(Qt.AlignCenter)        self.ui.PiclineEdit.setText(self.source_path)        # 更新检测数量        self.ui.label_nums.setText(str(len(self.detection_classes)))    def _calculate_display_size(self, image):        """计算适合显示的图像尺寸"""        img_height, img_width = image.shape[:2]        aspect_ratio = img_width / img_height        if aspect_ratio >= self.display_width / self.display_height:            width = self.display_width            height = int(width / aspect_ratio)        else:            height = self.display_height            width = int(height * aspect_ratio)        return width, height    def _update_object_selection(self):        """更新目标选择下拉框"""        options = ['全部']        target_labels = [            f'{Config.names[cls_id]}_{idx}'            for idx, cls_id in enumerate(self.detection_classes)        ]        options.extend(target_labels)        self.ui.comboBox.clear()        self.ui.comboBox.addItems(options)    def _show_detection_details(self, index=0):        """显示检测目标的详细信息"""        if not self.detection_boxes:            self._clear_detection_details()            return        box = self.detection_boxes[index]        self.ui.type_lb.setText(Config.CH_names[self.detection_classes[index]])        self.ui.label_conf.setText(self.confidence_scores[index])        self.ui.label_xmin.setText(str(box[0]))        self.ui.label_ymin.setText(str(box[1]))        self.ui.label_xmax.setText(str(box[2]))        self.ui.label_ymax.setText(str(box[3]))    def _clear_detection_details(self):        """清空检测详情显示"""        self.ui.type_lb.setText('')        self.ui.label_conf.setText('')        self.ui.label_xmin.setText('')        self.ui.label_ymin.setText('')        self.ui.label_xmax.setText('')        self.ui.label_ymax.setText('')    def _display_results_table(self, source_path):        """在表格中显示检测结果"""        table = self.ui.tableWidget        table.setRowCount(0)        table.clearContents()        for idx, (box, cls_id, conf) in enumerate(zip(                self.detection_boxes, self.detection_classes, self.confidence_scores)):            row = table.rowCount()            table.insertRow(row)            # 添加表格项            items = [                QTableWidgetItem(str(row + 1)),  # ID                QTableWidgetItem(source_path),  # 路径                QTableWidgetItem(Config.CH_names[cls_id]),  # 类别                QTableWidgetItem(conf),  # 置信度                QTableWidgetItem(str(box))  # 位置坐标            ]            # 设置文本居中            for item in [items[0], items[2], items[3]]:                item.setTextAlignment(Qt.AlignCenter)            # 添加到表格            for col, item in enumerate(items):                table.setItem(row, col, item)        table.scrollToBottom()    def _process_image_batch(self):        """批量处理图片"""        self._stop_video_capture()        folder = QFileDialog.getExistingDirectory(self, "选择图片文件夹", "./")        if not folder:            return        self.source_path = folder        valid_extensions = {'jpg', 'png', 'jpeg', 'bmp'}        for filename in os.listdir(folder):            filepath = os.path.join(folder, filename)            if (os.path.isfile(filepath) and                    filename.split('.')[-1].lower() in valid_extensions):                self._process_single_image(filepath)                QApplication.processEvents()  # 保持UI响应    def _update_selection(self):        """更新用户选择的检测目标显示"""        selection = self.ui.comboBox.currentText()        if selection == '全部':            boxes = self.detection_boxes            display_img = self.current_result            self._show_detection_details(0)        else:            idx = int(selection.split('_')[-1])            boxes = [self.detection_boxes[idx]]            display_img = self.detector(self.source_path)[0][idx].plot()            self._show_detection_details(idx)        # 更新显示        width, height = self._calculate_display_size(display_img)        resized_img = cv2.resize(display_img, (width, height))        qimage = tools.cvimg_to_qpiximg(resized_img)        self.ui.label_show.clear()        self.ui.label_show.setPixmap(qimage)        self.ui.label_show.setAlignment(Qt.AlignCenter)    def _handle_video_input(self):        """处理视频输入"""        if self.camera_active:            self._toggle_camera()        video_path = self._get_video_path()        if not video_path:            return        self._start_video_processing(video_path)        self.ui.comboBox.setEnabled(False)    def _get_video_path(self):        """获取视频文件路径"""        path, _ = QFileDialog.getOpenFileName(            self, '选择视频', './', "视频文件 (*.avi *.mp4)")        if path:            self.source_path = path            self.ui.VideolineEdit.setText(path)            return path        return None    def _start_video_processing(self, video_path):        """开始处理视频流"""        self.video_capture = cv2.VideoCapture(video_path)        self.frame_timer.start(1)        self.frame_timer.timeout.connect(self._process_video_frame)    def _stop_video_capture(self):        """停止视频捕获"""        if self.video_capture:            self.video_capture.release()            self.frame_timer.stop()            self.camera_active = False            self.ui.CaplineEdit.setText('摄像头未开启')            self.video_capture = None    def _process_video_frame(self):        """处理视频帧"""        ret, frame = self.video_capture.read()        if not ret:            self._stop_video_capture()            return        # 执行目标检测        start_time = time.time()        results = self.detector(frame)[0]        processing_time = time.time() - start_time        # 解析结果        self.detection_boxes = results.boxes.xyxy.int().tolist()        self.detection_classes = results.boxes.cls.int().tolist()        self.confidence_scores = [f'{conf * 100:.2f}%' for conf in results.boxes.conf.tolist()]        # 更新显示        self._update_detection_display(results, processing_time)        self._update_object_selection()        self._show_detection_details()        self._display_results_table(self.source_path)    def _toggle_camera(self):        """切换摄像头状态"""        self.camera_active = not self.camera_active        if self.camera_active:            self.ui.CaplineEdit.setText('摄像头开启')            self.video_capture = cv2.VideoCapture(0)            self._start_video_processing(0)            self.ui.comboBox.setEnabled(False)        else:            self.ui.CaplineEdit.setText('摄像头未开启')            self.ui.label_show.clear()            self._stop_video_capture()    def _save_results(self):        """保存检测结果"""        if not self.video_capture and not self.source_path:            QMessageBox.information(self, '提示', '没有可保存的内容,请先打开图片或视频!')            return        if self.camera_active:            QMessageBox.information(self, '提示', '无法保存摄像头实时视频!')            return        if self.video_capture:            self._save_video_result()        else:            self._save_image_result()    def _save_video_result(self):        """保存视频检测结果"""        confirm = QMessageBox.question(            self, '确认',            '保存视频可能需要较长时间,确定继续吗?',            QMessageBox.Yes | QMessageBox.No)        if confirm == QMessageBox.No:            return        self._stop_video_capture()        saver = VideoSaverThread(            self.source_path, self.detector,            self.ui.comboBox.currentText())        saver.start()        saver.update_ui_signal.connect(self._update_progress)    def _save_image_result(self):        """保存图片检测结果"""        if os.path.isfile(self.source_path):            # 处理单张图片            filename = os.path.basename(self.source_path)            name, ext = filename.rsplit(".", 1)            save_name = f"{name}_detect_result.{ext}"            save_path = os.path.join(Config.save_path, save_name)            cv2.imwrite(save_path, self.current_result)            QMessageBox.information(                self, '完成',                f'图片已保存至: {save_path}')        else:            # 处理文件夹中的图片            valid_exts = {'jpg', 'png', 'jpeg', 'bmp'}            for filename in os.listdir(self.source_path):                if filename.split('.')[-1].lower() in valid_exts:                    filepath = os.path.join(self.source_path, filename)                    name, ext = filename.rsplit(".", 1)                    save_name = f"{name}_detect_result.{ext}"                    save_path = os.path.join(Config.save_path, save_name)                    results = self.detector(filepath)[0]                    cv2.imwrite(save_path, results.plot())            QMessageBox.information(                self, '完成',                f'所有图片已保存至: {Config.save_path}')    def _update_progress(self, current, total):        """更新保存进度"""        if current == 1:            self.progress_dialog = ProgressBar(self)            self.progress_dialog.show()        if current >= total:            self.progress_dialog.close()            QMessageBox.information(                self, '完成',                f'视频已保存至: {Config.save_path}')            return        if not self.progress_dialog.isVisible():            return        percent = int(current / total * 100)        self.progress_dialog.setValue(current, total, percent)        QApplication.processEvents()class VideoSaverThread(QThread):    """视频保存线程"""    update_ui_signal = pyqtSignal(int, int)    def __init__(self, video_path, model, selection):        super().__init__()        self.video_path = video_path        self.detector = model        self.selection = selection        self.active = True        self.colors = tools.Colors()    def run(self):        """执行视频保存"""        cap = cv2.VideoCapture(self.video_path)        fourcc = cv2.VideoWriter_fourcc(*'XVID')        fps = cap.get(cv2.CAP_PROP_FPS)        size = (            int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),            int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))        filename = os.path.basename(self.video_path)        name, _ = filename.split('.')        save_path = os.path.join(            Config.save_path,            f"{name}_detect_result.avi")        writer = cv2.VideoWriter(save_path, fourcc, fps, size)        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))        current_frame = 0        while cap.isOpened() and self.active:            current_frame += 1            ret, frame = cap.read()            if not ret:                break            # 执行检测            results = self.detector(frame)[0]            frame = results.plot()            writer.write(frame)            self.update_ui_signal.emit(current_frame, total_frames)        # 释放资源        cap.release()        writer.release()    def stop(self):        """停止保存过程"""        self.active = Falseif __name__ == "__main__":    app = QApplication(sys.argv)    window = DetectionApp()    window.show()    sys.exit(app.exec_())

七、项目源码

演示与介绍视频:

视频下方简介内有项目源码和数据集

基于深度学习的昆虫识别检测系统(YOLOv8+YOLO数据集+UI界面+Python项目源码+模型)_哔哩哔哩_bilibili

基于深度学习的昆虫识别检测系统(YOLOv8+YOLO数据集+UI界面+Python项目源码+模型)

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

YOLOv8 农业害虫 智能检测 病虫害防治
相关文章