AI计算机视觉笔记十:结印动作识别

简介: 该项目基于恩培大佬的《火影结印识别》小项目,使用yolov5实现手势识别功能。项目包含数据集准备、模型训练和代码实现,可在无GPU环境下运行。代码利用状态机检测手势序列,完成特定结印后触发音效播放。[GitHub地址](https://github.com/enpeizhao/CVprojects)提供了详细步骤和示例代码。

感谢恩培大佬对项目进行了完整的实现,并将代码进行开源,供大家交流学习。

恩培大佬开源地址,有兴趣的可以去复现一下。GitHub - enpeizhao/CVprojects: computer vision projects | 计算机视觉相关好玩的AI项目(Python、C++)

一、介绍
从恩培大佬的git上看到的小项目《火影结印识别》,发现大佬开源的代码是需要GPU的,本人电脑没有GPU,环境安装好了,没复现成功,所以取巧使用yolov5的方式实现一样的功能。
image.png
yolov5安装及训练前面有提及,不熟悉yolov5训练可以看前面文章。

二、训练集
准备素材,训练的手势共有七种,每种采集30张图片,并使用lableImg标注所有图片。
image.png
image.png
label标签
image.png
三、训练
训练使用的是AutoDL云端训练,样本不多,训练大概20-30分钟,用的是3090显卡。

这有有个注意的,直接使用AutoDL提供的镜像训练出来的pt文件一直识别检测不到,所以又换回yolov5-5版本,训练出来正常。
image.png
效果还行,想要复现就得自己训练。

四、代码

1、生成字幕需要的中文PNG图片

PNG图片是为了把识别到的字显示出来,使用OPENCV不好显示中心,所以提前准备好png直接在视频内叠加PNG图片。

'''
生成字幕需要的中文PNG图片
'''

from PIL import Image,ImageDraw,ImageFont

def generate(name='你好',color_label='green'):

    filename = './png_label/'+name+'.png'

    # 背景
    bg = Image.new("RGBA",(400,100),(0,0,0,0))
    # 添加文字
    d = ImageDraw.Draw(bg)
    font  = ImageFont.truetype('./fonts/MSYH.ttc',80,encoding="utf-8")

    if color_label == 'green':
        color = (0,255,0,255)
    else:
        color = (255,0,0,255)


    d.text((0,0),name,font=font,fill=color)
    # 保存
    bg.save(filename)

    print('ok: '+ name)


generate('火遁豪火球之术','red')

运行后,会生成PNG图片。
image.png

2、完整代码

import ctypes
import cv2
import numpy as np
import time

# 多进程
from multiprocessing import Process, Value
import threading

import torch
import sys
from playsound import playsound


class Ai_tello:
    def __init__(self):
        # ************************************ 绘制 相关 *********************************
        self.png_dict = {}
        # 获取
        self.getPngList()

        # 加载 yolov5模型
        self.model = torch.hub.load('./yolov5', 'custom', './weights/pose.pt',source='local') 
        # 置信度阈值
        self.model.conf = 0.5
        print('self.model.conf = 0.5')

        self.take_off_time = None
        # 结印动作顺序
        self.yolo_action_seq = ['ani_1', 'ani_2','ani_3', 'ani_4', 'ani_5', 'ani_6', 'ani_7']
        # 状态机,1表示当前动作已做完(击中)
        self.yolo_action_status = [0, 0, 0, 0, 0, 0, 0]

    def getPngList(self):
        '''
        读取PNG图片,追加进png_dict
        '''
        palm_action = {'ani_1': '巳', 'ani_2': '未', 'ani_3': '申',
            'ani_4': '亥', 'ani_5': '午', 'ani_6': '寅', 'ani_7':'火遁豪火球之术'}

        for name in palm_action.values():
            filename = './png_label/'+name+'.png'
            png_img = self.readPngFile(filename, 0.9)
            self.png_dict[name] = png_img

        print('PNG文字标签加载完毕')

    def playVoice(self, fileName,mode):
        """
        播放音乐
        """
        playsound(fileName)

    def backPlay(self,fileName):
        """
        后台播放
        """
        t = threading.Thread(target=self.playVoice, args=(fileName,'voice'))
        t.start()

    def readPngFile(self, fileName, scale=0.5):
        '''
        读取PNG图片
        '''
        # 解决中文路径问题
        png_img = cv2.imdecode(np.fromfile(fileName, dtype=np.uint8), -1)
        # 转为BGR,变成3通道
        png_img = cv2.cvtColor(png_img, cv2.COLOR_RGB2BGR)
        png_img = cv2.resize(png_img, (0, 0), fx=scale, fy=scale)
        return png_img

    def addOverylay(self, frame, overlay, l, t):
        '''
        添加标签png覆盖
        '''
        # 解决l、t超界
        l = max(l, 0)
        t = max(t, 0)
        # 覆盖显示
        overlay_h, overlay_w = overlay.shape[:2]
        # 覆盖范围
        overlay_l, overlay_t = l, t
        overlay_r, overlay_b = (l + overlay_w), (overlay_t+overlay_h)
        # 遮罩
        overlay_copy = cv2.addWeighted(
            frame[overlay_t:overlay_b, overlay_l:overlay_r], 1, overlay, 20, 0)

        frame[overlay_t:overlay_b, overlay_l:overlay_r] = overlay_copy


    def cameraProcess(self):
        '''
        视频流处理:动作识别、绘制等
        '''
        print('cameraProcess');
        cap = cv2.VideoCapture(0)
        # 动作
        palm_action = {'ani_1':'巳','ani_2':'未','ani_3':'申','ani_4':'亥','ani_5':'午','ani_6':'寅','ani_7':'火遁豪火球之术'}

        triger_time = time.time()

        while True:

            # 读取视频帧
            ret,frame = cap.read()
            if frame is None:
                continue;

            frame = cv2.flip(frame, 1)


            # 转为RGB
            img_cvt = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)

            if self.take_off_time != None:  
                if time.time() - triger_time >= 2:
                    label_zh = palm_action['ani_7']
                    overlay = self.png_dict[label_zh]
                    self.addOverylay(frame,overlay,l,200)
            else:
                # 目标检测推理
                results = self.model(img_cvt)
                results_arr = results.pandas().xyxy[0].to_numpy()

                # 解析目标检测结果
                for item in results_arr:

                    # 标签ID
                    ret_label_id = item[-2]
                    # 标签名称
                    ret_label_text = item[-1]
                    # 置信度
                    ret_conf = item[-3]


                    # ani_1,ani_2....ani_6
                    # 结印动作,且置信度要求高一些
                    if 'ani_' in  ret_label_text and ret_conf >= 0.7:

                        l,t,r,b = item[:4].astype('int')
                        # 绘制
                        cv2.rectangle(frame,(l,t),(r,b),(0,255,20),2)
                        # 绘制动作中文png                        
                        label_zh = palm_action[ret_label_text]
                        print(ret_label_text)
                        # 拿到对应中文文字的数组图片
                        overlay = self.png_dict[label_zh]
                        # 覆盖绘制
                        self.addOverylay(frame,overlay,l,t-100)
                        cv2.putText(frame,'{}%'.format(round(ret_conf*100,2)),(l+80,t-20),cv2.FONT_ITALIC,1.5,(255,0,255),2)


                        # 状态机列表中第一个0的索引
                        first_0_index = next(i for i,x in enumerate(self.yolo_action_status) if x == 0 )
                        # 对应动作名 ['ani_1', 'ani_2','ani_3', 'ani_4', 'ani_5', 'ani_6']
                        check_action_name = self.yolo_action_seq[first_0_index]

                        # 动作匹配
                        if ret_label_text == check_action_name:
                            # 赋值1
                            self.yolo_action_status[first_0_index] = 1
                            # 检查是否完毕
                            if self.yolo_action_status == [1,1,1,1,1,1,1]:

                                self.take_off_time = time.time()
                                print('动作全部匹配完')

                                self.backPlay('火遁豪火球.mp3')

                                # 计时
                                triger_time = time.time()

                            else:
                                print('击中一个动作,当前列表为'+str(self.yolo_action_status))
                        else:
                            print('未击中动作,当前列表为'+str(self.yolo_action_status))

            cv2.imshow('demo', frame)
            if cv2.waitKey(10) & 0xFF == ord('q'):
                break

        cv2.destroyAllWindows()


if __name__ == '__main__':

    # 实例化
    ai_tello = Ai_tello()
    ai_tello.cameraProcess()

代码有几个需要注意的:

一、加载 yolov5模型

加载 yolov5模型时,有可能出错,遇到的问题是版本不同,使用的是yolov5-5版本训练的,加载的文件不是,出错。

二、识别流程

识别采用的状态机方式,即事先定义一下数组【0,0,0,0,0,0,0】共7个元素,

当检测到对应动作时就置1,当数组全部为1时,就播放声音。

五、效果演示

https://www.bilibili.com/video/BV1eh4y1v7xi/

相关文章
|
3月前
|
人工智能 测试技术 API
AI计算机视觉笔记二十 九:yolov10竹签模型,自动数竹签
本文介绍了如何在AutoDL平台上搭建YOLOv10环境并进行竹签检测与计数。首先从官网下载YOLOv10源码并创建虚拟环境,安装依赖库。接着通过官方模型测试环境是否正常工作。然后下载自定义数据集并配置`mycoco128.yaml`文件,使用`yolo detect train`命令或Python代码进行训练。最后,通过命令行或API调用测试训练结果,并展示竹签计数功能。如需转载,请注明原文出处。
|
3月前
|
机器学习/深度学习 人工智能 PyTorch
AI计算机视觉笔记三十二:LPRNet车牌识别
LPRNet是一种基于Pytorch的高性能、轻量级车牌识别框架,适用于中国及其他国家的车牌识别。该网络无需对字符进行预分割,采用端到端的轻量化设计,结合了squeezenet和inception的思想。其创新点在于去除了RNN,仅使用CNN与CTC Loss,并通过特定的卷积模块提取上下文信息。环境配置包括使用CPU开发板和Autodl训练环境。训练和测试过程需搭建虚拟环境并安装相关依赖,执行训练和测试脚本时可能遇到若干错误,需相应调整代码以确保正确运行。使用官方模型可获得较高的识别准确率,自行训练时建议增加训练轮数以提升效果。
|
3月前
|
人工智能 开发工具 计算机视觉
AI计算机视觉笔记三十:yolov8_obb旋转框训练
本文介绍了如何使用AUTODL环境搭建YOLOv8-obb的训练流程。首先创建虚拟环境并激活,然后通过指定清华源安装ultralytics库。接着下载YOLOv8源码,并使用指定命令开始训练,过程中可能会下载yolov8n.pt文件。训练完成后,可使用相应命令进行预测测试。
|
3月前
|
人工智能 并行计算 测试技术
AI计算机视觉笔记三十一:基于UNetMultiLane的多车道线等识别
该项目基于开源数据集 VIL100 实现了 UNetMultiLane,用于多车道线及车道线类型的识别。数据集中标注了六个车道的车道线及其类型。项目详细记录了从环境搭建到模型训练与测试的全过程,并提供了在 CPU 上进行训练和 ONNX 转换的代码示例。训练过程约需 4 小时完成 50 个 epoch。此外,还实现了视频检测功能,可在视频中实时识别车道线及其类型。
|
3月前
|
人工智能 监控 算法
AI计算机视觉笔记二十 八:基于YOLOv8实例分割的DeepSORT多目标跟踪
本文介绍了YOLOv8实例分割与DeepSORT视觉跟踪算法的结合应用,通过YOLOv8进行目标检测分割,并利用DeepSORT实现特征跟踪,在复杂环境中保持目标跟踪的准确性与稳定性。该技术广泛应用于安全监控、无人驾驶等领域。文章提供了环境搭建、代码下载及测试步骤,并附有详细代码示例。
|
7月前
|
机器学习/深度学习 计算机视觉
AIGC核心技术——计算机视觉(CV)预训练大模型
【1月更文挑战第13天】AIGC核心技术——计算机视觉(CV)预训练大模型
643 3
AIGC核心技术——计算机视觉(CV)预训练大模型
|
机器学习/深度学习 PyTorch 算法框架/工具
Azure 机器学习 - 使用 ONNX 对来自 AutoML 的计算机视觉模型进行预测
Azure 机器学习 - 使用 ONNX 对来自 AutoML 的计算机视觉模型进行预测
130 0
|
3月前
|
人工智能 测试技术 PyTorch
AI计算机视觉笔记二十四:YOLOP 训练+测试+模型评估
本文介绍了通过正点原子的ATK-3568了解并实现YOLOP(You Only Look Once for Panoptic Driving Perception)的过程,包括训练、测试、转换为ONNX格式及在ONNX Runtime上的部署。YOLOP由华中科技大学团队于2021年发布,可在Jetson TX2上达到23FPS,实现了目标检测、可行驶区域分割和车道线检测的多任务学习。文章详细记录了环境搭建、训练数据准备、模型转换和测试等步骤,并解决了ONNX转换过程中的问题。
|
5月前
|
自然语言处理 监控 自动驾驶
大模型在自然语言处理(NLP)、计算机视觉(CV)和多模态模型等领域应用最广
【7月更文挑战第26天】大模型在自然语言处理(NLP)、计算机视觉(CV)和多模态模型等领域应用最广
264 11
|
6月前
|
编解码 机器人 测试技术
2024年6月计算机视觉论文推荐:扩散模型、视觉语言模型、视频生成等
6月还有一周就要结束了,我们今天来总结2024年6月上半月发表的最重要的论文,重点介绍了计算机视觉领域的最新研究和进展。
159 8