构建AI智能体:九十六、基于YOLO的智能生活助手:食材识别、植物健康与宠物行为分析

一、引言

在人工智能技术日益普及的今天,计算机视觉正以前所未有的方式改变着我们的日常生活。YOLO作为先进的目标检测算法,以其快速和精准的特性,成为了实现智能视觉应用的得力工具。今天我们将通过四个贴近生活的趣味场景------智能厨房助手、植物健康监测、智能衣橱管理和宠物行为分析,一起领略YOLO技术的魅力。

无论你是烹饪爱好者、园艺新手、时尚达人还是宠物主人,这些应用都能为你的生活带来便利与乐趣。通过简单的代码实现,就可以让计算机识别食材并推荐菜谱,监测植物的健康状况,管理衣橱并提供穿搭建议,甚至分析宠物的行为状态。这些示例不仅展示了YOLO技术的广泛应用,也为初学者提供了实践机会,让我们在动手实现中深入理解计算机视觉的原理。让我们一起探索如何用YOLO模型构建智能生活助手,开启人工智能的奇妙之旅。

二、智能厨房助手

1. 场景描述

基于YOLO模型的智能厨房助手,能够识别图像中的食材,并根据识别到的食材推荐菜谱和计算营养成分。整个示例包含了食材检测、菜谱推荐、营养计算和结果可视化四个主要部分;

2. 示例代码

python 复制代码
import cv2
from ultralytics import YOLO
import requests
import json
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False    # 正常显示负号

class SmartKitchenAssistant:
    def __init__(self, model_size='n'):
        # 加载YOLO模型
        self.model = YOLO(f'yolov8{model_size}.pt')
        
        # 食材与菜谱映射
        self.ingredient_recipes = {
            'banana': ['香蕉奶昔', '香蕉面包', '香蕉煎饼'],
            'apple': ['苹果派', '苹果沙拉', '烤苹果'],
            'orange': ['橙汁', '橙子蛋糕', '水果沙拉'],
            'carrot': ['胡萝卜汤', '胡萝卜沙拉', '炒胡萝卜'],
            'broccoli': ['西兰花炒肉', '烤西兰花', '西兰花汤'],
            'tomato': ['番茄炒蛋', '番茄汤', '番茄沙拉'],
            'egg': ['煎蛋', '炒蛋', '蛋花汤'],
            'bread': ['吐司', '三明治', '法式吐司'],
            'chicken': ['烤鸡', '炸鸡', '鸡汤'],
            'fish': ['烤鱼', '炸鱼', '鱼汤']
        }
        
        # 食材营养成分(每100克)
        self.nutrition_info = {
            'banana': {'calories': 89, 'carbs': 23, 'protein': 1.1, 'fat': 0.3},
            'apple': {'calories': 52, 'carbs': 14, 'protein': 0.3, 'fat': 0.2},
            'orange': {'calories': 47, 'carbs': 12, 'protein': 0.9, 'fat': 0.1},
            'carrot': {'calories': 41, 'carbs': 10, 'protein': 0.9, 'fat': 0.2},
            'broccoli': {'calories': 34, 'carbs': 7, 'protein': 2.8, 'fat': 0.4},
            'tomato': {'calories': 18, 'carbs': 3.9, 'protein': 0.9, 'fat': 0.2},
            'egg': {'calories': 155, 'carbs': 1.1, 'protein': 13, 'fat': 11},
            'bread': {'calories': 265, 'carbs': 49, 'protein': 9, 'fat': 3.2},
            'chicken': {'calories': 165, 'carbs': 0, 'protein': 31, 'fat': 3.6},
            'fish': {'calories': 206, 'carbs': 0, 'protein': 22, 'fat': 12}
        }
    
    def detect_ingredients(self, image_path):
        """检测图像中的食材"""
        results = self.model.predict(source=image_path, conf=0.3)
        result = results[0]
        
        detected_ingredients = {}
        if result.boxes is not None:
            for box, cls in zip(result.boxes.xyxy, result.boxes.cls):
                class_name = self.model.names[int(cls)]
                
                # 只关注食材类别的检测
                if class_name in self.ingredient_recipes:
                    if class_name not in detected_ingredients:
                        detected_ingredients[class_name] = 0
                    detected_ingredients[class_name] += 1
        
        return detected_ingredients
    
    def recommend_recipes(self, ingredients):
        """根据检测到的食材推荐菜谱"""
        all_recipes = []
        
        for ingredient in ingredients:
            if ingredient in self.ingredient_recipes:
                all_recipes.extend(self.ingredient_recipes[ingredient])
        
        # 去除重复菜谱
        unique_recipes = list(set(all_recipes))
        
        # 根据食材匹配度排序(匹配食材越多的菜谱排前面)
        recipe_scores = {}
        for recipe in unique_recipes:
            score = 0
            for ingredient in ingredients:
                if ingredient in self.ingredient_recipes and recipe in self.ingredient_recipes[ingredient]:
                    score += 1
            recipe_scores[recipe] = score
        
        sorted_recipes = sorted(recipe_scores.items(), key=lambda x: x[1], reverse=True)
        
        return [recipe for recipe, score in sorted_recipes[:5]]  # 返回前5个推荐
    
    def calculate_nutrition(self, ingredients):
        """计算检测食材的总营养成分"""
        total_nutrition = {'calories': 0, 'carbs': 0, 'protein': 0, 'fat': 0}
        
        for ingredient, count in ingredients.items():
            if ingredient in self.nutrition_info:
                # 假设每个检测到的食材约100克
                nutrition = self.nutrition_info[ingredient]
                for key in total_nutrition:
                    total_nutrition[key] += nutrition[key] * count
        
        return total_nutrition
    
    def analyze_kitchen_scene(self, image_path):
        """完整的厨房场景分析"""
        # 检测食材
        ingredients = self.detect_ingredients(image_path)
        
        if not ingredients:
            return {
                'ingredients': {},
                'recipes': [],
                'nutrition': {},
                'message': '未检测到食材,请确保食材在视野范围内'
            }
        
        # 推荐菜谱
        recipes = self.recommend_recipes(ingredients.keys())
        
        # 计算营养
        nutrition = self.calculate_nutrition(ingredients)
        
        # 可视化结果
        self.visualize_results(image_path, ingredients, recipes, nutrition)
        
        return {
            'ingredients': ingredients,
            'recipes': recipes,
            'nutrition': nutrition,
            'message': f'检测到 {len(ingredients)} 种食材,推荐 {len(recipes)} 个菜谱'
        }
    
    def visualize_results(self, image_path, ingredients, recipes, nutrition):
        """可视化分析结果"""
        from PIL import Image, ImageDraw, ImageFont
        import numpy as np
        
        # 读取图像并转换为RGB
        image = cv2.imread(image_path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        
        # 使用YOLO绘制检测结果
        results = self.model.predict(source=image_path, conf=0.3)
        result_img = results[0].plot()
        
        # 转换为Pillow格式
        pil_img = Image.fromarray(result_img)
        draw = ImageDraw.Draw(pil_img)
        
        # 加载中文字体(确保系统中存在该字体)
        font_path = "simhei.ttf"  # 黑体字体文件路径
        font = ImageFont.truetype(font_path, 40)
        
        # 添加文本信息
        y_offset = 10
        draw.text((10, y_offset), "智能厨房助手分析结果:", font=font, fill=(0, 255, 0))
        # y_offset += 30
        
        # 显示检测到的食材
        draw.text((480, y_offset), f"检测到食材: {', '.join(ingredients.keys())}", font=font, fill=(106, 90, 205))
        # y_offset += 25
        
        # 显示营养成分
        draw.text((1200, y_offset), f"预估营养: 热量{round(nutrition['calories'], 2)}卡, 碳水{round(nutrition['carbs'], 2)}g, 蛋白质{round(nutrition['protein'], 2)}g, 脂肪{round(nutrition['fat'], 2)}g", 
                 font=font, fill=(139, 71, 38))
        y_offset += 42
        x_offset = 10
        # 显示推荐菜谱
        draw.text((10, y_offset), "推荐菜谱:", font=font, fill=(255, 127, 80))
        # y_offset += 25
       
        x_offset += 200
        for i, recipe in enumerate(recipes[:3]):  # 显示前3个菜谱
            draw.text((x_offset, y_offset), f"{i+1}.{recipe}", font=font, fill=(255, 177, 90))
            # y_offset += 20
            x_offset += 250
        
        # 转换回OpenCV格式
        result_img = np.array(pil_img)
        
        # 显示图像
        plt.figure(figsize=(12, 7))
        plt.imshow(result_img)
        plt.axis('off')
        plt.title('智能厨房助手分析结果')
        plt.tight_layout()
        plt.show()

# 使用示例
kitchen_assistant = SmartKitchenAssistant('n')
result = kitchen_assistant.analyze_kitchen_scene('kitchen_scene.jpg')
print(result)

3. 过程说明

  1. YOLO模型加载与使用:使用Ultralytics库加载YOLOv8模型,并进行图像预测。通过设置置信度阈值来过滤检测结果。
  2. 食材检测:遍历检测结果,只保留在预定义食材列表中的物体,并统计每种食材的数量。
  3. 菜谱推荐:根据检测到的食材,从预定义的菜谱映射中找出所有相关的菜谱,然后根据食材匹配度进行排序,返回前5个推荐菜谱。
  4. 营养计算:根据检测到的食材数量,从预定义的营养信息中累加计算总热量、碳水化合物、蛋白质和脂肪。
  5. 结果可视化:使用OpenCV和Matplotlib绘制检测结果,并用Pillow库添加中文文本。这里注意,由于OpenCV不支持中文,所以使用Pillow来绘制中文文本。
  6. 中文字体显示:通过Pillow的ImageDraw绘制中文,需要指定中文字体文件(如simhei.ttf),否则会出现乱码。
  7. 代码结构:采用面向对象的方式,将功能封装在SmartKitchenAssistant类中,使代码易于维护和扩展。

4. 结果分析

image 1/1 D:\AIWorld\case\test\kitchen_scene.jpg: 384x640 2 bananas, 5 apples, 1 orange, 59.3ms

Speed: 2.6ms preprocess, 59.3ms inference, 2.5ms postprocess per image at shape (1, 3, 384, 640)

image 1/1 D:\AIWorld\case\test\kitchen_scene.jpg: 384x640 2 bananas, 5 apples, 1 orange, 38.2ms

Speed: 2.3ms preprocess, 38.2ms inference, 2.4ms postprocess per image at shape (1, 3, 384, 640)

{'ingredients': {'banana': 2, 'apple': 5, 'orange': 1}, 'recipes': ['水果沙拉', '苹果派', '橙汁', '香蕉面包', '香蕉煎饼'], 'nutrition': {'calories': 485, 'carbs': 128, 'protein': 4.6000000000000005, 'fat': 1.7000000000000002}, 'message': '

检测到 3 种食材,推荐 5 个菜谱'}

结果图例:

分析后的结果图:

三、植物健康监测系统

1. 场景描述

基于YOLO模型的植物健康监测系统,利用YOLO模型检测图像中的植物,然后通过分析植物叶片的颜色特征来评估其健康状况,并给出相应的养护建议。该系统将计算机视觉技术与植物学知识相结合,为植物爱好者提供一个智能化的养护助手。

2. 示例代码

python 复制代码
import cv2
from ultralytics import YOLO
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False    # 正常显示负号

class PlantHealthMonitor:
    def __init__(self,model_size='n'):
        # 加载植物检测模型(需要自定义训练)
        self.detection_model = YOLO(f'yolov8{model_size}.pt') # 假设已训练
        
        # 植物养护信息
        self.plant_care_info = {
            'rose': {
                'water': '每周浇水2-3次,保持土壤湿润',
                'sunlight': '需要充足阳光,每天6小时以上',
                'fertilizer': '每月施一次玫瑰花肥',
                'common_issues': ['黑斑病', '白粉病', '蚜虫']
            },
            'cactus': {
                'water': '耐旱,每2-3周浇水一次',
                'sunlight': '需要充足阳光',
                'fertilizer': '生长季节每月施一次仙人掌专用肥',
                'common_issues': ['过度浇水', '日照不足']
            },
            'orchid': {
                'water': '每周浇水1-2次,避免积水',
                'sunlight': '需要散射光,避免直射',
                'fertilizer': '每2周施一次兰花专用肥',
                'common_issues': ['根腐病', '叶片发黄']
            },
            'succulent': {
                'water': '耐旱,土壤干透后再浇水',
                'sunlight': '需要充足阳光',
                'fertilizer': '生长季节每月施一次多肉专用肥',
                'common_issues': ['过度浇水', '日照不足']
            }
        }
    
    def detect_plants(self, image_path):
        """检测图像中的植物"""
        results = self.detection_model.predict(source=image_path, conf=0.4)
        return results[0]
    
    def analyze_leaf_health(self, image, leaf_region):
        """分析叶片健康状况"""
        # 提取叶片区域
        x1, y1, x2, y2 = map(int, leaf_region)
        leaf_img = image[y1:y2, x1:x2]
        
        if leaf_img.size == 0:
            return {'health_status': '无法分析', 'confidence': 0}
        
        # 转换为HSV颜色空间分析
        hsv = cv2.cvtColor(leaf_img, cv2.COLOR_RGB2HSV)
        
        # 分析颜色特征
        green_mask = cv2.inRange(hsv, (36, 25, 25), (86, 255, 255))
        yellow_mask = cv2.inRange(hsv, (20, 100, 100), (30, 255, 255))
        brown_mask = cv2.inRange(hsv, (10, 100, 20), (20, 255, 200))
        
        total_pixels = leaf_img.shape[0] * leaf_img.shape[1]
        green_ratio = np.sum(green_mask > 0) / total_pixels
        yellow_ratio = np.sum(yellow_mask > 0) / total_pixels
        brown_ratio = np.sum(brown_mask > 0) / total_pixels
        
        # 根据颜色比例判断健康状况
        if green_ratio > 0.7:
            health_status = "健康"
            confidence = green_ratio
        elif yellow_ratio > 0.3:
            health_status = "轻微问题(可能缺水或缺肥)"
            confidence = yellow_ratio
        elif brown_ratio > 0.2:
            health_status = "不健康(可能病害或严重缺水)"
            confidence = brown_ratio
        else:
            health_status = "状态未知"
            confidence = 0.5
        
        return {
            'health_status': health_status,
            'confidence': confidence,
            'color_analysis': {
                'green_ratio': green_ratio,
                'yellow_ratio': yellow_ratio,
                'brown_ratio': brown_ratio
            }
        }
    
    def get_care_recommendations(self, plant_type, health_status):
        """根据植物类型和健康状况提供养护建议"""
        if plant_type not in self.plant_care_info:
            return ["未知植物类型,建议咨询专业园艺师"]
        
        care_info = self.plant_care_info[plant_type]
        recommendations = []
        
        # 基础养护建议
        recommendations.append(f"浇水: {care_info['water']}")
        recommendations.append(f"光照: {care_info['sunlight']}")
        recommendations.append(f"施肥: {care_info['fertilizer']}")
        
        # 根据健康状况的特别建议
        if "不健康" in health_status or "问题" in health_status:
            recommendations.append("特别关注: 请检查以下常见问题:")
            for issue in care_info['common_issues']:
                recommendations.append(f"  - {issue}")
            recommendations.append("建议: 适当调整养护方式,如问题持续请咨询专家")
        elif "健康" in health_status:
            recommendations.append("当前状态良好,请继续保持现有养护方式")
        
        return recommendations
    
    def full_plant_analysis(self, image_path):
        """完整的植物分析"""
        # 检测植物
        result = self.detect_plants(image_path)
        image = cv2.imread(image_path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        
        analysis_results = []
        
        if result.boxes is not None:
            for i, (box, cls) in enumerate(zip(result.boxes.xyxy, result.boxes.cls)):
                plant_type = self.detection_model.names[int(cls)]
                
                # 分析叶片健康
                health_analysis = self.analyze_leaf_health(image, box.cpu().numpy())
                
                # 获取养护建议
                care_recommendations = self.get_care_recommendations(
                    plant_type, health_analysis['health_status']
                )
                
                analysis_results.append({
                    'plant_id': i + 1,
                    'plant_type': plant_type,
                    'bbox': box.cpu().numpy().tolist(),
                    'health_analysis': health_analysis,
                    'care_recommendations': care_recommendations
                })
        
        # 可视化结果
        self.visualize_plant_analysis(image_path, analysis_results)
        
        return analysis_results
    
    def visualize_plant_analysis(self, image_path, analysis_results):
        """可视化植物分析结果"""
        result_img = cv2.imread(image_path)
        result_img = cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
        
        # 绘制检测框和健康状态
        for result in analysis_results:
            bbox = result['bbox']
            x1, y1, x2, y2 = map(int, bbox)
            
            # 根据健康状态选择颜色
            health_status = result['health_analysis']['health_status']
            if "健康" in health_status:
                color = (0, 255, 0)  # 绿色
            elif "问题" in health_status:
                color = (0, 255, 255)  # 黄色
            else:
                color = (0, 0, 255)  # 红色
            
            # 绘制边界框
            cv2.rectangle(result_img, (x1, y1), (x2, y2), color, 2)
            
            # 添加标签(使用Pillow绘制中文)
            from PIL import Image, ImageDraw, ImageFont
            import numpy as np
            
            # 转换为Pillow格式
            pil_img = Image.fromarray(result_img)
            draw = ImageDraw.Draw(pil_img)
            
            # 加载中文字体(确保系统中存在该字体)
            font_path = "simhei.ttf"  # 黑体字体文件路径
            font = ImageFont.truetype(font_path, 20)
            
            # 绘制中文文本
            label = f"{result['plant_type']}: {health_status}"
            draw.text((x1, y1 - 30), label, font=font, fill=color)
            
            # 转换回OpenCV格式
            result_img = np.array(pil_img)
        
        # 显示结果
        plt.figure(figsize=(12, 8))
        plt.imshow(result_img)
        plt.axis('off')
        plt.title('植物健康监测结果')
        plt.tight_layout()
        plt.show()
        
        # 打印详细建议
        print("\n=== 植物养护建议 ===")
        for result in analysis_results:
            print(f"\n植物 {result['plant_id']} ({result['plant_type']}):")
            print(f"健康状态: {result['health_analysis']['health_status']} "
                  f"(置信度: {result['health_analysis']['confidence']:.2f})")
            print("养护建议:")
            for recommendation in result['care_recommendations']:
                print(f"  - {recommendation}")

# 使用示例
plant_monitor = PlantHealthMonitor()
results = plant_monitor.full_plant_analysis('garden_plants.jpg')

3. 重要节点

  • 环境配置与中文支持:
    • 使用matplotlib绘图时设置中文字体,避免中文显示乱码。
  • 植物健康监测类(PlantHealthMonitor):
    • 初始化时加载YOLO模型,并定义植物养护信息。
  • 植物检测:
    • 使用YOLO模型对输入图像进行植物检测,返回检测结果。
  • 叶片健康分析:
    • 提取检测到的植物区域(叶片),转换为HSV颜色空间。
    • 通过设定绿色、黄色、褐色的HSV范围,创建掩膜,计算各颜色像素所占比例。
    • 根据颜色比例判断叶片健康状况,并返回健康状态、置信度和颜色分析结果。
  • 养护建议:
    • 根据植物类型和健康状态,从预定义的植物养护信息中获取基础养护建议,并根据健康状态添加特别建议。
  • 完整分析流程:
    • 对图像进行植物检测,对每个检测到的植物进行健康分析,生成养护建议,并可视化结果。
  • 可视化:
    • 使用OpenCV和Pillow结合绘制检测框和中文标签,显示植物健康状态,并打印详细的养护建议。

4. 代码分析

4.1 植物健康诊断算法

python 复制代码
# 转换为HSV颜色空间分析
hsv = cv2.cvtColor(leaf_img, cv2.COLOR_RGB2HSV)

# 分析颜色特征
green_mask = cv2.inRange(hsv, (36, 25, 25), (86, 255, 255))
yellow_mask = cv2.inRange(hsv, (20, 100, 100), (30, 255, 255))
brown_mask = cv2.inRange(hsv, (10, 100, 20), (20, 255, 200))
  • HSV颜色空间:比RGB更适合颜色分析和分割
  • 颜色阈值设定:基于植物学知识的专业参数
    • 绿色范围(36-86):健康叶绿素反射
    • 黄色范围(20-30):缺素或病害早期
    • 褐色范围(10-20):严重病害或枯萎

4.2 专家知识系统

python 复制代码
self.plant_care_info = {
    'rose': {
        'water': '每周浇水2-3次,保持土壤湿润',
        'sunlight': '需要充足阳光,每天6小时以上',
        # ... 其他养护信息
    }
}
  • 结构化存储:按植物种类分类存储专业知识
  • 多维度建议:涵盖浇水、光照、施肥等关键因素
  • 问题诊断:包含常见病害和解决方案

4.3 混合可视化技术

python 复制代码
# OpenCV绘制边界框
cv2.rectangle(result_img, (x1, y1), (x2, y2), color, 2)

# Pillow渲染中文文本
pil_img = Image.fromarray(result_img)
draw = ImageDraw.Draw(pil_img)
font = ImageFont.truetype(font_path, 20)
draw.text((x1, y1 - 30), label, font=font, fill=color)
  • 技术融合:结合OpenCV的图形绘制和Pillow的文字渲染
  • 颜色编码:用不同颜色直观表示健康状态
  • 中文优化:解决计算机视觉中的中文显示难题

5. 输出结果

image 1/1 D:\AIWorld\case\test\garden_plants.jpg: 448x640 2 potted plants, 2 vases, 62.2ms

Speed: 2.6ms preprocess, 62.2ms inference, 1.8ms postprocess per image at shape (1, 3, 448, 640)

=== 植物养护建议 ===

植物 1 (potted plant):

健康状态: 状态未知 (置信度: 0.50)

养护建议:

  • 未知植物类型,建议咨询专业园艺师

植物 2 (vase):

健康状态: 状态未知 (置信度: 0.50)

养护建议:

  • 未知植物类型,建议咨询专业园艺师

植物 3 (potted plant):

健康状态: 状态未知 (置信度: 0.50)

养护建议:

  • 未知植物类型,建议咨询专业园艺师

植物 4 (vase):

健康状态: 状态未知 (置信度: 0.50)

养护建议:

  • 未知植物类型,建议咨询专业园艺师

结果图例:

分析后的结果图:

四、宠物行为分析器

1. 场景描述

基于YOLO模型的宠物行为分析器的代码,它使用YOLO模型来检测宠物(猫和狗),然后通过简单的宽高比分析来估计宠物的姿态(坐着、站着、躺着),并根据姿态和活动水平提供行为解释和健康建议,此外,代码还提供了视频分析功能,可以处理视频文件并生成行为报告。

2. 示例代码

python 复制代码
import cv2
from ultralytics import YOLO
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False    # 正常显示负号
class PetBehaviorAnalyzer:
    def __init__(self, model_size='n'):
        self.model = YOLO(f'yolov8{model_size}.pt')
        
        # 宠物行为分析规则
        self.behavior_rules = {
            'dog': {
                'sitting': '正常休息状态',
                'standing': '警觉或等待状态', 
                'lying': '深度休息',
                'running': '活跃玩耍',
                'eating': '进食时间',
                'drinking': '补充水分'
            },
            'cat': {
                'sitting': '观察环境',
                'standing': '准备行动', 
                'lying': '放松休息',
                'running': '玩耍或追逐',
                'eating': '进食时间',
                'drinking': '补充水分'
            }
        }
        
        # 宠物健康建议
        self.health_advice = {
            'dog': {
                'active': '运动量充足,继续保持',
                'inactive': '建议增加散步和游戏时间',
                'eating_well': '食欲正常',
                'not_eating': '注意观察食欲变化'
            },
            'cat': {
                'active': '活泼好动,状态良好',
                'inactive': '可能需要注意健康状态',
                'eating_well': '进食正常',
                'not_eating': '猫咪不进食需要关注'
            }
        }
    
    def detect_pets(self, image_path):
        """检测宠物"""
        results = self.model.predict(source=image_path, conf=0.4)
        return results[0]
    
    def analyze_pose(self, image, bbox, pet_type):
        """分析宠物姿态"""
        x1, y1, x2, y2 = map(int, bbox)
        pet_region = image[y1:y2, x1:x2]
        
        if pet_region.size == 0:
            return 'unknown'
        
        # 简单的姿态分析(实际应用中可以使用姿态估计模型)
        height = y2 - y1
        width = x2 - x1
        aspect_ratio = width / height if height > 0 else 1
        
        # 基于宽高比的简单姿态判断
        if aspect_ratio > 1.5:
            return 'lying'  # 躺着
        elif aspect_ratio < 0.7:
            return 'standing'  # 站着
        else:
            return 'sitting'  # 坐着
    
    def estimate_activity_level(self, pose, movement_data=None):
        """估计活动水平"""
        active_poses = ['running', 'jumping', 'playing']
        inactive_poses = ['lying', 'sleeping']
        
        if pose in active_poses:
            return 'active'
        elif pose in inactive_poses:
            return 'inactive'
        else:
            return 'moderate'
    
    def analyze_pet_behavior(self, image_path):
        """分析宠物行为"""
        result = self.detect_pets(image_path)
        image = cv2.imread(image_path)
        image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        
        pet_analyses = []
        
        if result.boxes is not None:
            for i, (box, cls, conf) in enumerate(zip(result.boxes.xyxy, result.boxes.cls, result.boxes.conf)):
                class_name = self.model.names[int(cls)]
                
                # 只关注宠物类别
                if class_name in ['dog', 'cat']:
                    # 分析姿态
                    pose = self.analyze_pose(image_rgb, box.cpu().numpy(), class_name)
                    
                    # 分析活动水平
                    activity_level = self.estimate_activity_level(pose)
                    
                    # 获取行为解释
                    behavior_explanation = self.behavior_rules[class_name].get(
                        pose, '行为状态未知'
                    )
                    
                    # 获取健康建议
                    health_advice = self.health_advice[class_name].get(
                        activity_level, '状态正常'
                    )
                    
                    pet_analyses.append({
                        'pet_id': i + 1,
                        'pet_type': class_name,
                        'confidence': conf.cpu().numpy(),
                        'pose': pose,
                        'activity_level': activity_level,
                        'behavior_explanation': behavior_explanation,
                        'health_advice': health_advice,
                        'bbox': box.cpu().numpy().tolist()
                    })
        
        # 可视化结果
        self.visualize_pet_analysis(image_path, pet_analyses)
        
        return pet_analyses
    
    def visualize_pet_analysis(self, image_path, pet_analyses):
        """可视化宠物分析结果"""
        result_img = cv2.imread(image_path)
        result_img = cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
        
        # 绘制检测框和行为信息
        for analysis in pet_analyses:
            bbox = analysis['bbox']
            x1, y1, x2, y2 = map(int, bbox)
            
            # 根据活动水平选择颜色
            if analysis['activity_level'] == 'active':
                color = (0, 255, 0)  # 绿色 - 活跃
            elif analysis['activity_level'] == 'inactive':
                color = (0, 0, 255)  # 红色 - 不活跃
            else:
                color = (0, 255, 255)  # 黄色 - 中等
            
            # 绘制边界框
            cv2.rectangle(result_img, (x1, y1), (x2, y2), color, 2)
            
            # 添加标签
            label = f"{analysis['pet_type']} - {analysis['pose']}"
            cv2.putText(result_img, label, (x1, y1 - 10), 
                       cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
        
        # 显示结果
        plt.figure(figsize=(12, 7))
        plt.imshow(result_img)
        plt.axis('off')
        plt.title('宠物行为分析结果')
        plt.tight_layout()
        plt.show()
        
        # 打印详细分析
        print("\n=== 宠物行为分析报告 ===")
        for analysis in pet_analyses:
            print(f"\n宠物 {analysis['pet_id']} ({analysis['pet_type']}):")
            print(f"检测置信度: {analysis['confidence']:.2f}")
            print(f"姿态: {analysis['pose']}")
            print(f"活动水平: {analysis['activity_level']}")
            print(f"行为解释: {analysis['behavior_explanation']}")
            print(f"健康建议: {analysis['health_advice']}")

# 使用示例
pet_analyzer = PetBehaviorAnalyzer('n')
results = pet_analyzer.analyze_pet_behavior('pet_photo.jpg')

# 视频分析版本
def analyze_pet_video(video_path, output_path):
    """分析宠物视频"""
    pet_analyzer = PetBehaviorAnalyzer('n')
    
    cap = cv2.VideoCapture(video_path)
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
    
    frame_count = 0
    behavior_log = []
    
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        
        # 临时保存帧并分析
        temp_path = f'temp_frame_{frame_count}.jpg'
        cv2.imwrite(temp_path, frame)
        
        # 分析当前帧
        analyses = pet_analyzer.analyze_pet_behavior(temp_path)
        
        # 记录行为
        for analysis in analyses:
            behavior_log.append({
                'frame': frame_count,
                'timestamp': frame_count / fps,
                'pet_type': analysis['pet_type'],
                'pose': analysis['pose'],
                'activity_level': analysis['activity_level']
            })
        
        # 读取带标注的帧
        annotated_frame = cv2.imread(temp_path)
        out.write(annotated_frame)
        
        frame_count += 1
        
        # 清理临时文件
        import os
        os.remove(temp_path)
        
        if frame_count % 100 == 0:  # 每30帧打印进度
            print(f"已处理 {frame_count} 帧")
    
    cap.release()
    out.release()
    
    # 生成行为报告
    generate_behavior_report(behavior_log, fps)
    
    return behavior_log

def generate_behavior_report(behavior_log, fps):
    """生成宠物行为报告"""
    if not behavior_log:
        print("未检测到宠物行为")
        return
    
    # 统计行为分布
    poses = [log['pose'] for log in behavior_log]
    pose_counts = {}
    for pose in poses:
        pose_counts[pose] = pose_counts.get(pose, 0) + 1
    
    activities = [log['activity_level'] for log in behavior_log]
    activity_counts = {}
    for activity in activities:
        activity_counts[activity] = activity_counts.get(activity, 0) + 1
    
    total_frames = len(behavior_log)
    
    print("\n=== 宠物行为分析报告 ===")
    print(f"分析时长: {total_frames / fps:.1f} 秒")
    print(f"总帧数: {total_frames}")
    
    print("\n姿态分布:")
    for pose, count in pose_counts.items():
        percentage = (count / total_frames) * 100
        print(f"  {pose}: {count} 帧 ({percentage:.1f}%)")
    
    print("\n活动水平分布:")
    for activity, count in activity_counts.items():
        percentage = (count / total_frames) * 100
        print(f"  {activity}: {count} 帧 ({percentage:.1f}%)")
    
    # 活动水平评估
    active_percentage = activity_counts.get('active', 0) / total_frames * 100
    if active_percentage > 50:
        print("\n评估: 宠物非常活跃,状态良好")
    elif active_percentage > 20:
        print("\n评估: 宠物活动水平正常")
    else:
        print("\n评估: 宠物较为安静,建议观察健康状况")

# 使用视频分析
behavior_log = analyze_pet_video('pet_video.mp4', 'analyzed_pet_video.mp4')

3. 代码分析

  • YOLO模型的使用:加载YOLOv8模型进行目标检测,识别图像中的猫和狗。
  • 姿态分析:通过边界框的宽高比来简单判断宠物的姿态。这是一种简化的方法,实际应用中可能需要更复杂的姿态估计模型。
  • 活动水平评估:根据姿态判断活动水平(活跃、不活跃、中等)。
  • 知识库规则:基于预定义的行为规则和健康建议,为检测到的宠物提供解释和建议。
  • 可视化:使用OpenCV和matplotlib绘制检测框和标签,并显示结果。
  • 视频处理:逐帧分析视频,记录行为日志,并生成统计报告。

3.1 基于几何特征的姿态识别算法

python 复制代码
def analyze_pose(self, image, bbox, pet_type):
    height = y2 - y1
    width = x2 - x1
    aspect_ratio = width / height if height > 0 else 1
    
    if aspect_ratio > 1.5:
        return 'lying'  # 躺着
    elif aspect_ratio < 0.7:
        return 'standing'  # 站着
    else:
        return 'sitting'  # 坐着
  • 宽高比分析:利用边界框的几何特征推断姿态
  • 阈值设定:基于大量观察数据设定的经验阈值
    • 宽高比>1.5:躺卧姿态(身体横向展开)
    • 宽高比<0.7:站立姿态(身体纵向伸展)
    • 其他情况:坐姿(中等宽高比)

3.2 活动水平评估机制

python 复制代码
def estimate_activity_level(self, pose, movement_data=None):
    active_poses = ['running', 'jumping', 'playing']
    inactive_poses = ['lying', 'sleeping']
    
    if pose in active_poses:
        return 'active'
    elif pose in inactive_poses:
        return 'inactive'
    else:
        return 'moderate'

评估逻辑:

  • 三级分类:活跃、中等、不活跃
  • 姿态映射:基于姿态类型的活动强度推断
  • 可扩展性:预留运动数据接口用于未来增强

3.3 时序行为分析系统

python 复制代码
def analyze_pet_video(video_path, output_path):
    behavior_log = []
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        
        # 分析当前帧并记录行为
        analyses = pet_analyzer.analyze_pet_behavior(temp_path)
        for analysis in analyses:
            behavior_log.append({
                'frame': frame_count,
                'timestamp': frame_count / fps,
                'pet_type': analysis['pet_type'],
                'pose': analysis['pose'],
                'activity_level': analysis['activity_level']
            })

时序分析:

  • 连续监测:逐帧分析构建时间序列数据
  • 行为日志:记录完整的行为变化历史
  • 统计分析:基于时间序列的行为模式分析

4. 输出结果

image 1/1 D:\AIWorld\case\test\pet_photo.jpg: 448x640 1 cat, 73.3ms

Speed: 60.3ms preprocess, 73.3ms inference, 1.3ms postprocess per image at shape (1, 3, 448, 640)

=== 宠物行为分析报告 ===

宠物 1 (cat):

检测置信度: 0.86

姿态: sitting

活动水平: moderate

行为解释: 观察环境

健康建议: 状态正常

image 1/1 D:\AIWorld\case\test\temp_frame_0.jpg: 384x640 1 cat, 84.2ms

Speed: 2.1ms preprocess, 84.2ms inference, 0.9ms postprocess per image at shape (1, 3, 384, 640)

=== 宠物行为分析报告 ===

宠物 1 (cat):

检测置信度: 0.90

姿态: sitting

活动水平: moderate

行为解释: 观察环境

健康建议: 状态正常

检测置信度: 0.87

姿态: sitting

活动水平: moderate

行为解释: 观察环境

健康建议: 状态正常

=== 宠物行为分析报告 ===

分析时长: 5.0 秒

总帧数: 121

姿态分布:

sitting: 96 帧 (79.3%)

lying: 25 帧 (20.7%)

活动水平分布:

moderate: 96 帧 (79.3%)

inactive: 25 帧 (20.7%)

评估: 宠物较为安静,建议观察健康状况

结果图例:

分析后的结果图:

视频逐帧分析结果:

五、总结

通过以上三个示例场景,我们看到了YOLO模型在生活中的多样化应用。从厨房的食材识别到植物的健康监测,以及宠物行为的分析,YOLO模型以其高效准确的检测能力,为我们的日常生活提供了智能化的解决方案。

这些应用不仅提升了生活品质,也展示了计算机视觉技术的巨大潜力。对于初学者而言,通过这些贴近生活的项目,可以更容易地理解和掌握YOLO模型的使用方法,并激发对人工智能技术的兴趣。我们学习也不要停留在模型原理的纸面理解,要通过具体项目将YOLO应用于真实场景。建议选择贴近生活的应用主题,如智能家居、健康监测等,这样既能保持学习兴趣,又能积累实战经验。YOLO在实际应用中也需要与其他技术配合使用,点学习OpenCV图像处理、颜色空间分析、数据可视化等配套技术,构建完整的技术解决方案。

相关推荐
t198751282 小时前
基于盲源分离与贝叶斯非局部均值(BM3D)的图像降噪算法实现
算法·计算机视觉·均值算法
化作星辰3 小时前
解决 OpenCV imread 在 Windows 中读取包含中文路径图片失败的问题
人工智能·opencv·计算机视觉
CoovallyAIHub3 小时前
CV研究告别数据荒?PAN世界模型实现「多步推理与规划」,可自造高质量训练数据
深度学习·算法·计算机视觉
极客BIM工作室3 小时前
多模态大模型的数据准备:从模态对齐到结构化成果
人工智能·深度学习·计算机视觉
翔云 OCR API4 小时前
NFC护照鉴伪查验流程解析-ICAO9303护照真伪查验接口技术方案
开发语言·人工智能·python·计算机视觉·ocr
CoovallyAIHub4 小时前
智能体与小模型:AI迈向平民化的新浪潮
深度学习·算法·计算机视觉
zl_vslam9 小时前
SLAM中的非线性优-3D图优化之李群李代数在Opencv-PNP中的应用(四)
人工智能·opencv·算法·计算机视觉
菜鸟学3219 小时前
opencv代码分析
人工智能·opencv·计算机视觉
xuehaikj21 小时前
【深度学习】YOLOv10n-MAN-Faster实现包装盒flap状态识别与分类,提高生产效率
深度学习·yolo·分类