ZeroOne AI
← 返回文章列表

YOLOv26 鱼类目标检测与计数任务实现与优化

👁 5
分类:AI视觉

基于 YOLOv26 实现智慧渔业场景下的鱼类目标检测与自动计数:从数据集构建与增强、训练配置与优化(K-Means 锚框、多尺度训练、量化与 TensorRT 加速),到检测计数系统实现与性能评估的完整技术方案。

YOLOv26 鱼类目标检测与计数任务实现与优化

一、项目背景

在智慧渔业和海洋生态研究中,鱼类目标检测与计数是一项关键任务。传统的人工计数方式依赖肉眼观察,效率低、误差大,难以满足规模化养殖和科研监测的需求。借助深度学习目标检测技术,可以实现对水下摄像头、养殖池监控画面的自动分析,实时识别鱼群并统计数量,为养殖管理、投喂决策和生态评估提供数据支撑。

YOLOv26 作为 YOLO 系列的最新目标检测模型,以高精度和实时性能见长。它在 YOLOv5 的基础上进行了多项改进:更高效的特征融合网络、更精准的注意力机制以及更轻量化的模型结构。这些改进使模型在保持高精度的同时显著降低计算资源需求,非常适合在嵌入式设备上部署,实现渔业现场的实时监测。

二、技术方案:整体流程

本项目的完整技术链路分为五个阶段:

  1. 数据集构建与预处理:采集标注鱼类图像,统一尺寸、归一化、数据增强;
  2. 模型训练与优化:配置超参数训练 YOLOv26,通过锚框优化、多尺度训练提升精度;
  3. 检测与计数实现:基于训练好的模型开发检测与计数模块;
  4. 性能评估:用 mAP、Precision/Recall 等指标量化模型效果;
  5. 部署与应用:量化 + TensorRT 加速,落地智能养殖监控场景。

三、系统架构:核心模块设计

3.1 数据集构建

鱼类目标检测的数据集通常包含多种鱼类的图像,每张图像都标注了鱼类的位置和类别。一个高质量的数据集应具备:

数据集的构建通常经过图像采集、标注、清洗和增强等步骤。对于小型数据集,数据增强尤为重要,可以显著提升模型泛化能力。

YOLO 格式的标注文件为每张图像对应一个 txt 文件,每行一个目标:

<class_id> <x_center> <y_center> <width> <height>

坐标均为归一化到 [0,1] 的相对值。数据集按 7:2:1 划分为训练集、验证集和测试集(split_dataset 脚本自动完成目录创建与文件复制)。

3.2 数据预处理与增强

归一化公式:将原始像素值 x 映射到 [0,1] 区间,帮助模型更快收敛:

x_norm = (x - x_min) / (x_max - x_min)

增强策略(针对鱼类检测场景):

使用 imgaug 库实现自动化增强流水线:

import cv2
import numpy as np
from imgaug import augmenters as iaa

# 定义数据增强序列
augmentation_seq = iaa.Sequential([
    iaa.Fliplr(0.5),  # 水平翻转
    iaa.Affine(
        scale={"x": (0.8, 1.2), "y": (0.8, 1.2)},  # 缩放
        rotate=(-20, 20),  # 旋转
        shear=(-10, 10),  # 剪切
        mode='reflect'
    ),
    iaa.AdditiveGaussianNoise(scale=(0, 0.1 * 255)),  # 高斯噪声
    iaa.Multiply((0.8, 1.2)),  # 亮度调整
    iaa.LinearContrast((0.8, 1.2)),  # 对比度调整
    iaa.AddToHueAndSaturation((-20, 20)),  # 色调调整
    iaa.Sometimes(0.5, iaa.Grayscale(3)),  # 转为灰度
    iaa.Sometimes(0.5, iaa.GaussianBlur(sigma=(0, 3.0)))  # 高斯模糊
])

对于需要同步修改边界框的增强(翻转、裁剪),可自定义 FishAugmentation 类,确保图像与标注框保持一致变换。

四、实施过程:训练、优化与计数实现

4.1 环境搭建

pip install torch torchvision
pip install ultralytics
pip install numpy opencv-python pillow
pip install tqdm tensorboard pyyaml

4.2 训练配置

数据集配置文件 fish.yaml 与模型配置文件核心参数如下:

# 模型配置
model: yolov26s.pt  # 使用预训练模型
data: fish.yaml     # 数据集配置文件

# 训练参数
epochs: 300        # 训练轮次
batch_size: 16     # 批次大小
img_size: 640      # 输入图像尺寸
workers: 8         # 数据加载线程数

# 优化器参数
optimizer: SGD     # 优化器
lr0: 0.01          # 初始学习率
lrf: 0.01          # 最终学习率比例
momentum: 0.937    # 动量
weight_decay: 0.0005  # 权重衰减

# 学习率调度
scheduler: cosine   # 余弦退火调度

# 数据增强
hsv_h: 0.015       # 色调增强比例
hsv_s: 0.7         # 饱和度增强比例
hsv_v: 0.4         # 明度增强比例
fliplr: 0.5        # 水平翻转概率
mosaic: 1.0        # Mosaic增强概率
mixup: 0.1         # Mixup增强概率

模型结构配置(backbone 采用 CSPDarknet 风格,neck 采用 PAN-FPN 特征融合,head 为 YOLO 检测头),类别数 nc: 1(鱼类单类别)。

学习率策略:采用 Cosine Annealing 平滑调整,避免训练震荡;也可以自定义 CosineAnnealingWarmupLR,先线性 warmup 再余弦退火,提升训练稳定性。

4.3 训练过程监控

使用 TensorBoard 实时记录训练与验证指标:

from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter()

for epoch in range(epochs):
    # 训练代码...

    # 记录训练损失
    writer.add_scalar('Train/total_loss', loss.item(), epoch)
    writer.add_scalar('Train/obj_loss', obj_loss.item(), epoch)
    writer.add_scalar('Train/cls_loss', cls_loss.item(), epoch)
    writer.add_scalar('Train/box_loss', box_loss.item(), epoch)

    # 记录验证指标
    writer.add_scalar('Val/mAP_0.5', map_50, epoch)
    writer.add_scalar('Val/mAP_0.5:0.95', map_50_95, epoch)

4.4 模型优化策略

1. 改进的锚框生成(K-Means)

鱼类目标长宽比差异大,使用标准锚框效果欠佳。对标注框的宽高取对数后做 K-Means 聚类,得到贴合数据分布的锚框:

def improved_anchors_kmeans(annotations, n_clusters=9, random_state=None):
    """
    改进的锚框生成算法,特别适合鱼类检测
    annotations: 标注数据列表,每个元素为[x_center, y_center, width, height]
    """
    annotations = np.array(annotations)
    wh = annotations[:, 2:]
    log_wh = np.log(wh)  # 对宽高取对数,降低尺度差异影响

    kmeans = KMeans(n_clusters=n_clusters, random_state=random_state)
    kmeans.fit(log_wh)

    anchors = np.exp(kmeans.cluster_centers_)  # 还原为实际尺寸

    # 按面积排序
    areas = anchors[:, 0] * anchors[:, 1]
    sorted_indices = np.argsort(areas)
    anchors = anchors[sorted_indices]
    return anchors

2. 多尺度训练

在 [640, 800, 960] 多种输入尺寸间轮换训练,增强模型对不同目标尺度的适应能力:

multi_scale_config = {
    'img_size_range': [640, 800, 960],  # 多种输入尺寸
    'stride_range': [8, 16, 32],        # 不同步长
    'anchor_sizes': [[10, 13, 16], [30, 61, 62], [116, 90, 156]]  # 不同尺度的锚框
}

3. 损失函数改进

针对鱼类目标小、样本不均衡的特点,可引入 Focal Loss(缓解难易样本不平衡)或 Varifocal Loss(提升密集场景下高质量锚框的权重)。

4. 模型量化与 TensorRT 加速

部署阶段先做动态量化压缩模型体积:

from torch.quantization import quantize_dynamic

quantized_model = quantize_dynamic(
    model,
    {nn.Conv2d, nn.Linear},  # 量化卷积与全连接层
    dtype=torch.qint8        # 8位量化
)
torch.save(quantized_model.state_dict(), 'yolov26_quantized.pth')

再导出 ONNX 并用 TensorRT 构建推理引擎,实现 GPU 上的极致加速:

import tensorrt as trt

logger = trt.Logger(trt.Logger.WARNING)
builder = trt.Builder(logger)
network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
parser = trt.OnnxParser(network, logger)

with open('yolov26.onnx', 'rb') as model:
    if not parser.parse(model.read()):
        print('ERROR: Failed to parse the ONNX file.')
        for error in range(parser.num_errors):
            print(parser.get_error(error))
        sys.exit(1)

config = builder.create_builder_config()
config.max_workspace_size = 1 << 30  # 1GB
engine = builder.build_engine(network, config)

with open('yolov26.trt', 'wb') as f:
    f.write(engine.serialize())

4.5 检测与计数实现

检测器封装推理全流程:预处理(resize 到 640×640、归一化、CHW 转置)→ 模型推理 → 后处理(置信度过滤 + NMS)→ 可视化:

class FishDetector:
    def __init__(self, model_path, device='cpu'):
        self.model = Model('models/yolov6s.yaml').to(device)
        self.model.load_state_dict(torch.load(model_path, map_location=device))
        self.model.eval()
        self.class_names = ['fish']

    def preprocess(self, img):
        img = cv2.resize(img, (640, 640))
        img = img.transpose((2, 0, 1))  # HWC to CHW
        img = np.ascontiguousarray(img)
        img = torch.from_numpy(img).float() / 255.0
        if img.ndimension() == 3:
            img = img.unsqueeze(0)
        return img

    def detect(self, img, conf_thres=0.25, iou_thres=0.45):
        # 预处理 -> 推理 -> 后处理(NMS) -> 返回框/分数/类别
        ...

计数模块在检测基础上引入跨帧跟踪去重,避免同一尾鱼被重复计数:

class SmartAquacultureSystem:
    def __init__(self, model_path, device='cpu'):
        self.detector = FishDetector(model_path, device)
        self.fish_count = 0
        self.counted_fish = set()
        self.tracking_history = {}
        self.max_track_length = 30
        self.cap = cv2.VideoCapture(0)

    def process_frame(self, frame):
        count, result_img = self.detector.count_fish(frame)
        current_fish = self.detect_and_track_fish(frame)  # 跟踪当前帧鱼群

        # 新增鱼进入画面才计数
        new_fish = current_fish - self.counted_fish
        self.fish_count += len(new_fish)
        self.counted_fish.update(new_fish)

        cv2.putText(result_img, f"Total Count: {self.fish_count}", (10, 60),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
        return result_img

4.6 性能评估

使用 Precision、Recall、mAP@0.5、mAP@0.5:0.95 等指标评估模型:

评估代码通过 precision_recall_curve 计算 PR 曲线,再对预测框做置信度过滤与 NMS 后与标注比对,统计各指标。

五、应用价值

六、SEO关键词

YOLOv26、鱼类检测、目标计数、智慧渔业、深度学习、目标检测、YOLO、数据增强、TensorRT、模型量化、水产养殖、实时监测

评论(0