訂閱
糾錯
加入自媒體

使用球員圖像姿勢的板球擊球分類

介紹

姿勢檢測是計算機視覺 (CV) 技術的子集,可預測人或物體的軌跡和位置。這是通過查看給定人或物體的姿勢和方向的組合來完成的。

目標

本文的目的是建立一個模型,該模型可以使用球員的姿勢對板球擊球進行分類。為此,將圖像輸入到模型中。它將檢測圖像中人的姿勢,然后使用檢測到的姿勢,我們將分類它屬于什么類型。

目錄

1. 安裝依賴項

2. 加載和預處理數據

3. 數據增強

4. 使用detectron2檢測姿勢

5. 使用球員的姿勢對板球擊球進行分類

6. 評估模型性能

安裝 Cricket Shot 分類的依賴項

!pip install pyyaml==5.1

# install detectron2:

!pip install detectron2==0.1.3 -f

    https://dl.fbaipublicfiles.com/detectron2/wheels/cu101/torch1.5/index.html

加載和預處理板球擊球分類的數據

我們將加載保存在驅動器上的數據集。因此,為此,我們將首先安裝驅動器,然后提取簡短的 zip 文件。

# mount drive

from google.colab import drive

drive.mount('drive/')

zip 文件包含不同類型鏡頭的圖像。接下來,我們獲取文件夾的名稱,它們是類別或不同類型的鏡頭。

# extract files

!unzip 'drive/My Drive/shot.zip'

接下來,我們使用 OS 庫的 list ERR 函數來執(zhí)行此操作。在這里,我們正在打印我們擁有的文件夾名稱,我們有四個文件夾,即 pull, cut, drive and sweep.

import os

# specify path

path='shot/'

# list down the folders

folders = os.listdir(path)

print(folders)

輸出:['pull', 'cut', 'drive', 'sweep']

接下來,我們正在讀取所有圖像并將它們存儲在一個名為 images 的列表中。我們還將標簽存儲在一個列表中,該列表是每個圖像的類。這個類存儲圖像的文件夾的名稱。我們將遍歷每個文件夾并逐個讀取圖像,并將它們附加到創(chuàng)建的列表中。

# for dealing with images

import cv2

# create lists

images  = []

labels  = []

# for each folder

for folder in folders:

   # list down image names

   names=os.listdir(path+folder)

   # for each image

   for name in names:

      # read an image

       img=cv2.imread(path+folder+'/'+name)

       # append image to list

       images.append(img)      

       # append folder name (type of shot) to list

       labels.append(folder)

讓我們使用 len 函數快速檢查圖像的數量。我們可以觀察到有 290 張圖像。

# number of images

len(images)

輸出:290

現在,我們正在可視化數據集中的一些圖像。所以對于每種類型的鏡頭。我們隨機繪制五張圖像。我們將使用matplotlib來可視化圖像。random 函數將用于隨機選擇圖像。

我們將創(chuàng)建一個子圖,其中四行代表四個不同的類,五列代表五個示例。接下來對于每個類,我們將隨機挑選五張圖像并使用 cv2.imread 函數讀取圖像。讀取圖像后,你可以將這些圖像轉換為 RGB 格式并可視化這些圖像。

# visualization library

import matplotlib.pyplot as plt

# for randomness

import random

# create subplots with 4 rows and 5 columns
fig, ax = plt.subplots(nrows=4, ncols=5, figsize=(15,15))

# randomly display 5 images for each shot for each folder

for i in range(len(folders)):

   # read image names

   names=os.listdir(path+folders[i])

   # randomly select 5 image names

   names= random.sample(names, 5)

   # for each image

   for j in range(len(names)):

     # read an image

     img = cv2.imread(path+ folders[i]+ '/' +names[j])

     # convert BGR to RGB

     img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

     # display image

     ax[i, j].imshow(img)

     # set folder name as title

     ax[i, j].set_title(folders[i])

     # Turn off axis

     ax[i, j].axis('off')

因此,你可以在這里看到我們從數據集中獲取的一些圖像示例,F在,因為我們在訓練集中的圖像數量較少。我們將使用數據增強技術來增加我們的訓練規(guī)模。

數據增強

為了增加我們的訓練規(guī)模,我們將水平翻轉圖像,這將有助于我們做兩件事,首先,玩家可以同時使用右手和左手,因此通過翻轉圖像。這將使我們的模型更加通用。它還將增加用于訓練的圖像數量。

在這里我們創(chuàng)建一個空列表來存儲數據集中每個圖像的增強圖像及其對應的標簽。

我們使用 cv2 的 flip 函數翻轉它,然后將其附加到列表中。

# image augmentation

aug_images=[]

aug_labels=[]

# for each image in training data

for idx in range(len(images)):

 # fetch an image and label

 img  = images[idx]

 label= labels[idx]

 # flip an image

 img_flip = cv2.flip(img, 1)

 # append augmented image to list

 aug_images.append(img_flip)

 # append label to list

 aug_labels.append(label)

接下來,我們將與原始圖像一起可視化一些增強圖像。

我們隨機挑選了五張圖片。此外,我們正在創(chuàng)建一個子圖來像以前一樣進行可視化。我們首先繪制實際圖像,然后繪制其增強版本。

在這里我們可以看到,使用數據增強來翻轉圖像,鏡頭的類型不會改變。即使我們水平旋轉圖像,pull類型的鏡頭仍屬于pull類。

# display actual and augmented image for sample images

# create indices

ind = range(len(aug_images))

# randomly sample indices

ind = random.sample(ind, 5)

# create subplots with 5 rows and 2 columns

fig, ax = plt.subplots(nrows=5, ncols=2, figsize=(15,15))

# for each row

for row in range(5):

 # for each column

 for col in range(2):    

   # first column for actual image

   if col==0:      

     # display actual image

     ax[row, col].imshow(images[ ind[row] ] )

     # set title

     ax[row, col].set_title('Actual')

     # Turn off axis

     ax[row, col].axis('off')

   # second column for augmented image

   else:

     # display augmented image      

     ax[row, col].imshow(aug_images[ ind[row] ] )

     # set title

     ax[row, col].set_title('Augmented')

     # Turn off axis

     ax[row, col].axis('off')

現在我們正在合并實際圖像和增強圖像并檢查圖像的數量。

# combine actual and augmented images & labels

images = images + aug_images

labels = labels + aug_labels

# number of images

len(images)

輸出:580

使用detectron2檢測姿勢

現在我們有 580 張圖像,包括用于訓練的實際圖像和增強圖像,F在我們的數據集已經準備好了。接下來,我們將使用detectron2 檢測所有這些圖像中玩家的姿勢。

我們將使用detectron2 中的預訓練模型來檢測這些姿勢。我們正在定義模型和一些庫,定義我們將使用的模型架構。我們還定義了使用預訓練模型的權重的路徑。

之后,我們將邊界框的閾值定義為 0.8。最后,我們正在定義我們的預測器。現在模型已經準備好了。

# import some common detectron2 utilities

# to obtain pretrained models

from detectron2 import model_zoo

# set up predictor

from detectron2.engine import DefaultPredictor

# set config

from detectron2.config import get_cfg

# define configure instance

cfg = get_cfg()

# get a model specified by relative path under Detectron2’s official configs/ directory.

cfg.merge_from_file(model_zoo.get_config_file
                           ("COCO-Keypoints/keypoint_rcnn_R_101_FPN_3x.yaml"))

# download pretrained model

cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url
                       ("COCO-Keypoints/keypoint_rcnn_R_101_FPN_3x.yaml")

# set threshold for this model

cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.8

# create predictor

predictor = DefaultPredictor(cfg)

讓我們可視化模型中的一些預測。在這里,我們隨機挑選五張圖像,然后對每張圖像進行預測,定義可視化器并在圖像上繪制預測。

# for drawing predictions on images

from detectron2.utils.visualizer import Visualizer

# to obtain metadata

from detectron2.data import MetadataCatalog

# to display an image

from google.colab.patches import cv2_imshow

# randomly select images

for img in random.sample(images,5):    

  # make predictions

   outputs = predictor(img)

   # use `Visualizer` to draw the predictions on the image.

   v = Visualizer(img[:, :, ::-1],

MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), scale=1)

   # draw prediction on image

   v = v.draw_instance_predictions(outputs["instances"].to("cpu"))

   # display image

   cv2_imshow(v.get_image()[:, :, ::-1])

這里是模型的預測。你可以看到我們有邊界框以及為每個玩家預測的關鍵點。你可以看到該模型甚至還預測了背景中的一些圖像。這些是模型的一些預測。

接下來,我們將定義一個函數,用于提取和檢測圖像的姿勢。因此,此函數將以圖像作為輸入,使用預訓練模型對圖像進行這些預測,然后將提取的關鍵點轉換為單個圖像的 numpy 數組。

也可以有多個對象。我們將選擇得分最高的對象并只保留那些關鍵點,最后我們將關鍵點轉換為一維數組。

因為我們希望在此之上建立一個神經網絡模型,并且神經網絡采用一維輸入。

所以在這里我們將其轉換為單一維度,現在我們將使用定義的函數,提取所有圖像的關鍵點,并將它們存儲在列表關鍵點中。

現在我們有了所有圖像的關鍵點。接下來,我們將構建一個神經網絡,將這些關鍵點分類為對應的鏡頭類型。

# define function that extracts the keypoints for an image

def extract_keypoints(img):  

 # make predictions

 outputs = predictor(img)

 # fetch keypoints

 keypoints = outputs['instances'].pred_keypoints

 # convert to numpy array

 kp = keypoints.cpu().numpy()

 # if keypoints detected

 if(len(keypoints)>0):

   # fetch keypoints of a person with maximum confidence score

   kp = kp[0]

   kp = np.delete(kp,2,1)

   # convert 2D array to 1D array

   kp = kp.flatten()

   # return keypoints

   return kp

# progress bar

from tqdm import tqdm

import numpy as np

# create list

keypoints   = []

# for every image

for i in tqdm(range(len(images))):

 # extract keypoints

 kp = extract_keypoints(images[i])

 # append keypoints

 keypoints.append(kp)

5. 使用球員姿勢對板球擊球進行分類

首先,我們將對關鍵點的值進行歸一化,這最終將加快訓練過程。

# for normalization

from sklearn.preprocessing import StandardScaler

# define normalizer

scaler= StandardScaler()

# normalize keypoints

keypoints = scaler.fit_transform(keypoints)

# convert to an array

keypoints = np.array(keypoints)

在這里我們對關鍵點的值進行了標準化。我們正在使用標簽編碼將當前為文本形式的目標轉換為數字。

# converting the target categories into numbers

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()

y=le.fit_transform(labels)

之后,我們使用訓練測試拆分功能將數據集拆分為訓練集和驗證集。所以我們將測試大小保持為 0.2,這意味著 80%的數據將用于訓練,20%將在驗證集中。

# for creating training and validation sets

from sklearn.model_selection import train_test_split

# split keypoints and labels in 80:20

x_tr, x_val, y_tr, y_val = train_test_split(keypoints, y, test_size=0.2, stratify=labels,
                                       random_state=120)

現在為了使用關鍵點和目標,我們必須將它們轉換為張量。因此,在這里我們將關鍵點和目標轉換為 python 張量,用于訓練和驗證集。

# converting the keypoints and target value to tensor
import torch

x_tr = torch.Tensor(x_tr)

x_val = torch.Tensor(x_val)

y_tr = torch.Tensor(y_tr)

y_tr = y_tr.type(torch.long)

y_val = torch.Tensor(y_val)

y_val = y_val.type(torch.long)

這是訓練的形狀,驗證集有 464 張用于訓練的圖像和 116 張用于驗證的圖像。

# shape of training and validation set

(x_tr.shape, y_tr.shape), (x_val.shape, y_val.shape)

現在我們將為我們的模型定義架構。在這里我們從 PyTorch 中導入一些對我們有幫助的函數。在這里,我們定義了一個簡單的神經網絡架構,其中只有一個具有 64 個神經元的隱藏層。

輸出層有四個神經元,因為我們有四個不同的類,輸出層的激活函數將返回概率。因此,我們有一個 softmax 激活函數。

# importing libraries for defining the architecture of model

from torch.autograd import Variable

from torch.optim import Adam

from torch.nn import Linear, ReLU, Sequential,

Softmax, CrossEntropyLoss

# defining the model architecture

model = Sequential(Linear(34, 64),
                  ReLU(),
                  Linear(64, 4),
                  Softmax()
                  )

接下來,我們將優(yōu)化器定義為 adam,將損失定義為交叉熵。這是一個多類分類問題,然后我們將模型轉移到 GPU。

# define optimizer and loss function

optimizer = Adam(model.parameters(), lr=0.01)

criterion = CrossEntropyLoss()

# checking if GPU is available

if torch.cuda.is_available():

   model = model.cuda()

   criterion = criterion.cuda()

接下來,我們將定義一個用于訓練模型的函數。這個函數會將 epoch 的數量作為輸入。首先,我們將損失初始化為零,然后使用 Pytorch 變量加載訓練和驗證集。

將我們的模型和驗證轉移到 GPU 之后,清除模型參數的梯度。接下來,我們從模型中獲取訓練集和驗證集的預測,并將它們分類為單獨的變量。

我們已經計算了訓練和驗證損失,最后,反向傳播梯度并更新參數。

此外,我們還在每 10 個 epoch 后打印驗證損失。

def train(epoch):

   model.train()

   tr_loss = 0

   # getting the training set

   x_train, y_train = Variable(x_tr), Variable(y_tr)

   # getting the validation set

   x_valid, y_valid = Variable(x_val), Variable(y_val)

   # converting the data into GPU format

   if torch.cuda.is_available():

       x_train = x_train.cuda()

       y_train = y_train.cuda()

       x_valid = x_valid.cuda()

       y_valid = y_valid.cuda()

  # clearing the Gradients of the model parameters

   optimizer.zero_grad()

   # prediction for training and validation set

   output_train = model(x_train)

   output_val = model(x_valid)

   # computing the training and validation loss

   loss_train = criterion(output_train, y_train)

   loss_val = criterion(output_val, y_valid)

   # computing the updated weights of all the model parameters

   loss_train.backward()

   optimizer.step()

   if epoch%10 == 0:

       # printing the validation loss

       print('Epoch : ',epoch+1, 't', 'loss :', loss_val.item())

現在我們已經定義了我們的函數。我們將使用此訓練功能并開始對我們的模型進行訓練。此外,我們正在訓練 400 個 epoch。你可以看到該模型每 10 個 epoch 打印一次損失。

最后,我們以 1.38 的損失開始,現在我們最終損失了 0.97。所以我們可以看到,隨著模型訓練的進行,模型的性能正在提高。

# defining the number of epochs

n_epochs = 100

# training the model

for epoch in range(n_epochs):

   train(epoch)

評估模型性能

讓我們評估模型性能,以便檢查模型的準確性。

從sklearn導入函數。我們得到了包括關鍵點和目標變量的驗證集。一旦獲得變量,首先將這些值傳輸到 GPU,我們將使用經過訓練的模型從模型中對驗證圖像進行預測。

現在我們正在使用 arg max 函數將預測概率轉換為相應的類。

# to check the model performance

from sklearn.metrics import accuracy_score

# get validation accuracy

x, y = Variable(x_val), Variable(y_val)

if torch.cuda.is_available():

 x_val = x.cuda()

 y_val = y.cuda()

pred = model(x_val)

final_pred = np.argmax(pred.cpu().data.numpy(), axis=1)

accuracy_score(y_val.cpu(), final_pred)

最后,我們計算了準確度得分,因此該模型的準確度為 0.79,約為 80%。

結論

為了提高準確性,你可以使用不同的超參數,例如增加模型中的隱藏層數、更改優(yōu)化器、更改激活函數、增加 epoch 數等等。這就是我們如何建立一個模型來使用球員的姿勢對鏡頭進行分類的教程。

       原文標題 : 使用球員圖像姿勢的板球擊球分類

聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯系舉報。

發(fā)表評論

0條評論,0人參與

請輸入評論內容...

請輸入評論/評論長度6~500個字

您提交的評論過于頻繁,請輸入驗證碼繼續(xù)

暫無評論

暫無評論

    掃碼關注公眾號
    OFweek人工智能網
    獲取更多精彩內容
    文章糾錯
    x
    *文字標題:
    *糾錯內容:
    聯系郵箱:
    *驗 證 碼:

    粵公網安備 44030502002758號