ST-GCN 實現(xiàn)人體姿態(tài)行為分類
引用
人體行為識別是計算機視覺及機器學習方面的熱門研究領域。它在對視頻中的人類行為進行運動分析、行為識別乃至延伸至人機交互領域都有著非常廣泛的應用。研究初期,人體行為識別主要是以基于靜態(tài)圖像為研究對象。通過提取靜態(tài)圖像中的人體動作特征并對動作進行分類。然而僅基于靜態(tài)圖像來進行識別人體行為的局限性在于人體行為是連續(xù)、動態(tài)的,單憑一張靜態(tài)圖像無法進行判斷識別。而基于視頻為研究對象,可以將視頻看作連續(xù)靜態(tài)圖像的時間序列。近兩年,很多基于視頻為對象的人體行為識別取得了不錯的成果,例如,Gao等人以多視角的視頻為基礎開發(fā)出了一種自適應融合和類別級詞典學習模型。
在通常情況下,人體行為識別有著例如外觀、光流、身體骨骼和深度等多種模態(tài),人們可以通過這些模態(tài)建模并傳達重要信息進而實現(xiàn)人體行為識別。近幾年,比較熱門的深度領域有著很多的成果,Kamel等人利用使用卷積神經(jīng)網(wǎng)絡從深度圖和姿勢數(shù)據(jù)中進行人體行為識別。Ji等人利用深度圖來將骨骼信息嵌入從而達到對人體進行分區(qū)的目的,以及Zhao等人提出了一種貝葉斯分層動態(tài)模型用于人類動作識別也取得了不錯的效果。而在這些模態(tài)當中,人類身體骨骼通常能與其他模態(tài)相輔相成并傳達重要信息。同時也因為骨骼信息的清晰直觀且不易受到人體外觀等其他因素的影響,具有良好的魯棒性。
基于骨架的人體行為識別方法因?qū)碗s場景具有較強的魯棒性,因此近些年涌現(xiàn)很多基于骨架的動作識別方法。一般分為兩種方法:
(1)基于人工特征選擇的方法,通過人工設定的特性來捕捉關節(jié)運動動態(tài)。例如關節(jié)的相對位置、關節(jié)軌跡的協(xié)方差矩陣或是身體部分之間的平移旋轉(zhuǎn)等特性。
(2)深度學習方法,基于深度學習進行骨架建模,端到端的動作識別模型通過使用遞歸神經(jīng)網(wǎng)絡和臨時CNNs來學習。ST-GCN不同于這些方法,雖然強調(diào)了人體關節(jié)建模的重要性,但這些部分一般使用領域知識明確分配指定。ST-GCN將GCN應用于基于骨架的人體行為識別系統(tǒng)中,在此基礎上加入了對識別人體行為非常重要的關節(jié)之間的空間關系這一因素,以人體關節(jié)為節(jié)點,同時連接關節(jié)之間的自然聯(lián)系和相同關節(jié)的跨連續(xù)時間聯(lián)系,然后以此為基礎構造多個時空圖卷積層,沿時空維度進行集成信息。
故本項目通過搭建ST-GCN實現(xiàn)對視頻時空流進行姿態(tài)估計和行為分類。最終可實現(xiàn)效果如下:
1、ST-GCN 介紹
ST-GCN是香港中文大學提出一種時空圖卷積網(wǎng)絡,可以用它進行人類行為識別。這種算法基于人類關節(jié)位置的時間序列表示而對動態(tài)骨骼建模,并將圖卷積擴展為時空圖卷積網(wǎng)絡而捕捉這種時空的變化關系。
1.1 模型通道
基于骨架的數(shù)據(jù)可以從動作捕捉設備中獲得,也可以從視頻中獲得姿態(tài)估計算法。通常數(shù)據(jù)是一個坐標系序列,每個坐標系都有一組關節(jié)坐標。ST-GCN就是構建一個以關節(jié)為圖節(jié)點,以人體結構和時間為圖邊的自然連接為圖節(jié)點的時空圖。ST-GCN的輸入是圖節(jié)點上的關節(jié)坐標向量。這可以看作是對基于圖像的cnn的模擬,其中輸入是由駐留在2D圖像網(wǎng)格上的像素強度向量構成的。對輸入數(shù)據(jù)進行多層次的時空圖卷積運算,在圖上生成更高層次的特征圖。然后它將被標準的SoftMax分類器分類到相應的動作類別。
1.2 骨骼圖結構
骨骼序列通常由每一幀中每個人體關節(jié)的2D或3D坐標表示。使用卷積進行骨骼動作識別,將所有關節(jié)的坐標向量連接起來,形成每幀的單一特征向量。
1.3 時空模型
針對空間時間建模。在構建了空間圖之后,需要在骨骼序列中建模時空動態(tài)。在構建圖的時候,圖的時間方面是通過在連續(xù)的框架中連接相同的關節(jié)來構建的。從而能夠定義一個非常簡單的策略,將空間圖CNN擴展到空間時域。
2、模型實驗
2.1 環(huán)境搭建
1、首先下載好完整無誤配置好的代碼(包括模型等等,見文末)。
2、搭建最新版的openpose環(huán)境,并使用cmake編譯。
3、配置好python的cuda環(huán)境,以及opencv等基礎環(huán)境。
4、使用命令
“python main.py demo --openpose E:/cmake/environment/x64/Release --video 2.mp4”進行測試生成結果。
其中“E:/cmake/environment/x64/Release”需要改成自己的openpose環(huán)境。
2.2 主函數(shù)調(diào)用
其中主函數(shù)通過使用processors管理的設定好的分類識別、輸入輸出管理等程序內(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()
2.3 模型網(wǎng)絡
通過調(diào)用空間-時間圖卷積網(wǎng)絡建立這個網(wǎng)絡模型。其中參數(shù)in_channels (int)為輸入數(shù)據(jù)中的通道數(shù);
num_class (int)表示用于分類任務的類的數(shù)量;
graph_args (dict)表示構建圖的參數(shù);
edge_importance_weighting (bool)表示如果“True”,添加一個可學習的對圖的邊進行重要性加權。代碼如下:
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), ))
2.4 ST-GCN網(wǎng)絡建立
建立ST-GCN網(wǎng)絡模型,其中in_channels (int)表示輸入序列數(shù)據(jù)中的通道數(shù);
out_channels (int)表示卷積產(chǎn)生的通道數(shù);
kernel_size (tuple)為時態(tài)卷積核和圖卷積核的大??;
stride (int,可選)為時間卷積的步幅。默認值:1;
dropout (int,可選)為最終輸出的輟學率。默認值:0;
residual (bool,可選)表示如果”True “,應用殘留機制。默認值:“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”即可直接運行:
完整代碼:
鏈接:
https://pan.baidu.com/s/1Ht7Mr6hJMt5oUKu6ue05fw
提取碼:0nqh
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權請聯(lián)系工作人員刪除。