足球视频AI(四)——队伍与裁判人员分类

news2024/11/16 5:58:11

一、基础概念

在这里插入图片描述

足球比赛中人员为:A队11人、B队11人、裁判,其中我们暂时不研究守门员。

需要将球场中的人员分类,并呈现在2D看板中。

1.1识别目标:

1)球场中的白队

2)球场中的蓝队

3)球场中的裁判

1.2 实现思路

方案一:自建深度学习网络Relu(主要介绍)

1)采用keras训练深度网络形成H5模型文件

2)H5文件转onnx文件

方案二:采用Yolo7训练网络

工程应用

二、训练Keras网络

依赖python包

autopep8==1.5.4
certifi==2020.6.20
chardet==3.0.4
cycler==0.10.0
idna==2.10
kiwisolver==1.2.0
matplotlib==3.3.1
mercurial==5.5
numpy==1.19.1
opencv-python==4.5.1.48
packaging==20.4
pandas==1.1.1
Pillow==7.2.0
pycodestyle==2.6.0
pyparsing==2.4.7
PyQt5==5.14.2
PyQt5-sip==12.11.0
pyqtgraph==0.11.0
python-dateutil==2.8.1
pytz==2020.1
requests==2.24.0
requests-cache==0.5.2
sip==5.4.0
six==1.15.0
toml==0.10.2
urllib3==1.25.11

依赖环境

Python 3.8 、 tensoflow 2.0(含keras)、

2.1 Python网络模型

import tensorflow as tf
from tensorflow import keras
from sklearn.model_selection import train_test_split
import numpy as np
from keras.datasets import mnist
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator
import os
import glob
import cv2
from google.colab.patches import cv2_imshow
import base64
from IPython.display import clear_output, Image

device_name = tf.test.gpu_device_name()
if device_name != '/device:GPU:0':
  print(
      '\n\nThis error most likely means that this notebook is not '
      'configured to use a GPU.  Change this in Notebook Settings via the '
      'command palette (cmd/ctrl-shift-P) or the Edit menu.\n\n')
  raise SystemError('GPU device not found')

tf.__version__, keras.__version__

# LABELS
BLUE, WHITE, REF = 0, 1, 2

def reading_files(path, label):
  files = glob.glob(path)
  data, labels = [], []
  
  for file in files:
    I = cv2.imread(file)
    data.append(I)
    l = np.zeros((3,))
    l[label] = 1
    labels.append(l)

  return np.array(data, dtype=np.float32), np.array(labels, dtype=np.float32)

def load_data(shuffle=True):
  X, Y = None, None
  checker = lambda X, M: M if X is None else np.vstack([M, X])

  for path, label in (("./blue/*.jpg", BLUE),
                      ("./white/*.jpg", WHITE), ("./referee/*.jpg", REF)):
    data, labels = reading_files(path, label)
    X = checker(X, data)
    Y = checker(Y, labels)
  if shuffle:
    initial_shape_X, initial_shape_Y = X.shape, Y.shape

    feature_count = np.prod(np.array([*X.shape[1:]]))
    whole_d = np.hstack([X.reshape(X.shape[0], -1), Y])

    np.random.shuffle(whole_d)
    X = whole_d[:, :feature_count].reshape(initial_shape_X)
    Y = whole_d[:, feature_count:]
  
  return X, Y
  
def des_label(label):
  i = np.argmax(label)
  return ("BLUE", "WHITE", "REFEREE")[i]

X, Y = load_data()
X.shape, Y.shape

# showing one image
print(des_label(Y[0]))
cv2_imshow(X[0])

# train test split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.1,
                                                    shuffle=True,
                                                    random_state=41)
X_train, X_val, Y_train, Y_val = train_test_split(X_train, Y_train, 
                                                test_size=0.15,
                                                shuffle=True,
                                                random_state=41)
X_train.shape, X_test.shape, Y_train.shape, Y_test.shape, X_val.shape, Y_val.shape

# preprocess
scaler = MinMaxScaler()
main_shape_X_train = X_train.shape
main_shape_X_test  = X_test.shape
scaler_train = scaler.fit(X_train.reshape(X_train.shape[0], -1))

X_train = scaler.transform(X_train.reshape(X_train.shape[0], -1)).reshape(main_shape_X_train)
X_test  = scaler.fit_transform(X_test.reshape(X_test.shape[0], -1)).reshape(*main_shape_X_test)
np.max(X_train[0].ravel()), np.min(X_train[0].ravel()), X_train.shape

def naive_inception_module(layer_in, f1=2, f2=2, f3=2):
	# 1x1 conv
	conv1 = keras.layers.Conv2D(f1, (1,1), padding='same', activation='relu')(layer_in)
	# 3x3 conv
	conv3 =  keras.layers.Conv2D(f2, (3,3), padding='same', activation='relu')(layer_in)
	# 5x5 conv
	conv5 = keras.layers.Conv2D(f3, (5,5), padding='same', activation='relu')(layer_in)
	# 3x3 max pooling
	pool = keras.layers.MaxPooling2D((3,3), strides=(1,1), padding='same')(layer_in)
	# concatenate filters, assumes filters/channels last
	layer_out = keras.layers.concatenate([conv1, conv3, conv5, pool], axis=-1)
	return layer_out

input_layer = keras.layers.Input([*X_train.shape[1:]])

second_layer = keras.layers.Conv2D(20, 5, padding="same")(input_layer)
th_layer = keras.layers.Activation("relu")(second_layer)

inception = naive_inception_module(th_layer)
inception = naive_inception_module(inception)

fo_layer = keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2))(inception)

fi_layer = keras.layers.Flatten()(fo_layer)
x_layer =  keras.layers.Dense(250, 
                kernel_initializer=keras.initializers.HeNormal(),
                kernel_regularizer=keras.regularizers.L1())(fi_layer)
s_layer = keras.layers.Activation(keras.activations.relu)(x_layer)
e_layer =  keras.layers.Dropout(rate=0.5)(s_layer)
  
n_layer =  keras.layers.Dense(100, 
                kernel_initializer=keras.initializers.HeNormal(),
                kernel_regularizer=keras.regularizers.L1())(e_layer)
t_layer =  keras.layers.Activation(keras.activations.relu)(n_layer)
ee_layer =  keras.layers.Dropout(rate=0.5)(t_layer)
out_layer = keras.layers.Dense(3, activation="softmax")(ee_layer)

model = keras.models.Model(inputs=input_layer, outputs=out_layer)
model.summary()

# model lenet 5 or vgg-16
def make_model(input_shape, output_dim):
  layers = []
  # init_kernel = lambda shape, dtype=tf.int32: tf.random.normal(shape, dtype=dtype)
  
  layers.append(keras.layers.Input(input_shape))

  layers.append(keras.layers.Conv2D(20, 5, padding="same", input_shape=input_shape))
  layers.append(keras.layers.Activation("relu"))
  layers.append(keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

  layers.append(keras.layers.Conv2D(20, 5, padding="same"))
  layers.append(keras.layers.Activation("relu"))
  layers.append(keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

  layers.append(keras.layers.Conv2D(10, 5, padding="same"))
  layers.append(keras.layers.Activation("relu"))
  layers.append(keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
  
  layers.append(keras.layers.Flatten())
  layers.append(keras.layers.Dense(80, 
                kernel_initializer=keras.initializers.HeNormal(),
                kernel_regularizer=keras.regularizers.L1()))
  layers.append(keras.layers.Activation(keras.activations.relu))
  layers.append(keras.layers.Dropout(rate=0.5))
  
  layers.append(keras.layers.Dense(50, 
                kernel_initializer=keras.initializers.HeNormal(),
                kernel_regularizer=keras.regularizers.L1()))
  layers.append(keras.layers.Activation(keras.activations.relu))
  layers.append(keras.layers.Dropout(rate=0.5))

  layers.append(keras.layers.Dense(output_dim, activation="softmax"))
  
  model = keras.models.Sequential(layers)  
  model.summary()
  return model

  
model = make_model(input_shape=[*X_train.shape[1:]], output_dim=3)

# compiling
model.compile(optimizer=keras.optimizers.Adam(),
              loss=keras.losses.categorical_crossentropy,
              metrics=["accuracy"])

datagen = ImageDataGenerator( # data augmentation
          rotation_range=30,
          width_shift_range=0.2,
          height_shift_range=0.2,
          zoom_range=0.2,
          fill_mode='nearest')

batch_size = 128
history = model.fit(datagen.flow(X_train, Y_train, batch_size=batch_size),
    validation_data=(X_val, Y_val),                       
    steps_per_epoch=len(Y_train) // batch_size, epochs=50, workers=6)

plt.figure(figsize=(15, 10)) 
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.legend()
plt.grid(True)

plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label='val_accuracy')

plt.legend()
plt.grid(True)
plt.show()
history.history.keys()

model.evaluate(X_test, Y_test)

pred = model.predict(X_test)
np.argmax(pred, axis=1), Y_test

# apply my test
I  = cv2.imread("./my_test/referee.png")
I1 = cv2.imread("./my_test/referee1.png")
I2 = cv2.imread("./my_test/white.png")
I = cv2.resize(I, (80, 80))
I1= cv2.resize(I1, (80, 80)) 
I2= cv2.resize(I2, (80, 80))
cv2_imshow(I1)
cv2_imshow(I)
print(I.shape, I.reshape(1, -1).shape)

X_my_test = np.vstack([[I], [I1], [I2]])
Y_my_labels = np.vstack([np.array([0, 1, 0]),
                         np.array([0, 0, 1]),
                         np.array([0, 0, 1])])

pred = model.predict(X_my_test)
print(X_my_test.shape, Y_my_labels.shape)
np.argmax(pred, axis=1), pred

model_json = model.to_json()
with open("model.json", "w") as json_file:
    json_file.write(model_json)

# serialize weights to HDF5
model.save_weights("model.h5")

因深度学习核心是数据标注,标注的数据无法提供大家自行准备。

准备数据可参见《足球视频AI(三)——YOLOV7目标检测自训练模型》

生成《model.h5》《model.json》文件

2.2 Keras模型H5转Onnx

参见《AI机器学习(五)Keras h5转onnx C# ML 推理》

三、训练YoloV7网络

准备数据可参见《足球视频AI(三)——YOLOV7目标检测自训练模型》

3.1 配置项修改

1,predefined_classes.txt

“BLUE”, “WHITE”, “REFEREE”

索引值:0,1,2

2,coco.yaml

设置 nc:3

设置 names:[‘BLUE’,‘WHITE’,‘REFEREE’]

3,yolov7.yaml

设置 ‘nc:3

3.2 标注说明

帧图像标记三种类别,尽量将所有出现的人都标记出来,包括裁判、蓝队、白队

四、Keras模型的工程应用

YoloV7的模型应用,参见《足球视频AI(三)——YOLOV7目标检测自训练模型》

4.1 定义接口

    public interface IClassific
    {
        bool UseClassic { get; set; }

        /// <summary>
        /// 加载模型
        /// </summary>
        void LoadModel();

        /// <summary>
        /// 预测
        /// </summary>
        /// <param name="inputs">多枚图像80x80的rgb</param>
        /// <returns>分类结果</returns>
        NDarray Predict(NDarray? inputs);
    }

4.2 应用模型

    public class ClassificWithOnnx : IClassific
    {
        private InferenceSession? session;

        public ClassificWithOnnx(bool useClassic)
        {
            UseClassic = useClassic;
            if (useClassic)
                LoadModel();
        }

        public bool UseClassic { get; set; }

        /// <summary>
        /// <inheritdoc/>
        /// </summary>
        public void LoadModel()
        {
            session = new InferenceSession(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Assets/model.onnx"));
        }


        /// <summary>
        /// <inheritdoc/>
        /// </summary>
        public NDarray Predict(NDarray? inputs)
        {
            var inputTensor = inputs?.ToDenseTensor();
            var input = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor<float>("input_11", inputTensor) };
            var outputs = session?.Run(input).ToList().Last().AsEnumerable<float>().ToArray();
            var outputarray = np.array<float>(outputs!);
            var arr = outputarray.reshape(inputs!.shape.Dimensions[0], 3);
            arr = np.argmax(arr, axis: 1);
            return arr;
        }
    }

其中推理的首个网络层名字"input_11"查看方法及静态方法定义,参见《AI机器学习(五)Keras h5转onnx C# ML 推理》

4.3 人员分类

依赖《足球视频AI(二)——球员与球的目标检测》,先检测到人员,将人员的Bound图像裁剪,传递给分类函数。

        [Fact]
        public void TestPlayerClassific()
        {
            Mat roi;
            NDarray? rois = null;
            NDarray? labels = null;
            List<YoloPrediction> lst;
            
            var detector = new DetectorYolov7();
            var classificor = new ClassificWithOnnx(true);

            using (var mat = LoadImages.Load("field_2.jpg"))
            {
                lst = detector.Detect(mat);
                lst.ForEach(prediction => {
                        var rect = prediction.Rectangle;
                        roi = new Mat(frame, GetBoundSize(rect,frame)).Clone();
                        roi = roi.Resize(new OpenCvSharp.Size(80, 80));
                        //添加待识别对象,供批量预测对象类型使用
                        var ndarray = roi.ToNDarray();
                        if (null == rois)
                            rois = ndarray;
                        else
                            rois = np.concatenate((rois, ndarray));
                       labels = classificor.Predict(rois);
                 }
            }
            Assert.True(labels?.item<int>(0)>=0);
        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/140643.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

剑指offer----C语言版----第九天

目录 1. 剪绳子 1.1 题目描述 1.2 基础知识 1.2.1 动态规划 1.2.2 贪婪算法 1.3 思路一&#xff1a;动态规划 1.4 思路二&#xff1a;贪婪算法 1.5 思路一的优化 1. 剪绳子 原题链接&#xff1a;剑指 Offer 14- I. 剪绳子 - 力扣&#xff08;LeetCode&#xff09;http…

无约束优化:Hessian-Free Optimization 拟牛顿类算法(BFGS,L-BFGS)

文章目录无约束优化&#xff1a;Hessian-Free Optimization 拟牛顿类算法&#xff08;BFGS&#xff0c;L-BFGS&#xff09;为什么要用拟牛顿算法割线方程严格凸且光滑函数的BFGS算法非凸但光滑函数的BFGS算法L-BFGS算法非凸非光滑函数的BFGS算法参考文献无约束优化&#xff1a;…

LInux僵尸进程的解决方法

文章目录僵尸进程是如何出现的&#xff1f;如何防止僵尸进程产生&#xff1f;使用wait函数使用waitpid函数阻塞等待非阻塞等待——轮询僵尸进程出现后如何解决&#xff1f;僵尸进程是如何出现的&#xff1f; 一个进程在退出后&#xff0c;操作系统会释放该进程对应的资源&…

网络舆情监测管理制度及处置机制,网络舆情监测服务项目实时方案?

舆情监测通常包括搜集、分析和报告舆论信息的过程。搜集信息的途径包括网络新闻、社交媒体、博客、论坛等&#xff0c;分析信息的方法包括自然语言处理、数据挖掘、模糊属性决策分析等。接下来TOOM舆情监测小编带您简单了解网络舆情监测管理制度及处置机制&#xff0c;网络舆情…

奈奎斯特采样定理(Nyquist)

采样定理在1928年由美国电信工程师H.奈奎斯特首先提出来的&#xff0c;因此称为奈奎斯特采样定理。1933年由苏联工程师科捷利尼科夫首次用公式严格地表述这一定理&#xff0c;因此在苏联文献中称为科捷利尼科夫采样定理。1948年信息论的创始人C.E.香农对这一定理加以明确地说明…

VirtualBox+Vagrant快速搭建linux虚拟环境

VirtualBoxVagrant快速搭建linux虚拟环境 1.下载安装VirtualBox 下载 Virtual Box 官网: https://www.virtualbox.org/ 2.BIOS 里修改设置开启虚拟化设备支持(f2, f10) 参考: https://jingyan.baidu.com/article/ab0b56305f2882c15afa7dda.html 3.安装 Virtual Box&#xff…

【自学Python】Windows Python交互式运行

Windows Python交互式运行 Windows Python交互式运行教程 安装好 Python 之后&#xff0c;Python 都会提供一个 Python 命令行工具&#xff0c;就叫 python。 python 命令行工具不仅能用于运行 Python 程序&#xff0c;也可作为一个交互式解释器&#xff0c;即开发者可以在该…

9种 分布式ID生成方式

一、为什么要用分布式ID&#xff1f; 在说分布式ID的具体实现之前&#xff0c;我们来简单分析一下为什么用分布式ID&#xff1f;分布式ID应该满足哪些特征&#xff1f; 1、什么是分布式ID&#xff1f; 拿MySQL数据库举个栗子&#xff1a; 在我们业务数据量不大的时候&#…

AcWing算法提高课:区间DP

两种实现方式 循环式 一般对于一维的DP问题可以应用。 for(len 1; len < n; len)for(l 1; l len-1 < n; l)r l len - 1;//枚举方案数记忆化搜索式 一般在二维DP中使用 循环也倒是可以&#xff0c;但是层数太多&#xff0c;所以使用记忆化进行实现。 常见策略 …

深入解读Netty 底层核心源码,全面分析Netty特新

前言 Netty 是一款基于 NIO&#xff08;非阻塞 I/O&#xff09;开发的网络框架&#xff0c;与传统 BIO 相比&#xff0c;它的并发性能得到了很大的提高&#xff0c;而且更加节省资源。Netty 不仅封装了 NIO 操作的很多细节&#xff1b;在设计上还基于灵活、可扩展的事件驱动模…

java学习day68(乐友商城)RabbitMQ及数据同步

今日目标&#xff1a; 了解常见的MQ产品 了解RabbitMQ的5种消息模型 会使用Spring AMQP 利用MQ实现搜索和静态页的数据同步 1.RabbitMQ 1.1.搜索与商品服务的问题 目前我们已经完成了商品详情和搜索系统的开发。我们思考一下&#xff0c;是否存在问题&#xff1f; 商品的…

Qt样式(qss)的几套配色方案

背景&#xff1a;之前写过有关qss的博客&#xff0c;记录了如何使用qt手册&#xff0c;以及在项目中如何使用qss的体验。经过实践&#xff0c;我归纳了自己需要的qss使用方法&#xff0c;使之尽量高效&#xff0c;容易维护。Qt样式&#xff08;qss&#xff09;手册小结&#xf…

工业数字孪生技术在钢铁企业中的应用展示

目前随着网络技术的发展&#xff0c;数字孪生技术已逐步应用于智慧工厂、智慧城市等领域。钢铁生产作为典型的工业流程制造场景&#xff0c;具备工艺复杂、物料交叉、生产节奏紧凑等特点。借助数字孪生技术仿真、虚实融合等能力&#xff0c;对钢铁生产过程的各个环节进行指导与…

SpringBoot+VUE前后端分离项目学习笔记 - 【14 SpringBoot和Vue实现用户登录】

前端代码 Login.vue 注意&#xff1a;el-form必须写 :model 否则无法使用表单校验功能 <el-form-item> 不能少 <template><div class"wrapper"><div style"margin: 200px auto; background-color: #fff; width: 350px; height: 300px; pa…

魔兽世界私服架设 服务器架设简易教程

今天早晨明杰终于把魔兽世界的私服搭建成功可以运行了。挺happy。记录一下搭建的全过程&#xff1a;1.先下载私服服务器端&#xff1a;从mangoscn.com下载大芒果ftp://www.mangoscn.com/TCCN-3.2.2-Trinity5749.exe从这个地址下载不需要注册&#xff0c;如果从mangoscn.com的网…

Python+Yolov5反光衣黄色马甲特征识别监测快速锁定目标人物体

程序示例精选 PythonYolov5反光衣识别 如需安装运行环境或远程调试&#xff0c;见文章底部微信名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 Yolov5比较Yolov4,Yolov3等其他识别框架&#xff0c;速度快&#xff0c;代码结构简单&#xff0c;识别效率高&#xff0…

计算机网络进阶 ---- MGRE ---- NHRP ---- 详解

一、MGRE&#xff08;多点GRE&#xff09;&#xff1a; 属于 NBMA 网络类型&#xff1b;在所有要连通的网络之间仅需要构建一个MA网段即可&#xff1b;且仅可以存在一个 固定的 IP地址&#xff0c;看作中心站点&#xff1b;其他分支站点可以是动态的 IP地址&#xff0c;节省成…

从recat源码角度看setState流程

setState setState() 将对组件 state 的更改排入队列批量推迟更新&#xff0c;并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件。其实setState实际上不是异步&#xff0c;只是代码执行顺序不同&#xff0c;有了异步的感觉。 使用方法 setState(stateChange | u…

助力生产质量检验,基于YOLOV5实现香烟质量缺陷检测

生产质量环境的检验始终是一个热门的应用场景&#xff0c;在之前一些项目和文章中我也做过一些相关的事情&#xff0c;比如PCB电路板相关的&#xff0c;如下&#xff1a;《助力质量生产&#xff0c;基于目标检测模型MobileNetV2-YOLOv3-Lite实现PCB电路板缺陷检测》本质的目的就…

含泪赔了近200万,我终于明白不是什么人都能干电商的……

文|螳螂观察 作者|图霖 又是一年年货节&#xff0c;围绕电商相关话题的讨论正在增多。 都说现在入行做电商十有九亏&#xff0c;但《螳螂观察》注意到一组数据&#xff1a;截至7月31日&#xff0c;过去一年入淘创业者的数量仍在增长&#xff0c;淘宝天猫净增了近120万商家&a…