우선 미디어파이프를 통해 여러 영상을 돌리면서 각 관절 데이터를 저장
저장은 x[video][frame][joint], y[video][frame][joint]의 형태로 저장했으며
x[1][30][2]는 두번째 영상의 31번째 프레임의 2번관절에 대한 x축 좌표가 저장되어있다.
def angle_of_vectors(vec1,vec2):
a,b,c,d=vec1[0],vec1[1],vec2[0],vec2[1]
dotProduct = a*c + b*d
modOfVector1 = math.sqrt( a*a + b*b)*math.sqrt(c*c + d*d)
angle = dotProduct/modOfVector1
angleInDegree = math.degrees(math.acos(angle))
return angleInDegree
# 12-11 어깨, 12-24 왼옆구리, 11-23 오른옆구리, 24-23 허리, 24-26 왼허벅 23-25 오른허벅
# 26-28 왼종아리, 25-27 오른종아리, 28-32 왼발등, 27-31 오른발등
# 12-14 왼팔, 11-13 오른팔, 14-16 왼전완, 13-15 오른전완
matchIndex=[[12,11],[12,24],[11,23],[24,23],[24,26],[23,25],[26,28],[25,27],[28,32],[27,31],
[12,14],[11,13],[14,16],[13,15]]
# x[0][0~f][djRo]
# x[1][0~f][djRo]
#x[video][frame][angle]
#angle = [[[a1...a14], frame], ... video]
angle = [[], [], [], [], [], [], []]
for i in range(videoNum):
for frameNum in range(videoEachFrame[i]):
temp = []
for idx in range(len(matchIndex)):
temp.append(angle_of_vectors([x[i][frameNum][matchIndex[idx][0]],y[i][frameNum][matchIndex[idx][0]]],[x[i][frameNum][matchIndex[idx][1]],y[i][frameNum][matchIndex[idx][1]]]))
angle[i].append(temp)
저장된 데이터를 관절끼리 묶어서(12번-11번 관절이면 어깨)
관절들의 각도를 계산하여 다시 저장해두었다 (만약 서있는 위치가 다르면 좌표로 할 경우 다른 자세라고 판단)
(하지만, 각도로 한다면 같은 자세로 다른 위치에 서있더라도 같은 자세라고 판단하고 dtw matching이 잘 될것)
이를 dtw에 적용시켜서 나오는 table을 저장했으며 (관절 묶은 데이터가 14개라 14번)
14개의 테이블을 평균을 구하여 다시 dtw path를 출력하였다.
while i>0 or j>0:
a= totalCostMap[i-1,j-1]
b= totalCostMap[i,j-1]
c= totalCostMap[i-1,j]
if min(a,b,c)==a:
i=i-1
j=j-1
elif min(a,b,c)==b:
j=j-1
elif min(a,b,c)==c:
i=i-1
path.append((i,j))
path.reverse()
원래라면 2d data에 대해 dtw를 수행하지만
관절 데이터 14개를 묶어서 한 번에 dtw를 수행할 수 있도록 하여 차원이 하나 더 늘어난 데이터에 대해 처리를 한 것이다.
왜 이렇게 하였는가.
만약 팔에 대해, 다리에 대해, .... 따로 dtw를 시도한다면
팔은 두 영상에 대해 1-3 frame matching, 다리는 1-10 frame matching이라면,
첫 프레임이 어떤 프레임과 매칭된다고 판단하기 힘들것이다.
우리는 차원을 늘려 팔,다리 등등 모든 데이터에 대해 수행하기에 그런 일이 없다.
매칭된 path를 통해 두 영상에서 잘 매칭되었나 확인하기 위해 해당 프레임의 영상 데이터를 뽑아봤다.
for i in range(1,3):
video = "../video/front%d.mp4" % (i)
cap = cv2.VideoCapture(video)
frame=0
while cap.isOpened():
success, image = cap.read()
if not success:
break
for j in range(len(path)):
if i==1 and (frame == path[j][0]):
cv2.imwrite("../image/%d[1].jpg" % (j), image)
break
elif i==2 and (frame == path[j][1]):
cv2.imwrite("../image/%d[2].jpg" % (j), image)
break
frame+=1
cap.release()
서로 다른 영상이지만 매칭된 프레임데이터를 보면 아주 비슷한 자세를 취하고 있는 것을 확인할 수 있다.
또한 좌표데이터가 아닌 앵글데이터를 사용했기에 서있는 좌표에 다르더라도 잘 매칭이 되고 있다.
전체 코드
[비공개처리]
'Project > DTW' 카테고리의 다른 글
DTW란? Dynamic Time Warping하며 학습 + 내가 생각한 알고리즘 (0) | 2023.01.11 |
---|---|
using dynamic time warping in 3d data (0) | 2022.10.30 |
Dynamic Time Warping(DTW) study (0) | 2022.10.13 |