行為識別
行為檢測是一個廣泛的研究領域,其應用包括安防監(jiān)控、健康醫(yī)療、娛樂等。
課程大綱
導論
圖卷積在行為識別中的應用:論文研讀,代碼解讀,實驗
Topdown關鍵點檢測中的hrnet:論文研讀,代碼解讀,實驗
行為識別的其它算法
深度學習中的重要組件:優(yōu)化器,學習率策略
導論
主要算法簡述
任務簡述:
識別人體行為 action recognition
行為分類(classification),行為定位(localization),行為檢測(detection)
識別人體行為(action recognition)是指從視頻數(shù)據(jù)中自動識別出人體的行為活動。行為識別可以分為三個層次:行為分類(classification)、行為定位(localization)和行為檢測(detection)。
-
行為分類(classification)
行為分類是指將整個視頻序列劃分為不同的行為類別,例如走路、跑步、開車等。這是行為識別中最基本的任務,也是最常見的任務。在行為分類中,通常會使用深度學習模型(如卷積神經(jīng)網(wǎng)絡、循環(huán)神經(jīng)網(wǎng)絡等)對視頻序列進行建模,并使用softmax分類器對各個行為類別進行分類。行為分類的難點在于解決類內(nèi)差異和類間相似性的問題,以及在不同場景和光照條件下的數(shù)據(jù)變化問題。 -
行為定位(localization)
行為定位是指在視頻序列中定位出某個行為的發(fā)生時間段,例如在一個長時間的視頻中,定位出某個人走路的具體時間段。行為定位比行為分類更具挑戰(zhàn)性,因為它需要確定行為的開始和結束時間,而且同一個行為在不同的時間段里可能會有不同的表現(xiàn)。在行為定位中,通常會使用時間窗口的方法對視頻序列進行分割,然后對每個時間窗口進行行為分類,最后通過時間對齊的方法確定行為的發(fā)生時間段。 -
行為檢測(detection)
行為檢測是指在視頻序列中檢測出某個特定行為的出現(xiàn),例如檢測出某個人是否在走路。行為檢測通常需要使用目標檢測等技術來定位出人體的位置,并使用行為分類技術對每個人體位置處的行為進行分類。行為檢測的難點在于解決多人行為的檢測問題,以及在復雜背景下的行為檢測問題。
需要注意的是,行為識別面臨許多挑戰(zhàn),例如數(shù)據(jù)量不足、數(shù)據(jù)噪聲、類內(nèi)差異和類間相似性等問題。為了提高行為識別的準確性,通常需要使用多種技術和模型進行結合,例如使用多種傳感器數(shù)據(jù)、多種特征提取方法和多種深度學習模型進行融合。
數(shù)據(jù)模態(tài):
外觀appearance
深度depth
光流optical-flow
骨骼graph
時間維度t
遍歷維度h,w,t
數(shù)據(jù)模態(tài)(data modality)指的是用于行為識別的數(shù)據(jù)類型,常用的數(shù)據(jù)模態(tài)包括外觀、深度、光流和骨骼等。時間維度(time dimension)指的是視頻數(shù)據(jù)中的時間軸,遍歷維度(spatial dimensions)指的是視頻數(shù)據(jù)中的圖像尺寸,通常為高(height)和寬(width)。
-
外觀(appearance)
外觀模態(tài)是指從視頻中提取的圖像數(shù)據(jù),通常使用深度卷積神經(jīng)網(wǎng)絡(Convolutional Neural Networks,CNN)對圖像進行特征提取,并使用分類器對行為進行分類。外觀模態(tài)可以通過使用不同的圖像預處理方法來增加數(shù)據(jù)的多樣性和魯棒性,例如使用數(shù)據(jù)增強和遷移學習等方法。 -
深度(depth)
深度模態(tài)是指從深度相機或其他深度傳感器中獲取的數(shù)據(jù),可以獲得人體的三維姿態(tài)信息。深度模態(tài)可以使用深度卷積神經(jīng)網(wǎng)絡或其他深度學習模型進行處理,并與其他數(shù)據(jù)模態(tài)進行融合以提高行為識別的準確性。 -
光流(optical-flow)
光流模態(tài)是指從視頻序列中提取的光流數(shù)據(jù),光流是描述像素點在時間上的運動變化的一種方法。光流模態(tài)可以用于描述人體運動的速度和方向,通常使用光流特征和深度學習模型進行行為識別。 -
骨骼(skeleton)
骨骼模態(tài)是指從動作捕捉設備中獲取的人體骨骼關節(jié)信息,可以獲得人體的動態(tài)姿態(tài)信息。骨骼模態(tài)可以使用骨骼關節(jié)坐標和骨骼運動特征等方法進行處理,并與其他數(shù)據(jù)模態(tài)進行融合以提高行為識別的準確性。
在時間維度上,行為識別通常會對視頻序列進行切割,形成不同的視頻段。在遍歷維度上,行為識別通常會使用卷積神經(jīng)網(wǎng)絡對視頻幀進行特征提取,并使用循環(huán)神經(jīng)網(wǎng)絡(Recurrent Neural Networks,RNN)或卷積神經(jīng)網(wǎng)絡進行視頻段級別的建模。為了提高行為識別的準確性,通常需要使用多種數(shù)據(jù)模態(tài)和處理方法進行融合。
算子擴展
Conv3d
GraphConv
- Conv3d
Conv3d是一種三維卷積操作,用于處理視頻數(shù)據(jù)等三維數(shù)據(jù)。它類似于卷積神經(jīng)網(wǎng)絡中的二維卷積操作,但是Conv3d對于三維數(shù)據(jù)的特征提取更為有效。Conv3d操作通常由多個3D卷積核組成,每個卷積核在三個維度上分別進行卷積,從而提取出三維數(shù)據(jù)中的特征。
Conv3d的輸入是一個四維張量,其維度分別為[batch_size, channels, depth, height, width],其中batch_size表示批量大小,channels表示通道數(shù),depth表示深度,height表示高度,width表示寬度。Conv3d的輸出也是一個四維張量,其維度與輸入張量相同。
- GraphConv
GraphConv是一種用于圖神經(jīng)網(wǎng)絡的卷積操作,用于處理圖結構數(shù)據(jù)。與傳統(tǒng)的卷積操作不同,GraphConv并不是在圖像上進行滑動窗口的操作,而是在圖的頂點上進行卷積操作。GraphConv利用圖的鄰接矩陣來描述頂點之間的關系,并將鄰接矩陣作為卷積核來提取頂點的特征。
GraphConv的輸入是一個二維張量,其維度為[batch_size, num_nodes, num_features],其中batch_size表示批量大小,num_nodes表示圖的頂點數(shù),num_features表示每個頂點的特征維度。GraphConv的輸出也是一個二維張量,其維度與輸入張量相同。
GraphConv可以應用于各種類型的圖結構數(shù)據(jù),例如社交網(wǎng)絡、推薦系統(tǒng)、化學分子等。它可以有效地捕獲頂點之間的關系,從而提高圖神經(jīng)網(wǎng)絡的性能。
https://blog.csdn.net/weixin_44402973/article/details/103498856
光流方程
光流方程是描述光流的數(shù)學模型,它描述了圖像中同一物體在不同幀之間的像素級運動狀態(tài)。在光流法中,光流方程是基于光強不變假設推導出來的。
假設在第t幀中一個像素點的位置為(x,y),在第t+1幀中位置為(x+u,y+v),其中(u,v)表示像素點在x和y方向上的位移,光強不變假設認為這兩個位置的像素點的灰度值是相等的。因此,可以得到光流方程:
I(x,y,t) = I(x+u,y+v,t+1)
其中,I(x,y,t)表示在第t幀中像素點(x,y)的灰度值,I(x+u,y+v,t+1)表示在第t+1幀中像素點(x+u,y+v)的灰度值。
使用泰勒展開對光強進行近似,可以得到:
I(x+u,y+v,t+1) ≈ I(x,y,t) + uIx + vIy + It
其中,Ix、Iy和It分別表示在像素點(x,y)處沿x、y和時間t方向的灰度梯度。
將上式代入光流方程中,可得到:
Ixu + Iyv = -It
這就是光流方程,它描述了像素在相鄰幀中的運動狀態(tài),其中(u,v)表示像素點在x和y方向上的位移,Ix和Iy表示在像素點(x,y)處沿x、y方向的灰度梯度,It表示在相鄰幀中像素點灰度的變化。
光流
光流(optical flow)是指在圖像序列中,相鄰兩幀之間,同一物體在像素級別上的運動狀態(tài)。光流法是一種基于像素級別的物體運動分析方法,它可以用于運動目標的跟蹤、三維重建、視覺里程計等應用。
在光流法中,核心的假設是光強不變假設,即同一點在相鄰幀中的光強不變。由此可以推導出光流方程,它描述了像素在相鄰幀中的運動狀態(tài)。光流方程的推導基于三個假設:光強不變假設、運動可微假設和區(qū)域一致性假設。
根據(jù)光強不變假設,同一點在相鄰幀中的光強不變,可以使用一階泰勒展開對光強進行近似。由此可以獲得光流方程,它描述了像素在相鄰幀中的運動狀態(tài)。但是,光流方程只有一個方程,還無法求解。為了解決這個問題,可以構造點的鄰域多個點的方程組,基于區(qū)域一致性假設,認為一點的鄰域運動一致。這樣,就可以得到多個方程,使用最小二乘法求解超定方程組,獲得像素點的運動狀態(tài)。
Lucas-Kanade光流法是一種稀疏光流方法,它使用像素點的鄰域點來構造方程組,提高了求解光流的效率。對于每個像素點,只選擇其鄰域中的一些點來構造方程組,從而減少了求解的復雜度。
總之,光流法是一種基于像素級別的物體運動分析方法,它可以用于運動目標的跟蹤、三維重建、視覺里程計等應用。
光流optical-flow
相鄰幀物體運動趨勢,
核心假設:
光強不變假設,同一點在相鄰幀光強差分為0。環(huán)境光一致,引起光強變化的只有物體運動
運動可微,時間變化不引起位置突變
區(qū)域一致性,一點的鄰域運動一致,相鄰幀同一點的鄰域近似( Lucas-Kanade光流法,稀疏光流)
一階泰勒展開
指高階無窮小
基于,獲得光流方程
除以dt,dt可認為是1,獲得
關注 ,是像素點p(x,y)在t時刻沿著x,y方向的運動速度
此時只有一個方程,還無法求解
類同上述方法,構造點P(x,y)鄰域多個點的一組方程,
基于假設3鄰域運動一致性,有一致, 為相鄰幀灰度變化
可對一點的鄰域多個點,聯(lián)立獲得方程組
和是單幀灰度圖在x,y方向的偏導,可使用sobel算子計算
是相鄰幀灰度圖差分
例如1個中心點,8個鄰域點,共9個方程,即3*3窗口內(nèi)運動一致
此時有兩個待求解參數(shù),這是一個超定方程組,可使用最小二乘法等求解
參考資料:
光流法(optical flow methods) - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/384651830
圖源:
光流估計——從傳統(tǒng)方法到深度學習 - 知乎 (zhihu.com)
A Comprehensive Study of Deep Video Action Recognition
https://zhuanlan.zhihu.com/p/74460341
骨骼skeleton
在人體骨骼關鍵點的場景中,可以使用無向圖G來表示骨骼的拓撲結構,其中點V表示人體的關鍵點,邊E表示骨骼之間的連接關系。鄰接矩陣A可以用來表示圖中點之間的連接情況,其中A(i,j)表示點i和點j之間是否有連接,如果有連接則為1,否則為0。
對于人體關鍵點,每個關鍵點可以表示為一個二元組[k,p],其中k表示關鍵點的標識,p表示關鍵點的位置信息。位置信息可以使用二維坐標 (x,y) 或三維坐標 (x,y,z) 來表示,其中 x、y 和 z 分別表示關鍵點在空間中的 x、y 和 z 坐標,c 表示關鍵點的置信度或可見度。
連接的邊長可以表示骨骼之間的距離,可以使用歐幾里得距離或其他距離度量來計算。在鄰接矩陣中,可以將邊長作為權重來表示,即 A(i,j) 表示點i和點j之間的邊權重,如果沒有連接則為0。這樣可以更準確地表示關鍵點之間的連接情況和距離關系。
無向圖G
點V
邊E
鄰接矩陣A,
鄰接為1,不考慮權重
人體關鍵點: [k,p], p=[x,y,c]或[x,y,z]
鄰接矩陣:
所有點兩兩連接(外積)
連接的邊長
右圖有什么問題?
0代表斷開還是距離為0,v和v自身連接如何表示?
在右圖中,鄰接矩陣中的0表示兩個點之間沒有邊連接,1表示有邊連接。因此,如果一個點與自身相連,則對應的鄰接矩陣元素應該為1。在人體關鍵點的情況下,如果一個關鍵點與自身相連,則表示該關鍵點存在自連接,可以使用1來表示。如果一個關鍵點與另一個關鍵點沒有連接,那么這兩個關鍵點之間的鄰接矩陣元素應該為0,而不是表示距離為0。
對于連接的邊長,可以將其作為權重進行表示,可以考慮使用帶權鄰接矩陣來表示圖,其中矩陣元素表示對應邊的權重。如果兩個關鍵點之間沒有連接,則對應的鄰接矩陣元素為0,表示它們之間沒有邊連接,也沒有權重。
圖源:
https://zhuanlan.zhihu.com/p/89503068
Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition
算子擴展
https://zhuanlan.zhihu.com/p/63974249
im2col 方法是一種將卷積運算轉化為矩陣乘法的方法,在卷積神經(jīng)網(wǎng)絡中被廣泛使用。其實現(xiàn)步驟如下:
- 對輸入圖像進行補零操作,使得卷積后輸出的大小與輸入大小相同。補零的大小由卷積核大小和步幅決定。
- 對補零后的輸入圖像進行滑動窗口操作,將每個窗口中的像素按照列優(yōu)先的方式排列成一個列向量,形成一個二維矩陣。這個矩陣的每一列對應于一個滑動窗口中的像素。
- 將所有滑動窗口中的列向量拼接成一個大矩陣,每一列對應于一個滑動窗口中的像素。
- 將卷積核中的元素按照行優(yōu)先的方式排列成一個行向量,形成一個二維矩陣。這個矩陣的每一行對應于卷積核中的一個元素。
- 對于每個卷積核大小的窗口,在步驟3生成的大矩陣中,選取對應的列向量,將其按行排列成一個行向量。這樣得到的矩陣的每一行對應于一個卷積核大小的窗口。
- 對于每個卷積核大小的窗口,將其對應的行向量與卷積核矩陣相乘,得到一個標量。這樣得到的標量構成了輸出矩陣中的一個元素。
- 將輸出矩陣進行重塑,得到輸出圖像。
這樣,通過將卷積運算轉化為矩陣乘法,可以利用矩陣乘法的高效性和并行性,加速卷積神經(jīng)網(wǎng)絡的計算過程。
-
im2col的反向計算是col2im。在反向傳播時,需要將誤差傳遞回輸入數(shù)據(jù)中,col2im就是將誤差轉換回輸入數(shù)據(jù)的過程。具體步驟如下:
1)將誤差張量重排為二維矩陣,每一列對應于im2col中的一列。
2)將卷積核重排為二維矩陣,每一行對應于im2col中的一行。
3)將二維誤差矩陣和二維卷積核矩陣相乘,得到二維輸出矩陣。
4)將輸出矩陣重排為輸入數(shù)據(jù)的形狀,即使用與im2col中相同的窗口大小和步幅,按照列優(yōu)先的方式將輸出矩陣轉換為輸入數(shù)據(jù)張量的形狀。 -
進行圖像仿射增強(旋轉)的目的是為了增加數(shù)據(jù)的多樣性和增強模型的泛化能力。通過旋轉圖像,可以得到更多的訓練數(shù)據(jù),從而使模型更好地學習圖像特征。對于卷積神經(jīng)網(wǎng)絡中的卷積核,如果圖像被旋轉了,卷積核也應該隨之旋轉,這樣才能更好地識別圖像中的特征。因此,在進行圖像旋轉時,卷積神經(jīng)網(wǎng)絡中的卷積核參數(shù)也需要進行旋轉,并重新訓練模型,以獲得更好的性能。
反映在filter參數(shù)上的特征是,經(jīng)過旋轉后的卷積核參數(shù)不再具有原來的對稱性和平移不變性,因此需要更多的參數(shù)來表示卷積核,以適應旋轉后的圖像特征。在旋轉圖像時,需要重新訓練卷積神經(jīng)網(wǎng)絡中的卷積核參數(shù),以適應旋轉后的圖像特征。
圖卷積神經(jīng)網(wǎng)絡
圖卷積神經(jīng)網(wǎng)絡(Graph Convolutional Networks,簡稱GCN)是一種能夠處理圖數(shù)據(jù)的神經(jīng)網(wǎng)絡模型。與傳統(tǒng)的卷積神經(jīng)網(wǎng)絡不同,GCN能夠處理非歐幾里得結構的數(shù)據(jù),如社交網(wǎng)絡、蛋白質分子結構等,具有廣泛的應用前景。
GCN的核心思想是在圖上進行卷積操作,將節(jié)點的特征表示傳遞給其鄰居節(jié)點,并進行加權求和。具體來說,GCN中的每個節(jié)點都有一個特征表示,這個特征表示可以是節(jié)點自身的特征向量,也可以是由節(jié)點的鄰居節(jié)點的特征向量組成的聚合特征向量。GCN通過對每個節(jié)點的特征向量進行線性變換和非線性變換,得到每個節(jié)點的新特征向量。這個過程可以看作是將節(jié)點的特征表示映射到一個更高維度的空間中,并在這個空間中進行卷積操作。
具體來說,GCN的卷積操作可以表示為:
H ( l + 1 ) = σ ( D ^ ? 1 2 A ^ D ^ ? 1 2 H ( l ) W ( l ) ) H^{(l+1)} = \sigma(\hat{D}^{-\frac{1}{2}}\hat{A}\hat{D}^{-\frac{1}{2}}H^{(l)}W^{(l)}) H(l+1)=σ(D^?21?A^D^?21?H(l)W(l))
其中, H ( l ) H^{(l)} H(l)表示第 l l l層GCN中所有節(jié)點的特征矩陣, A ^ \hat{A} A^是一個帶自環(huán)的鄰接矩陣, D ^ \hat{D} D^是 A ^ \hat{A} A^的對角線矩陣, σ \sigma σ是非線性激活函數(shù), W ( l ) W^{(l)} W(l)是第 l l l層GCN的權重矩陣。這個公式表示將節(jié)點的特征矩陣 H ( l ) H^{(l)} H(l)通過一個線性變換 W ( l ) W^{(l)} W(l)映射到一個新的特征空間中,然后通過鄰接矩陣 A ^ \hat{A} A^計算節(jié)點之間的鄰接關系,將節(jié)點的特征向量傳遞給鄰居節(jié)點,并進行加權求和。最后,通過非線性激活函數(shù) σ \sigma σ將這個加權和映射回原始特征空間,得到每個節(jié)點的新特征向量 H ( l + 1 ) H^{(l+1)} H(l+1)。
GCN的訓練過程通常使用反向傳播算法進行優(yōu)化,目標是最小化損失函數(shù),以提高模型的泛化能力。
圖卷積神經(jīng)網(wǎng)絡(GCN)的出現(xiàn)是為了解決圖數(shù)據(jù)處理的問題。傳統(tǒng)的神經(jīng)網(wǎng)絡模型(如全連接神經(jīng)網(wǎng)絡、卷積神經(jīng)網(wǎng)絡等)只能處理歐幾里得結構的數(shù)據(jù),即數(shù)據(jù)在空間上具有規(guī)則的網(wǎng)格結構。而對于圖數(shù)據(jù),其節(jié)點之間的連接關系是任意的、不規(guī)則的,因此無法直接應用傳統(tǒng)的神經(jīng)網(wǎng)絡模型進行處理。
GCN的出現(xiàn)恰好填補了這一空白。GCN可以通過圖卷積操作在節(jié)點之間傳遞和聚合信息,并在此基礎上提取圖的特征表示,從而可以用于圖數(shù)據(jù)的分類、聚類、鏈接預測等任務。
除了傳統(tǒng)神經(jīng)網(wǎng)絡無法處理圖數(shù)據(jù)這一問題,還有一些其他的原因促成了圖卷積神經(jīng)網(wǎng)絡的出現(xiàn):
-
圖數(shù)據(jù)的稀疏性:在圖數(shù)據(jù)中,節(jié)點之間的連接關系是任意的,這就導致圖數(shù)據(jù)通常是稀疏的。而傳統(tǒng)的神經(jīng)網(wǎng)絡模型需要密集的連接參數(shù),這就導致了傳統(tǒng)神經(jīng)網(wǎng)絡難以處理稀疏的圖數(shù)據(jù)。GCN使用的鄰接矩陣可以有效地處理稀疏性問題。
-
圖數(shù)據(jù)的不變性:在圖數(shù)據(jù)中,節(jié)點的標號是任意的,這就導致了節(jié)點的相對位置可能發(fā)生變化,從而導致傳統(tǒng)的神經(jīng)網(wǎng)絡模型很難應對。GCN使用的卷積操作是基于鄰接矩陣的,可以保證在不同圖中相同的節(jié)點具有相同的特征表示,從而具有一定的不變性。
-
圖數(shù)據(jù)的非平凡性:與傳統(tǒng)的歐幾里得結構的數(shù)據(jù)不同,圖數(shù)據(jù)中的每個節(jié)點都是獨立的,且每個節(jié)點的特征向量可能具有不同的維度。這就導致了傳統(tǒng)的神經(jīng)網(wǎng)絡模型很難處理圖數(shù)據(jù)中的非平凡性。GCN使用的卷積操作可以在不同的節(jié)點之間共享權重,從而有效地處理圖數(shù)據(jù)中的非平凡性問題。
因此,圖卷積神經(jīng)網(wǎng)絡的出現(xiàn)是為了解決圖數(shù)據(jù)的處理問題,GCN具有對圖數(shù)據(jù)進行有效的特征表示和學習的能力,能夠在圖數(shù)據(jù)的分類、聚類、鏈接預測等任務中取得較好的性能。
Conv3d : cincout(dhw)
3d數(shù)據(jù):d-depth
時序數(shù)據(jù):d-time
Kernel : cin*(d,k,k)
Filter : cout*(cin,d,k,k)
GraphConv,一般只考慮距離為1的鄰接點
Image描述為graph:
可獲得:
點集{V}={RGB(x,y)}
邊集{E}:{P(x,y)鄰接p(x1,y),p(x,y±1)},角點各有2個鄰接點,邊點各有3個鄰接點,其它點各有4個鄰接點
Conv2d描述為GraphConv:
假設一個conv2d的kernel,角點=0,其它點=1/5,則卷積過程等價于將一個像素與上下左右四個鄰接點做平均
等價于用GraphConv對點P和鄰接點{p(x1,y),p(x,y±1)}做圖卷積
圖源:從圖(Graph)到圖卷積(Graph Convolution):漫談圖神經(jīng)網(wǎng)絡模型 (二) - 知乎 (zhihu.com)
算子擴展:
GraphConv
節(jié)點的特征向量H
鄰接矩陣A,鄰接=1,不考慮權重
度矩陣D,鄰接點數(shù)
拉普拉斯矩陣L,D-A
激活函數(shù)σ
特征聚合計算方法
-
H’ = σ(A@H),存在什么問題?
維度變換:(k,p) = (k,k) @ (k,p)
L = D-A -
H’ = σ(L@H@W),存在什么問題?
-
L’ = ,可簡單理解為度矩陣的逆與鄰接矩陣的矩陣乘積
-
H’ = σ(A@H)存在什么問題?
在這種情況下,特征聚合的計算方法是直接將鄰接矩陣A與特征矩陣H做矩陣乘法,得到新的特征矩陣H’。這種方法存在一個問題,就是它沒有考慮到節(jié)點的度數(shù)信息,節(jié)點的度數(shù)對特征的聚合和傳遞有著重要的影響。在這種情況下,節(jié)點的度數(shù)越大,鄰居節(jié)點對該節(jié)點的特征聚合的影響就越大,但是直接使用鄰接矩陣進行特征聚合無法反映這種影響。 -
H’ = σ(L@H@W)存在什么問題?
在這種情況下,特征聚合的計算方法是將拉普拉斯矩陣L與特征矩陣H做矩陣乘法,并乘以權重矩陣W,得到新的特征矩陣H’。這種方法考慮了節(jié)點的度數(shù)信息,因為拉普拉斯矩陣中的度矩陣D反映了節(jié)點的度數(shù)信息。但是,這種方法存在一個問題,就是它沒有考慮到節(jié)點的自身特征信息,因為特征矩陣H直接乘以拉普拉斯矩陣L,沒有對特征矩陣進行變換。這可能會導致模型對節(jié)點自身特征的處理不足,影響模型的性能。 -
L’ = D^-1/2 * A * D^-1/2可簡單理解為度矩陣的逆與鄰接矩陣的矩陣乘積
在這種情況下,特征聚合的計算方法是先將鄰接矩陣A通過度矩陣D的逆矩陣進行歸一化處理,得到新的鄰接矩陣L’,然后將L’與特征矩陣H做矩陣乘法,并乘以權重矩陣W,得到新的特征矩陣H’。這種方法綜合考慮了節(jié)點的度數(shù)信息和節(jié)點自身特征信息,因為它同時考慮了鄰接矩陣和度矩陣。這種方法的性能要優(yōu)于上述兩種方法,因為它能夠更好地反映節(jié)點的特征聚合和傳遞過程。
主流算法
基于雙流網(wǎng)絡
雙流網(wǎng)絡是一種常用于視頻行為識別的深度學習模型,它使用兩個并行的卷積神經(jīng)網(wǎng)絡來處理視頻的兩個輸入流:圖像流和光流流。
圖像流是由視頻的一系列幀組成的,它提供了視頻中靜態(tài)的外觀信息。光流流是通過計算相鄰幀之間的像素運動而得到的,它提供了視頻中動態(tài)的運動信息。
在雙流網(wǎng)絡中,每個輸入流都有自己的卷積神經(jīng)網(wǎng)絡,這些網(wǎng)絡通常具有不同的結構和參數(shù)。例如,圖像流可以使用常規(guī)的卷積神經(jīng)網(wǎng)絡,例如VGG、ResNet等,而光流流通常使用光流估計算法提取光流特征,并使用3D卷積神經(jīng)網(wǎng)絡來處理光流張量。然后,兩個流的特征可以合并并輸入到全連接層中進行分類。
雙流網(wǎng)絡的優(yōu)點是它可以利用視頻中的靜態(tài)和動態(tài)信息,并且在行為識別任務中表現(xiàn)出了優(yōu)異的性能。它已經(jīng)在許多視頻行為識別任務中得到了廣泛的應用,例如人類行為識別、交通行為識別和手勢識別等。
基于雙流網(wǎng)絡的深度學習方法可以用于行為識別,它是一種利用RGB圖像和光流圖像的雙流模型。光流是指一個像素在相鄰兩幀圖像中的運動軌跡,它可以提供物體的運動信息。在雙流網(wǎng)絡中,RGB圖像和光流圖像分別輸入到兩個卷積神經(jīng)網(wǎng)絡中進行處理,然后將它們的特征合并起來進行分類,以實現(xiàn)對行為的識別。
以下是一些基于雙流網(wǎng)絡的行為識別的深度學習應用的例子:
-
人體行為識別:基于雙流網(wǎng)絡的深度學習方法可以用于人體行為識別,例如識別跑步、跳躍、打拳等行為。這種方法通常使用卷積神經(jīng)網(wǎng)絡和循環(huán)神經(jīng)網(wǎng)絡進行處理。
-
交通行為識別:基于雙流網(wǎng)絡的深度學習方法可以用于交通行為識別,例如識別汽車、行人、自行車等交通工具的行為。這種方法通常使用卷積神經(jīng)網(wǎng)絡和循環(huán)神經(jīng)網(wǎng)絡進行處理。
-
動作識別:基于雙流網(wǎng)絡的深度學習方法可以用于動作識別,例如識別手勢、面部表情等動作。這種方法通常使用卷積神經(jīng)網(wǎng)絡和循環(huán)神經(jīng)網(wǎng)絡進行處理。
需要注意的是,基于雙流網(wǎng)絡的深度學習方法需要大量的訓練數(shù)據(jù)和計算資源,同時需要特別注意數(shù)據(jù)預處理、數(shù)據(jù)增強和模型的選擇等問題。此外,基于雙流網(wǎng)絡的深度學習方法在實際應用中還存在一些挑戰(zhàn),例如如何處理光流圖像和如何選擇合適的網(wǎng)絡結構等問題。
基于3d模型
3D卷積神經(jīng)網(wǎng)絡(3D CNN)是一種深度學習模型,用于處理3D數(shù)據(jù),例如視頻、醫(yī)學圖像和3D物體等。它們是2D CNN的拓展,可以在視頻或3D圖像的三個維度上執(zhí)行卷積運算。
3D CNN的基本結構與2D CNN類似,包括卷積層、池化層和全連接層。在卷積層中,3D CNN使用3D卷積核來卷積3D張量。在池化層中,我們使用3D池化核來對3D張量進行池化操作。在全連接層中,我們將3D張量轉換為一維向量,并將其輸入到全連接層中進行分類或回歸。
當我們處理3D數(shù)據(jù)時,可以使用基于3D卷積神經(jīng)網(wǎng)絡(3D CNN)的深度學習模型。與2D CNN類似,3D CNN也使用卷積層和池化層來提取3D數(shù)據(jù)中的特征,并使用全連接層來分類或回歸。
3D CNN的輸入是一個三維張量,通常是由多個3D圖像組成的。類似于2D CNN,3D CNN也可以通過堆疊多個卷積層和池化層來增加網(wǎng)絡的深度。在卷積層中,我們使用3D卷積核來卷積3D張量。在池化層中,我們使用3D池化核來對3D張量進行池化操作。
在訓練3D CNN時,我們可以使用與2D CNN類似的方法,例如隨機梯度下降(SGD)和反向傳播算法。同時,我們還可以使用其他進階的優(yōu)化算法,例如Adam和Adagrad等。
3D CNN常常被用于處理3D數(shù)據(jù),例如視頻、3D物體和醫(yī)學圖像等。它們在行為識別、物體識別和醫(yī)學圖像分割等領域都有廣泛的應用。
基于3D模型的深度學習方法可以用于行為識別,它是一種利用視頻序列中的3D信息進行行為識別的方法。與基于2D模型的方法不同,基于3D模型的方法可以直接利用視頻中的空間信息,從而能夠更好地捕捉物體的運動和行為。
以下是一些基于3D模型的行為識別的深度學習應用的例子:
-
人體行為識別:基于3D模型的深度學習方法可以用于人體行為識別,例如識別跑步、跳躍、打拳等行為。這種方法通常使用3D卷積神經(jīng)網(wǎng)絡進行處理。
-
交通行為識別:基于3D模型的深度學習方法可以用于交通行為識別,例如識別汽車、行人、自行車等交通工具的行為。這種方法通常使用3D卷積神經(jīng)網(wǎng)絡進行處理。
-
動作識別:基于3D模型的深度學習方法可以用于動作識別,例如識別手勢、面部表情等動作。這種方法通常使用3D卷積神經(jīng)網(wǎng)絡進行處理。
需要注意的是,基于3D模型的深度學習方法也需要大量的訓練數(shù)據(jù)和計算資源,同時需要特別注意數(shù)據(jù)預處理、數(shù)據(jù)增強和模型的選擇等問題。此外,基于3D模型的深度學習方法還存在一些挑戰(zhàn),例如如何處理不同尺度的3D模型、如何處理運動模糊等問題。
基于2d模型+時序模型
基于2D模型+時序模型的行為識別算法通常是指將2D圖像和時間序列信息結合起來進行行為識別的方法。該算法包括兩個主要步驟:首先,使用2D卷積神經(jīng)網(wǎng)絡(CNN)從每個視頻幀中提取特征。其次,使用時序模型(例如循環(huán)神經(jīng)網(wǎng)絡,LSTM等)將提取的特征序列建模為行為序列,并對其進行分類或回歸。
具體來說,基于2D模型+時序模型的行為識別算法可以分為以下步驟:
-
數(shù)據(jù)預處理:對視頻進行預處理,例如裁剪、縮放和標準化等操作,以便于后續(xù)處理。
-
特征提?。菏褂?D CNN從視頻幀中提取特征。可以使用預先訓練好的2D CNN模型(例如VGG,ResNet等),也可以自己訓練一個特定于任務的2D CNN模型。
-
特征序列建模:使用時序模型將2D CNN提取的特征序列建模為行為序列??梢允褂肔STM、GRU等循環(huán)神經(jīng)網(wǎng)絡模型,也可以使用卷積LSTM等結合卷積和LSTM的模型。
-
行為分類或回歸:使用全連接層將時序模型的輸出映射到類別標簽或回歸值上。
基于2D模型+時序模型的行為識別算法通常需要大量的訓練數(shù)據(jù)和計算資源。此外,需要特別注意數(shù)據(jù)預處理、數(shù)據(jù)增強和模型的選擇等問題,以及如何處理不同尺度和運動模糊等問題。
基于骨架的圖模型
基于骨架的圖模型的行為識別算法是一種利用人體骨架信息進行行為識別的方法。該算法首先從視頻中檢測出人體骨架信息,然后將骨架信息轉換為圖模型,最后使用圖神經(jīng)網(wǎng)絡對圖模型進行建模和分類。
具體來說,基于骨架的圖模型的行為識別算法可以分為以下步驟:
-
數(shù)據(jù)預處理:對視頻進行預處理,例如裁剪、縮放和標準化等操作,以便于后續(xù)處理。
-
骨架檢測:使用人體骨架檢測算法(例如OpenPose)從視頻中提取人體骨架信息。
-
圖模型構建:將每個骨架節(jié)點轉換為圖模型中的節(jié)點,并連接相鄰的節(jié)點,構建骨架圖模型??梢愿鶕?jù)不同需求選擇不同的圖模型,例如基于鄰接矩陣的圖模型或基于邊列表的圖模型等。
-
圖神經(jīng)網(wǎng)絡建模:使用圖神經(jīng)網(wǎng)絡對骨架圖模型進行建模??梢允褂没贕CN(圖卷積網(wǎng)絡)或GAT(圖自注意力網(wǎng)絡)的圖神經(jīng)網(wǎng)絡模型。
-
行為分類:使用全連接層將圖神經(jīng)網(wǎng)絡的輸出映射到類別標簽上。
基于骨架的圖模型的行為識別算法可以利用人體骨架信息,不受視頻中的光照、背景等因素的影響,因此具有較好的魯棒性。此外,圖神經(jīng)網(wǎng)絡可以對不同的節(jié)點和邊進行建模,因此可以更好地捕捉骨架中的關節(jié)運動和姿態(tài)信息,提高行為識別的準確率。
需要注意的是,基于骨架的圖模型的行為識別算法需要大量的訓練數(shù)據(jù)和計算資源,同時需要特別注意數(shù)據(jù)預處理、數(shù)據(jù)增強和模型的選擇等問題,以及如何處理不同動作速度和姿態(tài)變化等問題。
slowfast
SlowFast是一種用于視頻行為識別的深度學習模型,由Facebook AI Research提出。它結合了慢速和快速兩個流程,以提高對視頻中快速動作和細節(jié)的捕捉能力。SlowFast模型由兩個部分組成:慢速骨干網(wǎng)絡和快速骨干網(wǎng)絡。
慢速骨干網(wǎng)絡處理低頻信息,例如物體的整體移動和姿態(tài)變化,以較低的幀率處理視頻。它通常采用較深的2D CNN模型(例如ResNet)來提取特征??焖俟歉删W(wǎng)絡處理高頻信息,例如物體的細節(jié)和文物,以較高的幀率處理視頻。它通常采用較淺的2D CNN模型(例如VGG)來提取特征。
SlowFast模型的主要優(yōu)點包括:
-
高效的特征提?。和ㄟ^分層處理視頻,SlowFast模型可以高效地提取視頻中的關鍵特征,從而提高行為識別的準確率。
-
對快速動作和細節(jié)的敏感度:采用慢速和快速兩個流程可以有效地捕捉視頻中的快速動作和細節(jié),從而提高行為識別的準確率。
-
可擴展性:SlowFast模型可以輕松地應用于不同的視頻行為識別任務,例如動作分類、動作檢測和行為定位等。
需要注意的是,使用SlowFast模型進行行為識別需要大量的訓練數(shù)據(jù)和計算資源,同時需要特別注意數(shù)據(jù)預處理、數(shù)據(jù)增強和模型的選擇等問題,以及如何處理不同尺度和運動模糊等問題。
st-gcn
ST-GCN是一種基于時空圖卷積神經(jīng)網(wǎng)絡(Spatial-Temporal Graph Convolutional Network)的視頻行為識別模型,它可以對人體骨骼運動進行建模并進行行為分類。ST-GCN模型可以捕捉人體骨骼運動中的時空關系,從而更好地表征人體運動特征。
ST-GCN主要包括三個部分:時空圖的構建、時空圖卷積神經(jīng)網(wǎng)絡和分類器。
-
時空圖的構建:首先,將人體骨骼運動序列轉化為時空圖結構,每個節(jié)點代表一個骨骼關鍵點,每條邊代表不同關鍵點之間的相連關系。然后,根據(jù)關鍵點之間的距離和時間上的關系,構建時空圖。
-
時空圖卷積神經(jīng)網(wǎng)絡:將構建好的時空圖輸入到ST-GCN的卷積神經(jīng)網(wǎng)絡中,其中每個節(jié)點表示一個骨骼關鍵點,每個時空圖卷積層都包含時空卷積和相應的非線性激活函數(shù)。通過多層時空圖卷積網(wǎng)絡的堆疊,可以有效地提取時空特征。
-
分類器:最后,使用全局池化操作將時空圖卷積網(wǎng)絡的輸出轉換為固定長度的特征向量,然后使用全連接層將其映射到行為類別上進行分類。
ST-GCN模型具有以下優(yōu)點:
-
能夠有效地捕捉人體骨骼運動的時空關系,提高行為分類的準確性。
-
可以處理不同數(shù)量的關鍵點和不同長度的骨骼運動序列。
-
模型參數(shù)相對較少,具有較高的計算效率。
需要注意的是,使用ST-GCN模型進行行為識別需要大量的訓練數(shù)據(jù)和計算資源,同時需要特別注意數(shù)據(jù)預處理、數(shù)據(jù)增強和模型的選擇等問題,以及如何處理不同尺度和姿態(tài)變化等問題。
Topdown-heatmap關鍵點檢測下的Hrnet
數(shù)據(jù)模態(tài)
數(shù)據(jù)模態(tài):
Rgb圖像=>人體檢測框對中圖像
保存框中心坐標center,以及寬高wh(縮放scale),用于將結果映射回原圖(decode)
算子擴展
算子擴展:
Conv2d(stride=2,…),縮小2倍圖像尺寸
Conv2d(ksize=1,…),保持原圖尺寸,只做通道變換
Conv2d(dilation=2,…),膨脹卷積/空洞卷積,在卷積核行/列插入dilation-1行/列0值
Conv2d(group=k,…),分組卷積,輸入通道分k組,輸出通道分k組
(深度可分離卷積:Conv2d(group=n,…)+Conv2d(kernelsize=1,…))
Conv2dtranspose(inchannel,outchannel,stride,pad,…),轉置卷積(反卷積deconvolution)
在輸入圖行/列插入stride-1行/列0值
減去pad邊
Pool2d/unpool2d
參考資料:
conv_arithmetic/README.md at master · vdumoulin/conv_arithmetic (github.com)
常規(guī)卷積
Conv2d(stride=2,…),縮小2倍圖像尺寸
Pool2d(stride=2,…),縮小尺寸,增大感受野,不會改變通道數(shù)
Backward
圖像尺寸:
感受野計算(第T層在第i層的感受野大小,i從0開始,即原始圖像):
Conv1 = conv2d(3,3,1), conv2=conv2d(3,3,1)
Feature0=7, feature1=3, feature2=1
第2層在第1層的感受野:3 = (1-1)*1+3
第2層在第0層的感受野:5 = (3-1)*1+3
常規(guī)卷積
Conv2d(ksize=1,pad=0,…),保持原圖尺寸
可用于通道轉換(對齊,…)
可用于輸出頭,代替linear做像素粒度的輸出
全連接層限制輸入尺寸
圖源:
1X1 Convolution, CNN, CV, Neural Networks | Analytics Vidhya (medium.com)
膨脹卷積/空洞卷積
Conv2d(dilation=2,…),在卷積核行/列插入dilation-1行/列0值
Im2col計算方法類同conv2d
增大感受野(reception field)
分組卷積
Conv2d(group=k,…),分組卷積,輸入通道分k組,輸出通道分k組
(深度可分離卷積:Conv2d(group=n,…)+Conv2d(kernelsize=1,…))
Conv2d參數(shù)量:
分組卷積參數(shù)量:
=>
深度可分離卷積:depthwise-conv + pointwise-conv
當 時,分組卷積成為depthwise-conv,設
當ksize=1時,常規(guī)卷積成為pointwise-conv,參數(shù)量
這種通道維度和空間維度分別掃描的思路,也適用于其它輕量化算子
轉置卷積
不是嚴格意義上的反卷積(deconvolution):只還原尺寸,不還原參數(shù)
Conv2dtranspose(stride,pad,…)
- Kernel與之前的對應的卷積層一致
- Stride不指卷積核滑動步長,而是指插入0值行列數(shù)量:
- 在輸入圖行/列插入stride-1行/列0值
- 卷積核滑動步長恒定為1
- Pad是減去邊,而不是加上邊
- Kernel將在超出圖像邊界處掃描,最遠保持1行/列掃描到
使用雙線性插值初始化卷積核
Img —conv2d(ksize=3,stride=2,pad=1)—>mid_img—conv2dtranspose(ksize=3,stride=2,pad=1)—>img_rec
Imgsize(i):
池化
Pool2d(stride=2),下采樣,增大感受野。avg/max?
輸出池化值和局部坐標
反池化(Max)
Unpool2d
接受池化值和局部坐標
僅還原最大值在原圖的坐標,其它值舍去
池化和反池化都將導致尺寸還原過程中的信息損失
圖源:
MaxUnpool2d — PyTorch 2.0 documentation
融合方式
融合方式(fuse)
拉平拼接
相加
通道拼接
后融合:
logits/prob融合,直接相加
特征融合:
單流/多流
單跳/稠密
Block內(nèi)/block間
對齊方式
通道對齊(conv2d(ksize=1))
尺寸對齊(interpolate, conv2d/conv2dtranspose, pool/unpool)
Topdown-heatmap
https://zhuanlan.zhihu.com/p/394060630
原圖?目標檢測模型
人體框圖(保留框中心坐標和框長寬)
符合關鍵點模型輸入尺寸的人體對中圖?關鍵點模型
下采樣熱力圖,每個通道對應一個關鍵點的熱力圖,最大值處即為關鍵點估計坐標
基于下采樣倍率和關鍵點估計坐標的鄰域值,還原人體對中圖中的關鍵點坐標
基于框中心坐標和框長寬,還原原圖中的關鍵點坐標
Top-down heatmap是一種基于人體姿態(tài)估計的方法,通過生成人體關鍵點熱度圖(heatmap)的方式來預測人體姿態(tài)。
具體來說,該方法首先將圖像輸入到卷積神經(jīng)網(wǎng)絡中進行特征提取,然后在最后一層卷積層的輸出上生成多個人體關鍵點的熱度圖,其中每個熱度圖對應一個關鍵點。每個熱度圖中的值表示該關鍵點在圖像中的可能位置,值越大表示該位置越可能是該關鍵點的位置。然后,根據(jù)這些熱度圖,可以使用一些特定的算法或者模型提取出每個關鍵點的位置,從而得到人體姿態(tài)的估計結果。
Top-down heatmap方法的優(yōu)點是能夠很好地處理遮擋、姿態(tài)變化等情況,同時具有較好的準確性和魯棒性。但是,該方法對于多人姿態(tài)估計和關鍵點匹配問題還存在一定的挑戰(zhàn)。因此,近年來,一些新的方法如Bottom-up heatmap等也逐漸受到關注。
Hrnet論文流程解析
HRNet(High-Resolution Network)是一種用于圖像分類和目標檢測的深度神經(jīng)網(wǎng)絡模型,由北京大學計算機視覺實驗室提出。相比于傳統(tǒng)的深度神經(jīng)網(wǎng)絡,HRNet在保持高分辨率特征圖的同時,通過多個分支網(wǎng)絡進行特征融合,從而提高了模型的準確性。
以下是HRNet論文的主要流程解析:
-
高分辨率特征提取:HRNet采用了高分辨率輸入和高分辨率特征提取的策略,即將輸入圖像的分辨率保持在較高水平,同時使用多個分支網(wǎng)絡提取不同尺度的特征。
-
多尺度特征融合:HRNet通過多個分支網(wǎng)絡提取不同尺度的特征,并采用一種高效的特征融合方法將這些特征融合為一個高質量的特征表示。具體來說,HRNet將分支網(wǎng)絡中的特征進行級聯(lián)或相加操作,從而進行特征融合。
-
高分辨率特征重建:HRNet通過使用轉置卷積或上采樣等方法,將低分辨率的特征圖進行上采樣,從而恢復高分辨率特征圖。這一步操作能夠使得模型在保持高分辨率特征的同時,具有較小的計算開銷。
-
分類或檢測:HRNet將重建的高分辨率特征圖輸入全連接層,進行分類或檢測等任務。
HRNet在多個圖像分類和目標檢測的任務中都取得了較好的性能表現(xiàn),尤其是在需要提取高分辨率特征的任務中具有明顯的優(yōu)勢。
Hrnet實際代碼流程解析
下面是HRNet的具體代碼實現(xiàn)流程:
- 數(shù)據(jù)預處理:使用OpenCV等圖像處理庫將原始圖像進行縮放和裁剪,得到指定大小的輸入圖像,然后將其轉換為Tensor格式。這一步可以使用PyTorch或TensorFlow的數(shù)據(jù)加載器和轉換工具實現(xiàn)。
import cv2
import numpy as np
import torch
def preprocess(img, input_size):
img = cv2.resize(img, (input_size[1], input_size[0]))
img = np.array(img, dtype=np.float32)
img = img / 255.0
img = (img - [0.485, 0.456, 0.406]) / [0.229, 0.224, 0.225]
img = np.transpose(img, (2, 0, 1))
img = np.expand_dims(img, axis=0)
return torch.from_numpy(img)
- 構建網(wǎng)絡:HRNet的網(wǎng)絡結構可以使用PyTorch實現(xiàn)。在實現(xiàn)過程中,需要首先定義高分辨率特征提取模塊、多尺度特征融合模塊和高分辨率特征重建模塊,然后將這些模塊組合起來構建HRNet網(wǎng)絡。
import torch.nn as nn
import torch.nn.functional as F
class HighResolutionModule(nn.Module):
def __init__(self, num_branches, blocks, num_blocks, num_channels, fuse_method):
super(HighResolutionModule, self).__init__()
self.num_branches = num_branches
self.fuse_method = fuse_method
self.branches = self._make_branches(num_branches, blocks, num_blocks, num_channels)
self.fuse_layers = self._make_fuse_layers()
self.relu = nn.ReLU(inplace=True)
def _make_one_branch(self, branch_index, block, num_blocks, num_channels):
layers = []
layers.append(block(64, num_channels[branch_index], stride=2))
for i in range(1, num_blocks):
layers.append(block(num_channels[branch_index], num_channels[branch_index], stride=1))
return nn.Sequential(*layers)
def _make_branches(self, num_branches, block, num_blocks, num_channels):
branches = []
for i in range(num_branches):
branches.append(self._make_one_branch(i, block, num_blocks, num_channels))
return nn.ModuleList(branches)
def _make_fuse_layers(self):
if self.num_branches == 1:
return None
num_branches = self.num_branches
num_fuse_layers = num_branches - 1
fuse_layers = []
for i in range(num_fuse_layers):
fuse_layer = []
for j in range(num_branches):
if j > i:
fuse_layer.append(nn.Conv2d(num_channels[j], num_channels[i], kernel_size=1, stride=1, padding=0))
elif j == i:
fuse_layer.append(None)
else:
conv3x3s = []
for k in range(i-j):
in_channels = num_channels[j + k]
out_channels = num_channels[i]
conv3x3s.append(nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=2, padding=1),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True)))
fuse_layer.append(nn.Sequential(*conv3x3s))
fuse_layers.append(nn.ModuleList(fuse_layer))
return nn.ModuleList(fuse_layers)
def _fuse(self, x):
if self.num_branches == 1:
return x
out = []
for i in range(len(self.fuse_layers)):
y = x[0] if i == 0 else self.fuse_layers[i][0](x[0])
for j in range(1, self.num_branches):
if i == j:
y = y + x[j]
elif j > i:
width_output = x[i].shape[-1]
height_output = x[i].shape[-2]
y = y + F.interpolate(self.fuse_layers[i][j](x[j]), size=[height_output, width_output],
mode='bilinear', align_corners=True)
else:
y = y + self.fuse_layers[i][j](x[j])
out.append(self.relu(y))
return out
def forward(self, x):
if self.num_branches == 1:
return [self.branches[0](x[0])]
x = self.branches[0](x[0])
x = [x]
for i in range(1, self.num_branches):
y = self.branches[i](x[i-1])
if i == self.num_branches - 1 and self.num_branches > 1:
y = self.fuse_layers[-1][i-1](y)
x.append(y)
x = self._fuse(x)
return x
- 定義損失函數(shù):在HRNet中,通常使用均方誤差(MSE)作為損失函數(shù),用于計算預測關鍵點位置與真實位置之間的差異。
import torch.nn as nn
class HeatmapLoss(nn.Module):
def __init__(self):
super(HeatmapLoss, self).__init__()
def forward(self, pred, gt):
loss = ((pred - gt) ** 2).mean()
return loss
- 訓練模型:通過定義訓練循環(huán),可以使用PyTorch的優(yōu)化器和損失函數(shù)來訓練HRNet模型。訓練過程中,需要將輸入圖像和目標熱圖傳入網(wǎng)絡,計算損失并進行反向傳播,最終更新網(wǎng)絡參數(shù)。
import torch.optim as optim
# define HRNet model and optimizer
model = HRNet()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=0.0001)
# define loss function
criterion = HeatmapLoss()
# define training loop
for epoch in range(num_epochs):
running_loss = 0.0
for i, data in enumerate(train_loader, 0):
inputs, targets = data
inputs = inputs.to(device)
targets = targets.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, targets)
loss.backward()
optimizer.step()
running_loss += loss.item()
print('Epoch %d loss: %.3f' % (epoch + 1, running_loss / len(train_loader)))
- 測試模型:使用測試集數(shù)據(jù)對訓練好的HRNet模型進行評估,計算預測關鍵點位置與真實位置之間的差異,并輸出平均誤差。
# define testing loop
test_loss = 0.0
with torch.no_grad():
for data in test_loader:
inputs, targets = data
inputs = inputs.to(device)
targets = targets.to(device)
outputs = model(inputs)
loss = criterion(outputs, targets)
test_loss += loss.item()
print('Test loss: %.3f' % (test_loss / len(test_loader)))
- 使用模型進行預測:使用訓練好的模型對新的圖像進行關鍵點檢測。首先,需要將圖像進行預處理,然后將其輸入到HRNet模型中,得到預測的熱圖。最后,可以使用后處理技術(如非極大值抑制)來提取關鍵點位置。
import numpy as np
import cv2
# load image
img = cv2.imread('test.jpg')
# preprocess image
input_size = (256, 192)
img_tensor = preprocess(img, input_size)
# predict heatmaps
with torch.no_grad():
output = model(img_tensor.to(device))
heatmaps = output[-1].cpu().numpy()
# postprocess heatmaps
keypoints = []
for heatmap in heatmaps:
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
heatmap = cv2.GaussianBlur(heatmap, (3, 3), 0)
heatmap = heatmap / np.max(heatmap)
heatmap[heatmap < 0.3] = 0
heatmap = heatmap.astype(np.uint8)
contours, _ = cv2.findContours(heatmap, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
keypoint = cv2.minMaxLoc(heatmap, mask=contour[::-1])[3]
keypoints.append(keypoint)
# visualize keypoints
for keypoint in keypoints:
cv2.circle(img, keypoint, 3, (0, 255, 0), -1)
cv2.imshow('keypoints', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
這段代碼將輸入一個測試圖像,并得到預測的關鍵點坐標,最后可視化結果。
以上是一個簡單的人體姿態(tài)估計的流程,其中可以調(diào)整的參數(shù)有很多,比如網(wǎng)絡結構、預處理方式、后處理方式等,需要根據(jù)具體的應用場景進行調(diào)整。
Hrnet主要模塊
HRNet是一種新型的高分辨率網(wǎng)絡,相對于傳統(tǒng)的深度學習網(wǎng)絡,其最大的優(yōu)點是能夠在多個分辨率上提取特征,從而兼顧了高分辨率和低分辨率下的特征。HRNet模型主要由四個模塊組成,分別是:
-
高分辨率特征提取模塊(High-Resolution Feature Extraction Module):這個模塊負責從輸入圖像中提取高分辨率的特征,并將其送入下一層網(wǎng)絡。這個模塊由兩個分支組成,一個分支對輸入圖像進行下采樣,得到低分辨率的特征,另一個分支則保持輸入圖像的分辨率,得到高分辨率的特征。
-
多分辨率融合模塊(Multi-Resolution Fusion Module):這個模塊將來自不同分辨率的特征進行融合,以兼顧不同分辨率下的特征信息。具體來說,這個模塊將低分辨率的特征通過上采樣恢復到高分辨率,并與高分辨率的特征進行融合。
-
高分辨率特征重建模塊(High-Resolution Feature Reconstruction Module):這個模塊負責將融合后的特征重建回原始的高分辨率特征。具體來說,這個模塊通過一個反卷積操作將融合后的特征上采樣到原始分辨率。
-
最終預測模塊(Final Prediction Module):這個模塊使用重建后的高分辨率特征進行最終的預測。在人體姿態(tài)估計任務中,這個模塊通常會輸出關鍵點的熱圖,以指示關鍵點在圖像中的位置。
以上四個模塊構成了HRNet模型的基本結構。在實踐中,可以根據(jù)具體任務對這些模塊進行調(diào)整和修改,以達到更好的性能。
topdown關鍵點檢測的hrnet全流程代碼解析
下面是Top-Down方法的HRNet關鍵點檢測的完整代碼,其中包含了數(shù)據(jù)預處理、模型訓練、模型預測等步驟的詳細解析。
- 數(shù)據(jù)預處理
首先,我們需要對數(shù)據(jù)進行預處理,以便在HRNet模型中進行訓練。數(shù)據(jù)預處理一般包括以下幾個步驟:
- 將圖像進行縮放,使其長邊的長度為輸入尺寸(如256或384),短邊按比例縮放;
- 將關鍵點坐標進行縮放,使其與縮放后的圖像對應;
- 對圖像進行數(shù)據(jù)增強,如隨機旋轉、隨機裁剪、隨機翻轉等。
import cv2
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
class KeyPointDataset(Dataset):
def __init__(self, img_path, label_path, input_size=(256, 192)):
self.input_size = input_size
self.img_path = img_path
self.label_path = label_path
self.img_list = []
self.label_list = []
with open(img_path, 'r') as f:
for line in f.readlines():
self.img_list.append(line.strip())
with open(label_path, 'r') as f:
for line in f.readlines():
label = np.array(line.strip().split(' ')).astype(np.float32).reshape(-1, 3)
self.label_list.append(label)
self.transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
def __len__(self):
return len(self.img_list)
def __getitem__(self, index):
# load image and label
img = cv2.imread(self.img_list[index])
label = self.label_list[index]
# resize image and label
h, w, _ = img.shape
scale_h = self.input_size[0] / h
scale_w = self.input_size[1] / w
img = cv2.resize(img, self.input_size)
label[:, 0] *= scale_w
label[:, 1] *= scale_h
# data augmentation
if self.training:
angle = np.random.randint(-30, 30)
scale = np.random.uniform(0.8, 1.2)
trans_x = np.random.randint(-30, 30)
trans_y = np.random.randint(-30, 30)
center = np.array([w / 2, h / 2])
M = cv2.getRotationMatrix2D(tuple(center), angle, scale)
M[:, 2] += np.array([trans_x, trans_y])
img = cv2.warpAffine(img, M, (w, h))
label[:, :2] = self._affine_transform(label[:, :2], M)
# normalize image
img = self.transform(img)
return img, label
def _affine_transform(self, pts, M):
n = pts.shape[0]
pts_pad = np.concatenate([pts, np.ones((n, 1))], axis=1)
pts_trans = np.dot(pts_pad, M.T)
return pts_trans[:, :2]
# create dataset and dataloader
train_dataset = KeyPointDataset('train_img.txt', 'train_label.txt')
val_dataset = KeyPointDataset('val_img.txt', 'val_label.txt')
train_dataloader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4)
val_dataloader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=4)
以上代碼中,我們定義了一個KeyPointDataset類,用于加載數(shù)據(jù)集,并進行預處理。在__init__函數(shù)中,我們讀取圖像和標簽的路徑,并將它們分別存儲在img_list和label_list中。在__getitem__函數(shù)中,我們首先讀取對應索引的圖像和標簽,然后將它們進行縮放和數(shù)據(jù)增強。最后,我們將圖像轉化為Tensor類型,并進行歸一化處理。
- 模型訓練
接下來,我們使用PyTorch框架來訓練HRNet模型。在訓練之前,我們需要定義損失函數(shù)和優(yōu)化器。
import torch.nn as nn
import torch.optim as optim
# define loss function and optimizer
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=1e-4)
然后,我們可以開始訓練模型。在每個epoch中,我們使用訓練集進行訓練,并使用驗證集進行評估。在每個batch中,我們計算模型的輸出以及與標簽的差異(損失函數(shù)),并使用優(yōu)化器更新模型參數(shù)。
def train(model, dataloader, criterion, optimizer, device):
model.train()
train_loss = 0.0
for i, (inputs, labels) in enumerate(dataloader):
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
train_loss += loss.item() * inputs.size(0)
train_loss /= len(dataloader.dataset)
return train_loss
def evaluate(model, dataloader, criterion, device):
model.eval()
val_loss = 0.0
with torch.no_grad():
for inputs, labels in dataloader:
inputs = inputs.to(device)
labels = labels.to(device)
outputs = model(inputs)
loss = criterion(outputs, labels)
val_loss += loss.item() * inputs.size(0)
val_loss /= len(dataloader.dataset)
return val_loss
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = HRNet().to(device)
num_epochs = 50
for epoch in range(num_epochs):
train_loss = train(model, train_dataloader, criterion, optimizer, device)
val_loss = evaluate(model, val_dataloader, criterion, device)
print(f'Epoch {epoch+1:02}/{num_epochs}, Train Loss: {train_loss:.4f}, Val Loss: {val_loss:.4f}')
- 模型預測
在訓練完成后,我們可以使用訓練好的模型進行預測。下面是一個使用訓練好的HRNet模型進行單張圖像預測的示例代碼。文章來源:http://www.zghlxwxcb.cn/news/detail-430187.html
def predict(model, img_path):
model.eval()
img = cv2.imread(img_path)
h, w, _ = img.shape
scale_h = 256 / h
scale_w = 192 / w
img = cv2.resize(img, (192, 256))
img = img.astype(np.float32) / 255.0
img = (img - np.array([0.485, 0.456, 0.406])) / np.array([0.229, 0.224, 0.225])
img = np.transpose(img, (2, 0, 1))
img = np.expand_dims(img, axis=0)
img = torch.from_numpy(img).to(device)
with torch.no_grad():
output = model(img)
output = output.cpu().numpy()[0]
output[:, 0] /= scale_w
output[:, 1] /= scale_h
return output
model_path = 'hrnet.pth'
model = HRNet().to(device)
model.load_state_dict(torch.load(model_path))
output = predict(model, 'test.jpg')
在預測中,我們首先讀取測試圖像,并將其縮放到網(wǎng)絡輸入尺寸。然后,我們將圖像轉化為Tensor類型,并進行歸一化處理。接著,我們使用訓練好的模型進行預測,并將輸出結果進行反縮放,得到最終的關鍵點坐標。文章來源地址http://www.zghlxwxcb.cn/news/detail-430187.html
到了這里,關于行為識別 Activity Recognition的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!