智慧畜牧监测系统YOLO + BoTSORT行为检测与跟踪,大语言模型(LLM)生成专业健康分析报告 人工智能AI基于DeepSeek和YOLOv8_YOLOV12智能动物健康监测识别系统
·
人工智能AI基于DeepSeek和YOLOv8_YOLOV12智能动物健康监测识别系统
1
人工智能AI基于DeepSeek和Yolov8_12的智能动物健康监测系统
一、技术栈
前端:Vue3+TypeScript+Element Plus+ECharts+Vite
后端:SpringBoot3+MyBatis-Plus+MySQL8+JWT
算法端:Flask+PyTorch+Yolo+OpenCV
1. 数据集概况表
| 数据集类型 | 行为类别 (中文/英文) | 类别数量 | 训练集 (Train) | 验证集 (Val) | 测试集 (Test) | 总计样例数 |
|---|---|---|---|---|---|---|
| 猪行为识别 | 1. 饮水 (drinking)2. 进食 (eating)3. 躺卧 (lying)4. 坐立 (sitting)5. 嗅探 (sniffing)6. 站立 (standing) | 6 | 866 | 248 | 123 | 1,237 |
| 牛行为识别 | 1. 发情 (Estrus)2. 吃草 (grazing)3. 躺卧 (lying)4. 站立 (standing) | 4 | 2,226 | 419 | 295 | 2,940 |
2. 模型训练精度表 (mAP50)
注:以下精度基于项目提供的特定数据集场景训练得出。对于场景一致的数据识别效果优秀,但在其他不同场景下泛化性可能较弱。
🐷 猪行为识别模型精度
| 行为类别 (英文) | 行为类别 (中文) | mAP50 精度 | 性能评价 |
|---|---|---|---|
| drinking | 饮水 | 0.955 | ⭐⭐⭐⭐⭐ 极佳 |
| lying | 躺卧 | 0.955 | ⭐⭐⭐⭐⭐ 极佳 |
| eating | 进食 | 0.949 | ⭐⭐⭐⭐⭐ 极佳 |
| standing | 站立 | 0.825 | ⭐⭐⭐⭐ 良好 |
| sitting | 坐立 | 0.804 | ⭐⭐⭐⭐ 良好 |
| sniffing | 嗅探 | 0.678 | ⭐⭐⭐ 一般 (需优化) |
| 平均精度 | - | ~0.861 | - |
🐮 牛行为识别模型精度
| 行为类别 (英文) | 行为类别 (中文) | mAP50 精度 | 性能评价 |
|---|---|---|---|
| lying | 躺卧 | 0.972 | ⭐⭐⭐⭐⭐ 极佳 |
| standing | 站立 | 0.935 | ⭐⭐⭐⭐⭐ 极佳 |
| grazing | 吃草 | 0.836 | ⭐⭐⭐⭐ 良好 |
| Estrus | 发情 | 0.834 | ⭐⭐⭐⭐ 良好 |
| 平均精度 | - | ~0.894 | - |
📊 数据分析总结
- 高置信度行为:模型对**“躺卧” (lying)和“站立” (standing)**这类静态或大动作行为的识别非常精准(mAP50 > 0.93),无论是猪还是牛。
- 难点行为:
- 猪的**“嗅探” (sniffing)**动作幅度小且特征不明显,精度相对较低 (0.678),是后续优化的重点。
- 猪的**“坐立” (sitting)**介于躺和站之间,也存在一定识别难度。
- 数据量影响:牛的行为数据集总量(约2940张)远大于猪(约1237张),整体来看,牛模型的平均精度 (~0.894) 略高于猪模型 (~0.861),说明数据量的增加对模型稳定性有正向帮助。
智慧畜牧监测系统。结合了**计算机视觉(YOLO + BoTSORT)进行实时行为检测与跟踪,并利用大语言模型(LLM)**生成专业的健康分析报告。
代码分为三个核心部分:
- AI 算法服务 (Python/Flask):负责视频流处理、YOLO 行为识别、BoTSORT 目标跟踪以及调用 LLM 生成报告。
- 后端业务服务 (Java/SpringBoot):负责用户权限、设备管理、数据存储和 API 接口。
- 前端可视化界面 (Vue3):实现多路监控宫格、数据大屏和行为分析报表。
第一部分:AI 算法微服务 (Python + Flask)
这是系统的“大脑”,负责处理视频流并输出结构化数据。
1. 环境依赖 (requirements.txt)
flask
flask-cors
ultralytics>=8.0.0
opencv-python
numpy
supervision
requests
pandas
2. 核心推理与跟踪代码 (ai_engine.py)
集成了 YOLO 检测和 BoTSORT 跟踪逻辑。
# file: ai_engine.py
import cv2
from ultralytics import YOLO
from supervision import Detections, ByteTrack # 或者使用 BoTSORT
import numpy as np
class AnimalBehaviorEngine:
def __init__(self, model_path='weights/pig_behavior.pt'):
# 加载 YOLO 模型
self.model = YOLO(model_path)
# 定义行为类别映射 (以猪为例)
self.class_map = {
0: 'drinking', 1: 'eating', 2: 'lying',
3: 'sitting', 4: 'sniffing', 5: 'standing'
}
# 初始化跟踪器 (BoTSORT 或 ByteTrack)
self.tracker = ByteTrack()
def process_frame(self, frame):
"""
处理单帧图像:检测 -> 跟踪 -> 行为统计
"""
# 1. YOLO 推理
results = self.model(frame, verbose=False)[0]
# 2. 转换为 Supervision Detections 格式
detections = Detections.from_ultralytics(results)
# 3. 更新跟踪器 (获取稳定的 ID)
detections = self.tracker.update_with_detections(detections)
# 4. 标注画面
annotated_frame = frame.copy()
behavior_counts = {}
for i, tracker_id in enumerate(detections.tracker_id):
if tracker_id is None: continue
class_id = detections.class_id[i]
conf = detections.confidence[i]
bbox = detections.xyxy[i]
label = self.class_map.get(class_id, "unknown")
# 统计行为数量
behavior_counts[label] = behavior_counts.get(label, 0) + 1
# 绘制框和 ID
cv2.rectangle(annotated_frame, (int(bbox[0]), int(bbox[1])),
(int(bbox[2]), int(bbox[3])), (0, 255, 0), 2)
cv2.putText(annotated_frame, f"ID:{tracker_id} {label}",
(int(bbox[0]), int(bbox[1]-10)),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
return annotated_frame, behavior_counts, detections
3. Flask API 服务 (app.py)
提供视频流推流接口和 LLM 分析接口。
# file: app.py
from flask import Flask, Response, request, jsonify
from flask_cors import CORS
from ai_engine import AnimalBehaviorEngine
import cv2
import requests
import json
app = Flask(__name__)
CORS(app)
# 初始化引擎
engine = AnimalBehaviorEngine('weights/pig_behavior.pt')
# 模拟视频源 (实际项目中应连接 RTSP)
# 注意:说明中提到不支持真实摄像头,这里用本地视频文件模拟
VIDEO_SOURCE = 'videos/demo_pig.mp4'
@app.route('/video_feed/<camera_id>')
def video_feed(camera_id):
"""生成 MJPEG 视频流"""
cap = cv2.VideoCapture(VIDEO_SOURCE)
def generate():
while cap.isOpened():
ret, frame = cap.read()
if not ret: break
# AI 处理
annotated_frame, counts, _ = engine.process_frame(frame)
# 编码为 JPEG
ret, buffer = cv2.imencode('.jpg', annotated_frame)
frame_bytes = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')
# 将统计数据发送到前端 (可通过 WebSocket 或 SSE,这里简化为打印日志)
# print(f"Camera {camera_id} Stats: {counts}")
return Response(generate(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/analyze/health', methods=['POST'])
def analyze_health():
"""调用大模型生成健康报告"""
data = request.json
behavior_stats = data.get('stats', {}) # 例如 {'lying': 50, 'eating': 20...}
prompt = f"""
你是一位资深畜牧专家。根据以下动物行为统计数据,生成一份健康分析报告:
数据:{json.dumps(behavior_stats)}
要求:
1. 评估整体健康状态(良好/一般/危险)。
2. 指出异常行为(如躺卧时间过长可能生病)。
3. 给出具体的饲养建议。
4. 输出格式为 JSON,包含 status, summary, suggestions 字段。
"""
# 调用阿里百炼/Qwen API (伪代码)
# response = call_qwen_api(prompt)
# return jsonify(response)
# 模拟返回
return jsonify({
"status": "良好",
"summary": "群体活跃度正常,进食量达标。",
"suggestions": ["建议检查饮水区卫生", "夜间注意保温"]
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
第二部分:后端业务服务 (Java SpringBoot 3)
负责管理摄像头信息、存储历史记录和权限控制。
1. 实体类 (Camera.java)
// file: src/main/java/com/example/smartfarm/entity/Camera.java
@Data
@TableName("sys_camera")
public class Camera {
@TableId(type = IdType.AUTO)
private Long id;
private String name; // 摄像头名称,如 "保育区监控01"
private String rtspUrl; // 虽然本项目用模拟视频,但字段保留
private String location; // 位置
private Integer status; // 0-离线 1-在线
}
2. 行为记录控制器 (BehaviorController.java)
提供前端图表所需的数据接口。
// file: src/main/java/com/example/smartfarm/controller/BehaviorController.java
@RestController
@RequestMapping("/api/behavior")
@CrossOrigin
public class BehaviorController {
@Autowired
private BehaviorRecordService recordService;
/**
* 获取行为分布统计 (用于饼图)
*/
@GetMapping("/distribution")
public Result<Map<String, Object>> getDistribution(
@RequestParam String cameraId,
@RequestParam String startDate,
@RequestParam String endDate) {
List<BehaviorRecord> records = recordService.lambdaQuery()
.eq(BehaviorRecord::getCameraId, cameraId)
.between(BehaviorRecord::getCreateTime, startDate, endDate)
.list();
// 统计各类别数量
Map<String, Long> stats = records.stream()
.collect(Collectors.groupingBy(BehaviorRecord::getBehaviorType, Collectors.counting()));
return Result.success(stats);
}
/**
* 获取健康分析摘要
*/
@GetMapping("/summary/{id}")
public Result<HealthReport> getSummary(@PathVariable Long id) {
// 从数据库获取之前由 Python 服务生成并保存的报告
HealthReport report = reportService.getById(id);
return Result.success(report);
}
}
第三部分:前端可视化界面 (Vue3 + TS)
多路监控、宫格切换和数据大屏。
1. 视频监控组件 (VideoMonitor.vue)
<!-- file: src/views/monitor/VideoMonitor.vue -->
<template>
<div class="monitor-container">
<!-- 顶部工具栏 -->
<div class="toolbar">
<el-select v-model="currentCamera" placeholder="选择摄像头">
<el-option v-for="cam in cameras" :key="cam.id" :label="cam.name" :value="cam.id" />
</el-select>
<el-radio-group v-model="gridLayout">
<el-radio-button label="1">1 宫格</el-radio-button>
<el-radio-button label="4">4 宫格</el-radio-button>
<el-radio-button label="9">9 宫格</el-radio-button>
</el-radio-group>
<el-button type="primary" @click="startAnalysis">AI 智能分析</el-button>
</div>
<!-- 视频宫格区域 -->
<div class="video-grid" :class="'grid-' + gridLayout">
<div v-for="i in gridCount" :key="i" class="video-card">
<div class="video-header">
<span>{{ getCameraName(i) }}</span>
<el-tag size="small" type="success">直播中</el-tag>
</div>
<img
:src="`http://localhost:5000/video_feed/${getCameraId(i)}`"
class="video-stream"
alt="Stream"
/>
<!-- 悬浮显示实时统计 -->
<div class="overlay-stats">
<span v-if="liveStats[i]">站立: {{ liveStats[i].standing || 0 }}</span>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { ElMessage } from 'element-plus';
const gridLayout = ref('1');
const currentCamera = ref('');
const liveStats = ref<Record<number, any>>({});
// 模拟摄像头列表
const cameras = [
{ id: 'cam01', name: '保育区监控01' },
{ id: 'cam02', name: '喂食区监控01' },
{ id: 'cam03', name: '运动场监控01' }
];
const gridCount = computed(() => parseInt(gridLayout.value));
const getCameraId = (index: number) => {
// 简单轮询分配摄像头 ID
return cameras[(index - 1) % cameras.length].id;
};
const getCameraName = (index: number) => {
return cameras[(index - 1) % cameras.length].name;
};
const startAnalysis = () => {
ElMessage.info("正在调用大模型生成健康报告...");
// 调用后端 API 生成报告并跳转
};
</script>
<style scoped>
.monitor-container { padding: 20px; height: 100%; display: flex; flex-direction: column; }
.toolbar { margin-bottom: 20px; display: flex; gap: 15px; align-items: center; }
.video-grid { display: grid; gap: 15px; flex: 1; }
.grid-1 { grid-template-columns: 1fr; }
.grid-4 { grid-template-columns: repeat(2, 1fr); }
.grid-9 { grid-template-columns: repeat(3, 1fr); }
.video-card {
background: #000;
border-radius: 8px;
overflow: hidden;
position: relative;
aspect-ratio: 16/9;
}
.video-stream { width: 100%; height: 100%; object-fit: cover; }
.video-header {
position: absolute; top: 0; left: 0; right: 0;
background: rgba(0,0,0,0.6); color: white;
padding: 5px 10px; display: flex; justify-content: space-between;
}
.overlay-stats {
position: absolute; bottom: 10px; right: 10px;
background: rgba(0, 0, 0, 0.7); color: #00ff00;
padding: 5px; border-radius: 4px; font-size: 12px;
}
</style>
2. 行为分析大屏 (BehaviorAnalysis.vue)
<!-- file: src/views/analysis/BehaviorAnalysis.vue -->
<template>
<div class="analysis-dashboard">
<!-- 顶部筛选 -->
<div class="filters">
<el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"/>
<el-button type="primary" @click="fetchData">查询</el-button>
</div>
<!-- 统计卡片 -->
<el-row :gutter="20">
<el-col :span="6">
<el-card shadow="hover">
<template #header>总记录数</template>
<div class="stat-value">{{ totalRecords }}</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<template #header>平均持续时间</template>
<div class="stat-value">{{ avgDuration }}秒</div>
</el-card>
</el-col>
</el-row>
<!-- 图表区域 -->
<el-row :gutter="20" style="margin-top: 20px;">
<el-col :span="12">
<el-card>
<template #header>行为类型分布</template>
<div ref="pieChartRef" style="height: 300px;"></div>
</el-card>
</el-col>
<el-col :span="12">
<el-card>
<template #header>摄像头分布</template>
<div ref="barChartRef" style="height: 300px;"></div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import * as echarts from 'echarts';
import axios from 'axios';
const pieChartRef = ref<HTMLElement>();
const barChartRef = ref<HTMLElement>();
const totalRecords = ref(0);
const avgDuration = ref(0);
onMounted(() => {
fetchData();
});
const fetchData = async () => {
// 1. 获取统计数据
const res = await axios.get('http://localhost:8080/api/behavior/distribution?cameraId=all&startDate=2023-01-01&endDate=2023-12-31');
const data = res.data.data;
// 2. 渲染饼图
const chart = echarts.init(pieChartRef.value!);
chart.setOption({
tooltip: { trigger: 'item' },
series: [{
type: 'pie',
radius: ['40%', '70%'],
data: Object.keys(data).map(key => ({ value: data[key], name: key }))
}]
});
totalRecords.value = Object.values(data).reduce((a, b) => a + b, 0);
avgDuration.value = 38; // 模拟数据
};
</script>
第四部分:项目启动与运行指南
1. 目录结构建议
SmartAnimalSystem/
├── ai_service/ # Python Flask 服务
│ ├── weights/ # 存放 best.pt
│ ├── videos/ # 存放演示视频
│ └── app.py
├── backend/ # Java SpringBoot 服务
│ ├── src/
│ └── pom.xml
├── frontend/ # Vue3 前端
│ ├── src/
│ └── package.json
└── docs/ # 文档和教程
2. 启动步骤
- 启动 AI 服务:
cd ai_service pip install -r requirements.txt python app.py # 访问 http://localhost:5000/video_feed/cam01 查看视频流 - 启动后端:
- 配置
application.yml连接 MySQL。 - 运行 SpringBoot 主类。
- 配置
- 启动前端:
cd frontend npm install npm run dev
3. 关于 ID 识别的特别说明
正如项目描述所言,本系统使用的是 BoTSORT/ByteTrack 生成的临时追踪 ID。
- 特点:ID 仅在单次视频会话中有效。如果动物离开画面再回来,ID 会改变。
- 适用场景:短期行为统计、实时计数。
- 不适用场景:长期个体档案建立(这需要 ReID 重识别技术)。
**
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)