使用球員圖像姿勢(shì)的板球擊球分類
介紹
姿勢(shì)檢測(cè)是計(jì)算機(jī)視覺 (CV) 技術(shù)的子集,可預(yù)測(cè)人或物體的軌跡和位置。這是通過查看給定人或物體的姿勢(shì)和方向的組合來完成的。
目標(biāo)
本文的目的是建立一個(gè)模型,該模型可以使用球員的姿勢(shì)對(duì)板球擊球進(jìn)行分類。為此,將圖像輸入到模型中。它將檢測(cè)圖像中人的姿勢(shì),然后使用檢測(cè)到的姿勢(shì),我們將分類它屬于什么類型。
目錄
1. 安裝依賴項(xiàng)
2. 加載和預(yù)處理數(shù)據(jù)
3. 數(shù)據(jù)增強(qiáng)
4. 使用detectron2檢測(cè)姿勢(shì)
5. 使用球員的姿勢(shì)對(duì)板球擊球進(jìn)行分類
6. 評(píng)估模型性能
安裝 Cricket Shot 分類的依賴項(xiàng)
!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
加載和預(yù)處理板球擊球分類的數(shù)據(jù)
我們將加載保存在驅(qū)動(dòng)器上的數(shù)據(jù)集。因此,為此,我們將首先安裝驅(qū)動(dòng)器,然后提取簡(jiǎn)短的 zip 文件。
# mount drive
from google.colab import drive
drive.mount('drive/')
zip 文件包含不同類型鏡頭的圖像。接下來,我們獲取文件夾的名稱,它們是類別或不同類型的鏡頭。
# extract files
!unzip 'drive/My Drive/shot.zip'
接下來,我們使用 OS 庫(kù)的 list ERR 函數(shù)來執(zhí)行此操作。在這里,我們正在打印我們擁有的文件夾名稱,我們有四個(gè)文件夾,即 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']
接下來,我們正在讀取所有圖像并將它們存儲(chǔ)在一個(gè)名為 images 的列表中。我們還將標(biāo)簽存儲(chǔ)在一個(gè)列表中,該列表是每個(gè)圖像的類。這個(gè)類存儲(chǔ)圖像的文件夾的名稱。我們將遍歷每個(gè)文件夾并逐個(gè)讀取圖像,并將它們附加到創(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.a(chǎn)ppend(img)
# append folder name (type of shot) to list
labels.a(chǎn)ppend(folder)
讓我們使用 len 函數(shù)快速檢查圖像的數(shù)量。我們可以觀察到有 290 張圖像。
# number of images
len(images)
輸出:290
現(xiàn)在,我們正在可視化數(shù)據(jù)集中的一些圖像。所以對(duì)于每種類型的鏡頭。我們隨機(jī)繪制五張圖像。我們將使用matplotlib來可視化圖像。random 函數(shù)將用于隨機(jī)選擇圖像。
我們將創(chuàng)建一個(gè)子圖,其中四行代表四個(gè)不同的類,五列代表五個(gè)示例。接下來對(duì)于每個(gè)類,我們將隨機(jī)挑選五張圖像并使用 cv2.imread 函數(shù)讀取圖像。讀取圖像后,你可以將這些圖像轉(zhuǎn)換為 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].a(chǎn)xis('off')
因此,你可以在這里看到我們從數(shù)據(jù)集中獲取的一些圖像示例,F(xiàn)在,因?yàn)槲覀冊(cè)谟?xùn)練集中的圖像數(shù)量較少。我們將使用數(shù)據(jù)增強(qiáng)技術(shù)來增加我們的訓(xùn)練規(guī)模。
數(shù)據(jù)增強(qiáng)
為了增加我們的訓(xùn)練規(guī)模,我們將水平翻轉(zhuǎn)圖像,這將有助于我們做兩件事,首先,玩家可以同時(shí)使用右手和左手,因此通過翻轉(zhuǎn)圖像。這將使我們的模型更加通用。它還將增加用于訓(xùn)練的圖像數(shù)量。
在這里我們創(chuàng)建一個(gè)空列表來存儲(chǔ)數(shù)據(jù)集中每個(gè)圖像的增強(qiáng)圖像及其對(duì)應(yīng)的標(biāo)簽。
我們使用 cv2 的 flip 函數(shù)翻轉(zhuǎn)它,然后將其附加到列表中。
# 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.a(chǎn)ppend(img_flip)
# append label to list
aug_labels.a(chǎn)ppend(label)
接下來,我們將與原始圖像一起可視化一些增強(qiáng)圖像。
我們隨機(jī)挑選了五張圖片。此外,我們正在創(chuàng)建一個(gè)子圖來像以前一樣進(jìn)行可視化。我們首先繪制實(shí)際圖像,然后繪制其增強(qiáng)版本。
在這里我們可以看到,使用數(shù)據(jù)增強(qiáng)來翻轉(zhuǎn)圖像,鏡頭的類型不會(huì)改變。即使我們水平旋轉(zhuǎn)圖像,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].a(chǎn)xis('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].a(chǎn)xis('off')
現(xiàn)在我們正在合并實(shí)際圖像和增強(qiáng)圖像并檢查圖像的數(shù)量。
# combine actual and augmented images & labels
images = images + aug_images
labels = labels + aug_labels
# number of images
len(images)
輸出:580
使用detectron2檢測(cè)姿勢(shì)
現(xiàn)在我們有 580 張圖像,包括用于訓(xùn)練的實(shí)際圖像和增強(qiáng)圖像,F(xiàn)在我們的數(shù)據(jù)集已經(jīng)準(zhǔn)備好了。接下來,我們將使用detectron2 檢測(cè)所有這些圖像中玩家的姿勢(shì)。
我們將使用detectron2 中的預(yù)訓(xùn)練模型來檢測(cè)這些姿勢(shì)。我們正在定義模型和一些庫(kù),定義我們將使用的模型架構(gòu)。我們還定義了使用預(yù)訓(xùn)練模型的權(quán)重的路徑。
之后,我們將邊界框的閾值定義為 0.8。最后,我們正在定義我們的預(yù)測(cè)器。現(xiàn)在模型已經(jīng)準(zhǔn)備好了。
# 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)
讓我們可視化模型中的一些預(yù)測(cè)。在這里,我們隨機(jī)挑選五張圖像,然后對(duì)每張圖像進(jìn)行預(yù)測(cè),定義可視化器并在圖像上繪制預(yù)測(cè)。
# 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])
這里是模型的預(yù)測(cè)。你可以看到我們有邊界框以及為每個(gè)玩家預(yù)測(cè)的關(guān)鍵點(diǎn)。你可以看到該模型甚至還預(yù)測(cè)了背景中的一些圖像。這些是模型的一些預(yù)測(cè)。
接下來,我們將定義一個(gè)函數(shù),用于提取和檢測(cè)圖像的姿勢(shì)。因此,此函數(shù)將以圖像作為輸入,使用預(yù)訓(xùn)練模型對(duì)圖像進(jìn)行這些預(yù)測(cè),然后將提取的關(guān)鍵點(diǎn)轉(zhuǎn)換為單個(gè)圖像的 numpy 數(shù)組。
也可以有多個(gè)對(duì)象。我們將選擇得分最高的對(duì)象并只保留那些關(guān)鍵點(diǎn),最后我們將關(guān)鍵點(diǎn)轉(zhuǎn)換為一維數(shù)組。
因?yàn)槲覀兿M诖酥辖⒁粋(gè)神經(jīng)網(wǎng)絡(luò)模型,并且神經(jīng)網(wǎng)絡(luò)采用一維輸入。
所以在這里我們將其轉(zhuǎn)換為單一維度,現(xiàn)在我們將使用定義的函數(shù),提取所有圖像的關(guān)鍵點(diǎn),并將它們存儲(chǔ)在列表關(guān)鍵點(diǎn)中。
現(xiàn)在我們有了所有圖像的關(guān)鍵點(diǎn)。接下來,我們將構(gòu)建一個(gè)神經(jīng)網(wǎng)絡(luò),將這些關(guān)鍵點(diǎn)分類為對(duì)應(yīng)的鏡頭類型。
# 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.a(chǎn)ppend(kp)
5. 使用球員姿勢(shì)對(duì)板球擊球進(jìn)行分類
首先,我們將對(duì)關(guān)鍵點(diǎn)的值進(jìn)行歸一化,這最終將加快訓(xùn)練過程。
# for normalization
from sklearn.preprocessing import StandardScaler
# define normalizer
scaler= StandardScaler()
# normalize keypoints
keypoints = scaler.fit_transform(keypoints)
# convert to an array
keypoints = np.a(chǎn)rray(keypoints)
在這里我們對(duì)關(guān)鍵點(diǎn)的值進(jìn)行了標(biāo)準(zhǔn)化。我們正在使用標(biāo)簽編碼將當(dāng)前為文本形式的目標(biāo)轉(zhuǎn)換為數(shù)字。
# converting the target categories into numbers
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y=le.fit_transform(labels)
之后,我們使用訓(xùn)練測(cè)試拆分功能將數(shù)據(jù)集拆分為訓(xùn)練集和驗(yàn)證集。所以我們將測(cè)試大小保持為 0.2,這意味著 80%的數(shù)據(jù)將用于訓(xùn)練,20%將在驗(yàn)證集中。
# 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)
現(xiàn)在為了使用關(guān)鍵點(diǎn)和目標(biāo),我們必須將它們轉(zhuǎn)換為張量。因此,在這里我們將關(guān)鍵點(diǎn)和目標(biāo)轉(zhuǎn)換為 python 張量,用于訓(xùn)練和驗(yàn)證集。
# 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)
這是訓(xùn)練的形狀,驗(yàn)證集有 464 張用于訓(xùn)練的圖像和 116 張用于驗(yàn)證的圖像。
# shape of training and validation set
(x_tr.shape, y_tr.shape), (x_val.shape, y_val.shape)
現(xiàn)在我們將為我們的模型定義架構(gòu)。在這里我們從 PyTorch 中導(dǎo)入一些對(duì)我們有幫助的函數(shù)。在這里,我們定義了一個(gè)簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)架構(gòu),其中只有一個(gè)具有 64 個(gè)神經(jīng)元的隱藏層。
輸出層有四個(gè)神經(jīng)元,因?yàn)槲覀冇兴膫(gè)不同的類,輸出層的激活函數(shù)將返回概率。因此,我們有一個(gè) softmax 激活函數(shù)。
# importing libraries for defining the architecture of model
from torch.a(chǎn)utograd 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,將損失定義為交叉熵。這是一個(gè)多類分類問題,然后我們將模型轉(zhuǎn)移到 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()
接下來,我們將定義一個(gè)用于訓(xùn)練模型的函數(shù)。這個(gè)函數(shù)會(huì)將 epoch 的數(shù)量作為輸入。首先,我們將損失初始化為零,然后使用 Pytorch 變量加載訓(xùn)練和驗(yàn)證集。
將我們的模型和驗(yàn)證轉(zhuǎn)移到 GPU 之后,清除模型參數(shù)的梯度。接下來,我們從模型中獲取訓(xùn)練集和驗(yàn)證集的預(yù)測(cè),并將它們分類為單獨(dú)的變量。
我們已經(jīng)計(jì)算了訓(xùn)練和驗(yàn)證損失,最后,反向傳播梯度并更新參數(shù)。
此外,我們還在每 10 個(gè) epoch 后打印驗(yàn)證損失。
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())
現(xiàn)在我們已經(jīng)定義了我們的函數(shù)。我們將使用此訓(xùn)練功能并開始對(duì)我們的模型進(jìn)行訓(xùn)練。此外,我們正在訓(xùn)練 400 個(gè) epoch。你可以看到該模型每 10 個(gè) epoch 打印一次損失。
最后,我們以 1.38 的損失開始,現(xiàn)在我們最終損失了 0.97。所以我們可以看到,隨著模型訓(xùn)練的進(jìn)行,模型的性能正在提高。
# defining the number of epochs
n_epochs = 100
# training the model
for epoch in range(n_epochs):
train(epoch)
評(píng)估模型性能
讓我們?cè)u(píng)估模型性能,以便檢查模型的準(zhǔn)確性。
從sklearn導(dǎo)入函數(shù)。我們得到了包括關(guān)鍵點(diǎn)和目標(biāo)變量的驗(yàn)證集。一旦獲得變量,首先將這些值傳輸?shù)?GPU,我們將使用經(jīng)過訓(xùn)練的模型從模型中對(duì)驗(yàn)證圖像進(jìn)行預(yù)測(cè)。
現(xiàn)在我們正在使用 arg max 函數(shù)將預(yù)測(cè)概率轉(zhuǎn)換為相應(yīng)的類。
# 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.a(chǎn)rgmax(pred.cpu().data.numpy(), axis=1)
accuracy_score(y_val.cpu(), final_pred)
最后,我們計(jì)算了準(zhǔn)確度得分,因此該模型的準(zhǔn)確度為 0.79,約為 80%。
結(jié)論
為了提高準(zhǔn)確性,你可以使用不同的超參數(shù),例如增加模型中的隱藏層數(shù)、更改優(yōu)化器、更改激活函數(shù)、增加 epoch 數(shù)等等。這就是我們?nèi)绾谓⒁粋(gè)模型來使用球員的姿勢(shì)對(duì)鏡頭進(jìn)行分類的教程。
原文標(biāo)題 : 使用球員圖像姿勢(shì)的板球擊球分類

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
3月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
4月30日立即下載>> 【村田汽車】汽車E/E架構(gòu)革新中,新智能座艙挑戰(zhàn)的解決方案
-
5月15-17日立即預(yù)約>> 【線下巡回】2025年STM32峰會(huì)
-
即日-5.15立即報(bào)名>>> 【在線會(huì)議】安森美Hyperlux™ ID系列引領(lǐng)iToF技術(shù)革新
-
5月15日立即下載>> 【白皮書】精確和高效地表征3000V/20A功率器件應(yīng)用指南
-
5月16日立即參評(píng) >> 【評(píng)選啟動(dòng)】維科杯·OFweek 2025(第十屆)人工智能行業(yè)年度評(píng)選
推薦專題
- 1 UALink規(guī)范發(fā)布:挑戰(zhàn)英偉達(dá)AI統(tǒng)治的開始
- 2 北電數(shù)智主辦酒仙橋論壇,探索AI產(chǎn)業(yè)發(fā)展新路徑
- 3 降薪、加班、裁員三重暴擊,“AI四小龍”已折戟兩家
- 4 “AI寒武紀(jì)”爆發(fā)至今,五類新物種登上歷史舞臺(tái)
- 5 國(guó)產(chǎn)智駕迎戰(zhàn)特斯拉FSD,AI含量差幾何?
- 6 光計(jì)算迎來商業(yè)化突破,但落地仍需時(shí)間
- 7 東陽(yáng)光:2024年扭虧、一季度凈利大增,液冷疊加具身智能打開成長(zhǎng)空間
- 8 地平線自動(dòng)駕駛方案解讀
- 9 封殺AI“照騙”,“淘寶們”終于不忍了?
- 10 優(yōu)必選:營(yíng)收大增主靠小件,虧損繼續(xù)又逢關(guān)稅,能否乘機(jī)器人東風(fēng)翻身?