背景意义

随着农业现代化的不断推进,牲畜养殖业在全球范围内日益受到重视。牲畜的健康管理、生产效率提升以及资源的合理利用都依赖于对牲畜的精准监测与管理。传统的牲畜监测方法往往依赖人工观察,效率低下且容易受到人为因素的影响。近年来,计算机视觉技术的快速发展为牲畜监测提供了新的解决方案。特别是基于深度学习的图像分割技术,能够实现对牲畜的自动识别与分类,为养殖业的智能化转型提供了强有力的支持。

在众多图像分割算法中,YOLO(You Only Look Once)系列模型因其高效的实时检测能力而受到广泛关注。YOLOv8作为该系列的最新版本,具备了更高的准确性和更快的处理速度,适用于复杂的农业环境。然而,尽管YOLOv8在目标检测方面表现出色,但在细粒度的实例分割任务中仍存在一定的局限性。为此,基于改进YOLOv8的牲畜图像分割系统的研究显得尤为重要。

本研究所使用的数据集M-vet包含2000张图像,涵盖了10个类别的牲畜,包括牛、羊、猪、兔子等。这些类别不仅具有较高的经济价值,而且在养殖管理中各自面临不同的挑战。通过对这些牲畜进行实例分割,可以实现对每一只动物的独立识别,从而为后续的健康监测、行为分析和饲养管理提供数据支持。此外,数据集中包含的不同视角(前、后、左、右)和状态(有效、无效)也为模型的训练提供了丰富的样本,有助于提高模型的鲁棒性和适应性。

研究的意义不仅体现在技术层面,更在于其对农业生产方式的深远影响。通过构建基于改进YOLOv8的牲畜图像分割系统,可以有效提高牲畜监测的自动化水平,降低人工成本,提升管理效率。同时,该系统能够实时监测牲畜的健康状况,及时发现潜在的疾病风险,从而提高牲畜的存活率和生产效益。此外,精确的图像分割技术还可以为养殖场提供数据支持,帮助农户优化饲养策略,实现资源的合理配置。

综上所述,基于改进YOLOv8的牲畜图像分割系统的研究不仅具有重要的学术价值,也为实际应用提供了切实可行的解决方案。通过推动这一领域的研究进展,将为农业智能化发展提供新思路,助力实现可持续的农业生产模式。

图片效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数据集信息

在本研究中,我们采用了名为“M-vet”的数据集,以训练和改进YOLOv8-seg的牲畜图像分割系统。该数据集专注于农业和畜牧业领域,旨在通过精确的图像分割技术,提高牲畜的识别和管理效率。M-vet数据集包含10个不同的类别,具体包括:牛(cow)、前视(front)、山羊(goat)、无效(invalid)、左侧(left)、猪(pig)、兔子(rabbit)、后视(rear)、右侧(right)和羊(sheep)。这些类别的选择不仅涵盖了常见的家畜种类,还考虑到了不同的视角和状态,为模型的训练提供了丰富的多样性。

在数据集的构建过程中,研究团队进行了广泛的图像采集,确保每个类别都具有足够的样本量和多样性。牛、羊、猪等常见牲畜的图像来自不同的环境和条件,包括农场、牧场以及其他相关场所。这种多样化的图像来源有助于模型在不同的场景下进行有效的识别和分割。此外,前视、左侧、右侧和后视等不同角度的图像,使得模型能够学习到牲畜在各种姿态下的特征,增强了其鲁棒性。

在数据集的标注过程中,采用了高精度的分割标注技术,确保每个类别的边界清晰可辨。无效类别的引入则是为了帮助模型学习如何处理不完整或模糊的图像,这对于实际应用中的图像处理至关重要。通过对无效图像的标注,模型能够更好地适应现实世界中可能遇到的各种挑战,提高其在复杂环境下的表现。

M-vet数据集的构建不仅考虑了图像的数量和质量,还注重了数据的平衡性。每个类别的样本数量经过精心设计,以避免模型在训练过程中出现偏向某一类别的现象。这种平衡性确保了模型在识别和分割各类牲畜时的公平性和准确性,使其能够在实际应用中更好地服务于农业生产和管理。

通过使用M-vet数据集,我们的目标是显著提升YOLOv8-seg在牲畜图像分割任务中的性能。该数据集的多样性和高质量标注将为模型提供强有力的支持,使其能够在实际应用中实现更高的精度和效率。随着技术的不断进步,图像分割在农业领域的应用前景广阔,M-vet数据集的使用将为未来的研究和实践奠定坚实的基础。通过不断优化和改进,我们期待该系统能够为牲畜管理提供更加智能化的解决方案,推动农业现代化的发展。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

核心代码

以下是经过精简和注释的核心代码部分,保留了自动标注功能的主要逻辑:

# 导入必要的库
from pathlib import Path
from ultralytics import SAM, YOLO

def auto_annotate(data, det_model='yolov8x.pt', sam_model='sam_b.pt', device='', output_dir=None):
    """
    使用YOLO目标检测模型和SAM分割模型自动标注图像。

    参数:
        data (str): 包含待标注图像的文件夹路径。
        det_model (str, optional): 预训练的YOLO检测模型,默认为'yolov8x.pt'。
        sam_model (str, optional): 预训练的SAM分割模型,默认为'sam_b.pt'。
        device (str, optional): 模型运行的设备,默认为空字符串(CPU或可用的GPU)。
        output_dir (str | None | optional): 保存标注结果的目录,默认为与'data'相同目录下的'labels'文件夹。

    示例:
        auto_annotate(data='ultralytics/assets', det_model='yolov8n.pt', sam_model='mobile_sam.pt')
    """
    # 加载YOLO和SAM模型
    det_model = YOLO(det_model)  # 初始化YOLO检测模型
    sam_model = SAM(sam_model)    # 初始化SAM分割模型

    # 将数据路径转换为Path对象
    data = Path(data)
    # 如果未指定输出目录,则创建一个默认输出目录
    if not output_dir:
        output_dir = data.parent / f'{data.stem}_auto_annotate_labels'
    Path(output_dir).mkdir(exist_ok=True, parents=True)  # 创建输出目录

    # 使用YOLO模型进行目标检测
    det_results = det_model(data, stream=True, device=device)

    # 遍历检测结果
    for result in det_results:
        class_ids = result.boxes.cls.int().tolist()  # 获取检测到的类别ID
        if len(class_ids):  # 如果检测到目标
            boxes = result.boxes.xyxy  # 获取边界框坐标
            # 使用SAM模型进行分割,传入边界框
            sam_results = sam_model(result.orig_img, bboxes=boxes, verbose=False, save=False, device=device)
            segments = sam_results[0].masks.xyn  # 获取分割结果

            # 将分割结果写入文本文件
            with open(f'{str(Path(output_dir) / Path(result.path).stem)}.txt', 'w') as f:
                for i in range(len(segments)):
                    s = segments[i]
                    if len(s) == 0:  # 如果没有分割结果,跳过
                        continue
                    segment = map(str, segments[i].reshape(-1).tolist())  # 将分割结果转换为字符串
                    f.write(f'{class_ids[i]} ' + ' '.join(segment) + '\n')  # 写入类别ID和分割坐标

代码注释说明:

  1. 导入库:引入Path用于处理文件路径,SAMYOLO用于加载相应的模型。
  2. 函数定义auto_annotate函数负责自动标注图像,接受多个参数以配置模型和输出。
  3. 模型加载:通过YOLOSAM类初始化检测和分割模型。
  4. 输出目录处理:如果未指定输出目录,则根据输入数据路径自动创建一个输出目录。
  5. 目标检测:使用YOLO模型对输入数据进行目标检测,返回检测结果。
  6. 结果处理:遍历检测结果,提取类别ID和边界框信息,调用SAM模型进行分割。
  7. 结果保存:将分割结果和类别ID写入文本文件,以便后续使用。```
    这个文件是一个用于自动标注图像的Python脚本,主要依赖于YOLO(You Only Look Once)目标检测模型和SAM(Segment Anything Model)分割模型。其主要功能是通过YOLO模型检测图像中的对象,并利用SAM模型对检测到的对象进行分割,最终生成标注结果。

首先,文件导入了必要的库,包括Path用于处理文件路径,以及SAMYOLO模型的实现。接着定义了一个名为auto_annotate的函数,该函数接受多个参数,包括数据路径、检测模型、分割模型、设备类型和输出目录。

在函数内部,首先通过传入的模型名称实例化YOLO和SAM模型。接着,使用Path库将数据路径转换为Path对象。如果没有指定输出目录,函数会自动创建一个名为“_auto_annotate_labels”的文件夹,用于存储标注结果。

接下来,使用YOLO模型对指定路径下的图像进行目标检测,结果以流的形式返回。对于每个检测结果,函数提取出检测到的类别ID和边界框信息。如果检测到的类别ID不为空,函数会调用SAM模型对原始图像及其对应的边界框进行分割。分割结果以掩码的形式返回。

最后,函数将每个分割结果写入到一个文本文件中,文件名与原始图像相同,后缀为.txt。每行记录了类别ID和对应的分割坐标信息,方便后续的分析和使用。

总体而言,这个脚本提供了一种高效的方式来自动化图像标注过程,结合了目标检测和图像分割技术,适用于需要大量标注数据的计算机视觉任务。


```python
import base64
import streamlit as st

# 读取图片并转换为 Base64 编码
def get_base64_of_bin_file(bin_file):
    # 以二进制模式打开文件
    with open(bin_file, 'rb') as file:
        # 读取文件内容
        data = file.read()
    # 将读取的二进制数据进行 Base64 编码,并返回字符串格式
    return base64.b64encode(data).decode()

# 定义自定义的 CSS 样式
def def_css_hitml():
    st.markdown("""
        <style>
        /* 全局样式 */
        .css-2trqyj, .css-1d391kg, .st-bb, .st-at {
            font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; /* 设置字体 */
            background-color: #cadefc; /* 设置背景颜色 */
            color: #21618C; /* 设置字体颜色 */
        }

        /* 按钮样式 */
        .stButton > button {
            border: none; /* 去掉边框 */
            color: white; /* 字体颜色为白色 */
            padding: 10px 20px; /* 设置内边距 */
            text-align: center; /* 文本居中 */
            text-decoration: none; /* 去掉下划线 */
            display: inline-block; /* 使按钮为块级元素 */
            font-size: 16px; /* 设置字体大小 */
            margin: 2px 1px; /* 设置外边距 */
            cursor: pointer; /* 鼠标悬停时显示为手型 */
            border-radius: 8px; /* 设置圆角 */
            background-color: #9896f1; /* 设置背景颜色 */
            box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2); /* 设置阴影效果 */
            transition-duration: 0.4s; /* 设置过渡效果时间 */
        }
        .stButton > button:hover {
            background-color: #5499C7; /* 鼠标悬停时改变背景颜色 */
            color: white; /* 鼠标悬停时字体颜色为白色 */
            box-shadow: 0 8px 12px 0 rgba(0,0,0,0.24); /* 鼠标悬停时改变阴影效果 */
        }

        /* 侧边栏样式 */
        .css-1lcbmhc.e1fqkh3o0 {
            background-color: #154360; /* 设置侧边栏背景颜色 */
            color: #FDFEFE; /* 设置侧边栏字体颜色 */
            border-right: 2px solid #DDD; /* 设置右边框 */
        }

        /* Radio 按钮样式 */
        .stRadio > label {
            display: inline-flex; /* 设置为弹性盒子布局 */
            align-items: center; /* 垂直居中对齐 */
            cursor: pointer; /* 鼠标悬停时显示为手型 */
        }
        .stRadio > label > span:first-child {
            background-color: #FFF; /* 设置选项框背景颜色 */
            border: 1px solid #CCC; /* 设置边框 */
            width: 1em; /* 设置宽度 */
            height: 1em; /* 设置高度 */
            border-radius: 50%; /* 设置圆角 */
            margin-right: 10px; /* 设置右边距 */
            display: inline-block; /* 设置为块级元素 */
        }

        /* 滑块样式 */
        .stSlider .thumb {
            background-color: #2E86C1; /* 设置滑块的颜色 */
        }
        .stSlider .track {
            background-color: #DDD; /* 设置滑轨的颜色 */
        }

        /* 表格样式 */
        table {
            border-collapse: collapse; /* 合并边框 */
            margin: 25px 0; /* 设置外边距 */
            font-size: 18px; /* 设置字体大小 */
            font-family: sans-serif; /* 设置字体 */
            min-width: 400px; /* 设置最小宽度 */
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); /* 设置阴影效果 */
        }
        thead tr {
            background-color: #a8d8ea; /* 设置表头背景颜色 */
            color: #ffcef3; /* 设置表头字体颜色 */
            text-align: left; /* 设置文本左对齐 */
        }
        th, td {
            padding: 15px 18px; /* 设置单元格内边距 */
        }
        tbody tr {
            border-bottom: 2px solid #ddd; /* 设置底部边框 */
        }
        tbody tr:nth-of-type(even) {
            background-color: #D6EAF8; /* 设置偶数行背景颜色 */
        }
        tbody tr:last-of-type {
            border-bottom: 3px solid #5499C7; /* 设置最后一行底部边框 */
        }
        tbody tr:hover {
            background-color: #AED6F1; /* 鼠标悬停时改变背景颜色 */
        }
        </style>
        """, unsafe_allow_html=True)  # 允许使用 HTML 代码

代码说明:

  1. 导入模块:导入 base64streamlit 模块,前者用于处理 Base64 编码,后者用于构建 web 应用。
  2. get_base64_of_bin_file 函数:该函数接收一个二进制文件路径,读取文件内容并将其转换为 Base64 编码的字符串。
  3. def_css_hitml 函数:该函数定义了应用的 CSS 样式,包括全局样式、按钮样式、侧边栏样式、单选按钮样式、滑块样式和表格样式。通过 st.markdown 方法将 CSS 代码插入到 Streamlit 应用中。```
    这个程序文件 ui_style.py 是一个用于设置 Streamlit 应用程序界面样式的 Python 脚本。它主要包含两个功能:读取图片并将其转换为 Base64 格式,以及定义自定义的 CSS 样式。

首先,文件导入了 base64streamlit 库。base64 用于处理二进制数据的编码,而 streamlit 是一个用于构建数据应用的库。

接下来,定义了一个名为 get_base64_of_bin_file 的函数。这个函数接受一个二进制文件的路径作为参数,打开该文件并读取其内容。然后,它使用 base64.b64encode 方法将读取到的二进制数据编码为 Base64 格式,并将其解码为字符串形式返回。这种方法通常用于在网页中嵌入图片或其他二进制数据。

然后,定义了 def_css_hitml 函数,该函数使用 st.markdown 方法将一段 CSS 样式代码插入到 Streamlit 应用中。该 CSS 样式代码用于全局样式、按钮样式、侧边栏样式、单选按钮样式、滑块样式、表格样式等多个方面。

在全局样式部分,设置了字体和背景颜色,使整个应用看起来更加美观。按钮样式部分则定义了按钮的外观,包括边框、颜色、内边距、字体大小、边距、圆角和阴影效果,同时还设置了按钮在鼠标悬停时的样式变化。侧边栏样式部分设置了侧边栏的背景颜色和文本颜色。

对于单选按钮和滑块,CSS 样式定义了它们的外观,使其更具吸引力。表格样式部分则设置了表格的边框、阴影、字体、背景颜色等,使表格在视觉上更加清晰易读。

总的来说,这个文件通过自定义 CSS 样式,使得 Streamlit 应用的界面更加美观和用户友好,同时提供了一个读取二进制文件并转换为 Base64 的功能,方便在应用中使用。


```python
# 导入必要的库
from copy import copy
import numpy as np
from ultralytics.data import build_dataloader, build_yolo_dataset
from ultralytics.engine.trainer import BaseTrainer
from ultralytics.models import yolo
from ultralytics.nn.tasks import DetectionModel
from ultralytics.utils import LOGGER, RANK
from ultralytics.utils.torch_utils import de_parallel, torch_distributed_zero_first

class DetectionTrainer(BaseTrainer):
    """
    扩展自BaseTrainer类的检测模型训练类。
    """

    def build_dataset(self, img_path, mode='train', batch=None):
        """
        构建YOLO数据集。

        参数:
            img_path (str): 包含图像的文件夹路径。
            mode (str): 模式,'train'或'val',用于不同的数据增强。
            batch (int, optional): 批次大小,仅用于'rect'模式。
        """
        gs = max(int(de_parallel(self.model).stride.max() if self.model else 0), 32)  # 获取模型的最大步幅
        return build_yolo_dataset(self.args, img_path, batch, self.data, mode=mode, rect=mode == 'val', stride=gs)

    def get_dataloader(self, dataset_path, batch_size=16, rank=0, mode='train'):
        """构建并返回数据加载器。"""
        assert mode in ['train', 'val']  # 确保模式有效
        with torch_distributed_zero_first(rank):  # 在分布式训练中,确保数据集只初始化一次
            dataset = self.build_dataset(dataset_path, mode, batch_size)  # 构建数据集
        shuffle = mode == 'train'  # 训练模式下打乱数据
        if getattr(dataset, 'rect', False) and shuffle:
            LOGGER.warning("WARNING ⚠️ 'rect=True'与DataLoader的shuffle不兼容,设置shuffle=False")
            shuffle = False
        workers = self.args.workers if mode == 'train' else self.args.workers * 2  # 设置工作线程数
        return build_dataloader(dataset, batch_size, workers, shuffle, rank)  # 返回数据加载器

    def preprocess_batch(self, batch):
        """对图像批次进行预处理,缩放并转换为浮点数。"""
        batch['img'] = batch['img'].to(self.device, non_blocking=True).float() / 255  # 将图像转换为浮点数并归一化
        return batch

    def set_model_attributes(self):
        """设置模型的属性,包括类别数量和名称。"""
        self.model.nc = self.data['nc']  # 将类别数量附加到模型
        self.model.names = self.data['names']  # 将类别名称附加到模型
        self.model.args = self.args  # 将超参数附加到模型

    def get_model(self, cfg=None, weights=None, verbose=True):
        """返回YOLO检测模型。"""
        model = DetectionModel(cfg, nc=self.data['nc'], verbose=verbose and RANK == -1)  # 创建检测模型
        if weights:
            model.load(weights)  # 加载权重
        return model

    def get_validator(self):
        """返回YOLO模型验证器。"""
        self.loss_names = 'box_loss', 'cls_loss', 'dfl_loss'  # 定义损失名称
        return yolo.detect.DetectionValidator(self.test_loader, save_dir=self.save_dir, args=copy(self.args))  # 返回验证器

    def plot_training_samples(self, batch, ni):
        """绘制训练样本及其注释。"""
        plot_images(images=batch['img'],
                    batch_idx=batch['batch_idx'],
                    cls=batch['cls'].squeeze(-1),
                    bboxes=batch['bboxes'],
                    paths=batch['im_file'],
                    fname=self.save_dir / f'train_batch{ni}.jpg',
                    on_plot=self.on_plot)  # 保存训练样本图像

    def plot_metrics(self):
        """绘制来自CSV文件的指标。"""
        plot_results(file=self.csv, on_plot=self.on_plot)  # 保存结果图像

代码说明:

  1. 导入库:导入了必要的库和模块,以支持数据处理、模型构建和训练。
  2. DetectionTrainer类:这是一个用于训练YOLO检测模型的类,继承自BaseTrainer
  3. build_dataset方法:构建YOLO数据集,支持训练和验证模式。
  4. get_dataloader方法:创建数据加载器,支持多线程和数据打乱。
  5. preprocess_batch方法:对输入的图像批次进行预处理,将其转换为浮点数并归一化。
  6. set_model_attributes方法:设置模型的类别数量和名称等属性。
  7. get_model方法:返回一个YOLO检测模型,并可选择加载预训练权重。
  8. get_validator方法:返回一个用于验证模型性能的验证器。
  9. plot_training_samples和plot_metrics方法:用于可视化训练样本和训练指标。```
    这个程序文件是Ultralytics YOLO(You Only Look Once)模型的训练模块,主要用于目标检测任务。文件中定义了一个名为DetectionTrainer的类,该类继承自BaseTrainer,并扩展了用于训练YOLO模型的功能。

在文件开头,导入了一些必要的库和模块,包括用于数据处理的build_dataloaderbuild_yolo_dataset,用于训练的BaseTrainer,以及YOLO模型相关的类和工具函数。接下来,DetectionTrainer类的文档字符串提供了一个使用示例,展示了如何初始化训练器并开始训练。

DetectionTrainer类包含多个方法。build_dataset方法用于构建YOLO数据集,接受图像路径、模式(训练或验证)和批量大小作为参数。它会根据模型的步幅计算出合适的步幅值,并调用build_yolo_dataset来创建数据集。

get_dataloader方法用于构建和返回数据加载器,确保在分布式训练时只初始化一次数据集缓存。它根据模式决定是否打乱数据,并设置工作线程的数量。

preprocess_batch方法用于对输入的图像批次进行预处理,包括将图像数据转换为浮点数并进行归一化。

set_model_attributes方法用于设置模型的属性,包括类别数量和类别名称。这些属性将影响模型的训练过程。

get_model方法用于返回一个YOLO检测模型,可以根据配置文件和权重文件进行初始化。

get_validator方法返回一个用于验证YOLO模型的验证器,设置了损失名称以便在训练过程中进行监控。

label_loss_items方法用于返回带有标签的训练损失项字典,方便监控训练过程中的损失情况。

progress_string方法返回一个格式化的字符串,显示训练进度,包括当前的轮次、GPU内存使用情况、损失值、实例数量和图像大小。

plot_training_samples方法用于绘制训练样本及其标注,帮助可视化训练数据的质量。

最后,plot_metricsplot_training_labels方法分别用于绘制训练过程中的指标和创建带标签的训练图,以便于分析模型的性能和训练效果。

整体来看,这个文件提供了YOLO模型训练的核心功能,涵盖了数据集构建、数据加载、模型设置、训练过程监控和结果可视化等多个方面。

源码文件

在这里插入图片描述

源码获取

欢迎大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐