博客專欄

EEPW首頁 > 博客 > ST-GCN 實現(xiàn)人體姿態(tài)行為分類

ST-GCN 實現(xiàn)人體姿態(tài)行為分類

發(fā)布人:AI科技大本營 時間:2021-10-18 來源:工程師 發(fā)布文章

引用

人體行為識別是計算機視覺及機器學(xué)習(xí)方面的熱門研究領(lǐng)域。它在對視頻中的人類行為進行運動分析、行為識別乃至延伸至人機交互領(lǐng)域都有著非常廣泛的應(yīng)用。研究初期,人體行為識別主要是以基于靜態(tài)圖像為研究對象。通過提取靜態(tài)圖像中的人體動作特征并對動作進行分類。然而僅基于靜態(tài)圖像來進行識別人體行為的局限性在于人體行為是連續(xù)、動態(tài)的,單憑一張靜態(tài)圖像無法進行判斷識別。而基于視頻為研究對象,可以將視頻看作連續(xù)靜態(tài)圖像的時間序列。近兩年,很多基于視頻為對象的人體行為識別取得了不錯的成果,例如,Gao等人以多視角的視頻為基礎(chǔ)開發(fā)出了一種自適應(yīng)融合和類別級詞典學(xué)習(xí)模型。

在通常情況下,人體行為識別有著例如外觀、光流、身體骨骼和深度等多種模態(tài),人們可以通過這些模態(tài)建模并傳達重要信息進而實現(xiàn)人體行為識別。近幾年,比較熱門的深度領(lǐng)域有著很多的成果,Kamel等人利用使用卷積神經(jīng)網(wǎng)絡(luò)從深度圖和姿勢數(shù)據(jù)中進行人體行為識別。Ji等人利用深度圖來將骨骼信息嵌入從而達到對人體進行分區(qū)的目的,以及Zhao等人提出了一種貝葉斯分層動態(tài)模型用于人類動作識別也取得了不錯的效果。而在這些模態(tài)當(dāng)中,人類身體骨骼通常能與其他模態(tài)相輔相成并傳達重要信息。同時也因為骨骼信息的清晰直觀且不易受到人體外觀等其他因素的影響,具有良好的魯棒性。

基于骨架的人體行為識別方法因?qū)?fù)雜場景具有較強的魯棒性,因此近些年涌現(xiàn)很多基于骨架的動作識別方法。一般分為兩種方法:

(1)基于人工特征選擇的方法,通過人工設(shè)定的特性來捕捉關(guān)節(jié)運動動態(tài)。例如關(guān)節(jié)的相對位置、關(guān)節(jié)軌跡的協(xié)方差矩陣或是身體部分之間的平移旋轉(zhuǎn)等特性。

(2)深度學(xué)習(xí)方法,基于深度學(xué)習(xí)進行骨架建模,端到端的動作識別模型通過使用遞歸神經(jīng)網(wǎng)絡(luò)和臨時CNNs來學(xué)習(xí)。ST-GCN不同于這些方法,雖然強調(diào)了人體關(guān)節(jié)建模的重要性,但這些部分一般使用領(lǐng)域知識明確分配指定。ST-GCN將GCN應(yīng)用于基于骨架的人體行為識別系統(tǒng)中,在此基礎(chǔ)上加入了對識別人體行為非常重要的關(guān)節(jié)之間的空間關(guān)系這一因素,以人體關(guān)節(jié)為節(jié)點,同時連接關(guān)節(jié)之間的自然聯(lián)系和相同關(guān)節(jié)的跨連續(xù)時間聯(lián)系,然后以此為基礎(chǔ)構(gòu)造多個時空圖卷積層,沿時空維度進行集成信息。

故本項目通過搭建ST-GCN實現(xiàn)對視頻時空流進行姿態(tài)估計和行為分類。最終可實現(xiàn)效果如下:

1.png

1、ST-GCN 介紹

ST-GCN是香港中文大學(xué)提出一種時空圖卷積網(wǎng)絡(luò),可以用它進行人類行為識別。這種算法基于人類關(guān)節(jié)位置的時間序列表示而對動態(tài)骨骼建模,并將圖卷積擴展為時空圖卷積網(wǎng)絡(luò)而捕捉這種時空的變化關(guān)系。


1.1 模型通道

基于骨架的數(shù)據(jù)可以從動作捕捉設(shè)備中獲得,也可以從視頻中獲得姿態(tài)估計算法。通常數(shù)據(jù)是一個坐標(biāo)系序列,每個坐標(biāo)系都有一組關(guān)節(jié)坐標(biāo)。ST-GCN就是構(gòu)建一個以關(guān)節(jié)為圖節(jié)點,以人體結(jié)構(gòu)和時間為圖邊的自然連接為圖節(jié)點的時空圖。ST-GCN的輸入是圖節(jié)點上的關(guān)節(jié)坐標(biāo)向量。這可以看作是對基于圖像的cnn的模擬,其中輸入是由駐留在2D圖像網(wǎng)格上的像素強度向量構(gòu)成的。對輸入數(shù)據(jù)進行多層次的時空圖卷積運算,在圖上生成更高層次的特征圖。然后它將被標(biāo)準(zhǔn)的SoftMax分類器分類到相應(yīng)的動作類別。

2.png

1.2 骨骼圖結(jié)構(gòu)

骨骼序列通常由每一幀中每個人體關(guān)節(jié)的2D或3D坐標(biāo)表示。使用卷積進行骨骼動作識別,將所有關(guān)節(jié)的坐標(biāo)向量連接起來,形成每幀的單一特征向量。

3.png

1.3 時空模型

針對空間時間建模。在構(gòu)建了空間圖之后,需要在骨骼序列中建模時空動態(tài)。在構(gòu)建圖的時候,圖的時間方面是通過在連續(xù)的框架中連接相同的關(guān)節(jié)來構(gòu)建的。從而能夠定義一個非常簡單的策略,將空間圖CNN擴展到空間時域。

2、模型實驗

2.1 環(huán)境搭建

1、首先下載好完整無誤配置好的代碼(包括模型等等,見文末)。

2、搭建最新版的openpose環(huán)境,并使用cmake編譯。

4.png

3、配置好python的cuda環(huán)境,以及opencv等基礎(chǔ)環(huán)境。

4、使用命令

“python main.py demo --openpose E:/cmake/environment/x64/Release --video 2.mp4”進行測試生成結(jié)果。

其中“E:/cmake/environment/x64/Release”需要改成自己的openpose環(huán)境。


2.2 主函數(shù)調(diào)用

其中主函數(shù)通過使用processors管理的設(shè)定好的分類識別、輸入輸出管理等程序內(nèi)部函數(shù)進行整個程序的布置。

代碼如下:

import argparse
import sys
import torchlight
from torchlight import import_class
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Processor collection')
    processors = dict()
    processors['recognition'] = import_class('processor.recognition.REC_Processor')
    processors['demo'] = import_class('processor.demo.Demo')
    subparsers = parser.add_subparsers(dest='processor')
    for k, p in processors.items():
        subparsers.add_parser(k, parents=[p.get_parser()])
    arg = parser.parse_args()
    Processor = processors[arg.processor]
    p = Processor(sys.argv[2:])
    p.start()

5.png

2.3 模型網(wǎng)絡(luò)

通過調(diào)用空間-時間圖卷積網(wǎng)絡(luò)建立這個網(wǎng)絡(luò)模型。其中參數(shù)in_channels (int)為輸入數(shù)據(jù)中的通道數(shù);

num_class (int)表示用于分類任務(wù)的類的數(shù)量;

graph_args (dict)表示構(gòu)建圖的參數(shù);

edge_importance_weighting (bool)表示如果“True”,添加一個可學(xué)習(xí)的對圖的邊進行重要性加權(quán)。代碼如下:

def __init__(self, in_channels, num_class, graph_args,
             edge_importance_weighting, **kwargs):
    super().__init__()
    self.graph = Graph(**graph_args)
    A = torch.tensor(self.graph.A, dtype=torch.float32, requires_grad=False)
    self.register_buffer('A', A)
    spatial_kernel_size = A.size(0)
    temporal_kernel_size = 9
    kernel_size = (temporal_kernel_size, spatial_kernel_size)
    self.data_bn = nn.BatchNorm1d(in_channels * A.size(1))
    kwargs0 = {k: v for k, v in kwargs.items() if k != 'dropout'}
    self.st_gcn_networks = nn.ModuleList((
        st_gcn(in_channels, 64, kernel_size, 1, residual=False, **kwargs0),
        st_gcn(64, 64, kernel_size, 1, **kwargs),
        st_gcn(64, 64, kernel_size, 1, **kwargs),
        st_gcn(64, 64, kernel_size, 1, **kwargs),
        st_gcn(64, 128, kernel_size, 2, **kwargs),
        st_gcn(128, 128, kernel_size, 1, **kwargs),
        st_gcn(128, 128, kernel_size, 1, **kwargs),
        st_gcn(128, 256, kernel_size, 2, **kwargs),
        st_gcn(256, 256, kernel_size, 1, **kwargs),
        st_gcn(256, 256, kernel_size, 1, **kwargs),
    ))

6.png

2.4 ST-GCN網(wǎng)絡(luò)建立

建立ST-GCN網(wǎng)絡(luò)模型,其中in_channels (int)表示輸入序列數(shù)據(jù)中的通道數(shù);

out_channels (int)表示卷積產(chǎn)生的通道數(shù);

kernel_size (tuple)為時態(tài)卷積核和圖卷積核的大?。?/p>

stride (int,可選)為時間卷積的步幅。默認(rèn)值:1;

dropout (int,可選)為最終輸出的輟學(xué)率。默認(rèn)值:0;

residual (bool,可選)表示如果”True “,應(yīng)用殘留機制。默認(rèn)值:“True”。

代碼如下:

   

def __init__(self,
                 in_channels,
                 out_channels,
                 kernel_size,
                 stride=1,
                 dropout=0,
                 residual=True):
        super().__init__()
        assert len(kernel_size) == 2
        assert kernel_size[0] % 2 == 1
        padding = ((kernel_size[0] - 1) // 2, 0)
        self.gcn = ConvTemporalGraphical(in_channels, out_channels,
                                         kernel_size[1])
        self.tcn = nn.Sequential(
            nn.BatchNorm2d(out_channels),
            nn.ReLU(inplace=True),
            nn.Conv2d(
                out_channels,
                out_channels,
                (kernel_size[0], 1),
                (stride, 1),
                padding,
            ),
            nn.BatchNorm2d(out_channels),
            nn.Dropout(dropout, inplace=True),
        )
        if not residual:
            self.residual = lambda x: 0
        elif (in_channels == out_channels) and (stride == 1):
            self.residual = lambda x: x

運行過程如下可見,在這里通過雙擊“test.bat”即可直接運行:

7.png8.png

完整代碼:

鏈接:

https://pan.baidu.com/s/1Ht7Mr6hJMt5oUKu6ue05fw

提取碼:0nqh

*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。



關(guān)鍵詞: AI

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉