-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathdecode_pose.py
136 lines (121 loc) · 6.47 KB
/
decode_pose.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import math
from keypoints import poseChain, partIds, partNames
from decode_utils import clamp, addVectors, getImageCoords, getOffsetPoint
parentChildrenTuples = []
for joint_name in poseChain:
parent_joint_name = joint_name[0]
child_joint_name = joint_name[1]
parentChildrenTuples.append([partIds[parent_joint_name], \
partIds[child_joint_name]])
''''
parentChildrenTuples = poseChain.map(
([parentJoinName, childJoinName]): NumberTuple =>
([partIds[parentJoinName], partIds[childJoinName]]));
'''
parentToChildEdges = []
for joint_id in parentChildrenTuples:
parentToChildEdges.append(joint_id[1]) #child_joint_id
'''
const parentToChildEdges: number[] =
parentChildrenTuples.map(([, childJointId]) => childJointId);
'''
childToParentEdges = []
for joint_id in parentChildrenTuples:
childToParentEdges.append(joint_id[0]) #child_joint_id
'''
const childToParentEdges: number[] =
parentChildrenTuples.map(([
parentJointId,
]) => parentJointId);
'''
def getDisplacement(edgeId, point, displacements):
numEdges = int(displacements.shape[2] / 2)
point_x = int(point['x'])
point_y = int(point['y'])
y = displacements[point_y][point_x][edgeId]
x = displacements[point_y][point_x][numEdges+edgeId]
return {'y':y, 'x':x}
def getStridedIndexNearPoint(point, outputStride, height, width):
return {'y':clamp(round(float(point['y']) / float(outputStride)), 0, height - 1), \
'x':clamp(round(float(point['x']) / float(outputStride)), 0, width - 1)}
'''
* We get a new keypoint along the `edgeId` for the pose instance, assuming
* that the position of the `idSource` part is already known. For this, we
* follow the displacement vector from the source to target part (stored in
* the `i`-t channel of the displacement tensor).
'''
def traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId,
scoresBuffer, offsets, outputStride, displacements):
height, width, numberScores = scoresBuffer.shape
#Nearest neighbor interpolation for the source->target displacements.
#最近邻插值(Nearest Neighbor interpolation)
sourceKeypointIndices = getStridedIndexNearPoint(sourceKeypoint['position'], \
outputStride, \
height, \
width)
displacement = getDisplacement(edgeId, sourceKeypointIndices, displacements)
displacedPoint = addVectors(sourceKeypoint['position'], displacement)
displacedPointIndices = getStridedIndexNearPoint(displacedPoint, \
outputStride, \
height, \
width)
x = int(displacedPointIndices['x'])
y = int(displacedPointIndices['y'])
offsetPoint = getOffsetPoint(y, x, targetKeypointId, offsets)
score = scoresBuffer[y][x][targetKeypointId]
targetKeypoint = addVectors( \
{'x': displacedPointIndices['x'] * outputStride, 'y': displacedPointIndices['y'] * outputStride}, \
{'x': offsetPoint['x'], 'y': offsetPoint['y']})
return {"position": targetKeypoint, \
"part": partNames[targetKeypointId], \
"score":score}
'''
* Follows the displacement fields to decode the full pose of the object
* instance given the position of a part that acts as root.
*
* @return An array of decoded keypoints and their scores for a single pose
'''
def decodePose(root, scores, offsets, outputStride, displacementsFwd, displacementsBwd):
numParts = scores.shape[2]
numEdges = len(parentToChildEdges)
#const instanceKeypoints: Keypoint[] = new Array(numParts);
instanceKeypoints = []
for i in range(numParts):
keypoint = {'position':{'x':0, 'y':0}, 'part':'null', 'score':0.0}
instanceKeypoints.append(keypoint)
#Start a new detection instance at the position of the root.
rootPart, rootScore = root['part'], root['score']
rootPoint = getImageCoords(rootPart, outputStride, offsets)
id = rootPart['id']
instanceKeypoints[id] = {'position':rootPoint, 'part':partNames[id], 'score':rootScore}
#Decode the part positions upwards in the tree, following the backward displacements.
for edge in reversed(range(numEdges)):
sourceKeypointId = parentToChildEdges[edge]
targetKeypointId = childToParentEdges[edge]
if instanceKeypoints[sourceKeypointId]['score'] > 0.0 \
and math.isclose(instanceKeypoints[targetKeypointId]['score'], 0.0, rel_tol=1e-9) is True:
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge,
instanceKeypoints[sourceKeypointId],
targetKeypointId,
scores,
offsets,
outputStride,
displacementsBwd)
# Decode the part positions downwards in the tree, following the forward
#displacements.
for edge in range(numEdges):
sourceKeypointId = childToParentEdges[edge]
targetKeypointId = parentToChildEdges[edge]
#if instanceKeypoints[sourceKeypointId] is not None and instanceKeypoints[targetKeypointId] is None:
if instanceKeypoints[sourceKeypointId]['score'] > 0.0 \
and math.isclose(instanceKeypoints[targetKeypointId]['score'], 0.0, rel_tol=1e-9) is True:
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge, \
instanceKeypoints[sourceKeypointId], \
targetKeypointId, \
scores, \
offsets, \
outputStride, \
displacementsFwd)
return instanceKeypoints