-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Neil Lawrence
committed
Mar 16, 2015
1 parent
0e55437
commit 05cc96e
Showing
61 changed files
with
3,153 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,39 @@ | ||
# hgplvm | ||
Hierarchical Gaussian process latent variable model. | ||
|
||
## Hierarchical Gaussian Process Latent Variable Model - MATLAB Software | ||
|
||
# Hierarchical GP-LVM Software | ||
|
||
This page describes examples of how to use the hierarchical Gaussian process latent variable model Software (HGPLVM). | ||
|
||
The hierarchical GP-LVM allows you to create hierarchies of Gaussian process models. With the toolbox two hierarchy examples are given below. | ||
|
||
### Examples | ||
|
||
Two examples of hierarchical models are provided with the code, the first is an example where two interacting subjects are jointly model. Two subjects from the <a href="http://mocap.cs.cmu.edu">CMU Mocap data base</a> approach each other and 'high five'. The hierarchy models the subjects separately and jointly. It can be run with the command | ||
|
||
```matlab | ||
>> demHighFive1 | ||
``` | ||
|
||
A visualisation of the result, including points that have been propagated through the hierarchy is given below. | ||
|
||
<center><img src="demHighFive_talk.png"><br> | ||
|
||
Joint visualisation of the two subjects that 'high five'. The points A, B, C, D, E, F, G and H have been propagated through the hierarchy and are shown on the right. Grey scale visualisations in the latent space have not been shown to keep the smaller plots clear.</center> | ||
|
||
A second example involves a subject modelled running and walking. In this case the separate limbs of the subject are split into a hierarchy as shown below. | ||
|
||
<center><img src="stickHierarchy.png"><br>Hierarchical decomposition of the skeleton. The limbs and abdomen are leaf nodes, behind which we build a hierarchical structure.</center> | ||
|
||
This example can be reconstructed with | ||
```matlab | ||
>> demWalkRun1 | ||
``` | ||
|
||
Results of applying the hierarchical structure to a combined data set of a run and a walk, using two root nodes, one for the run and one for the walk, are shown below. | ||
|
||
<center><img src="demWalkRun_portrait.png"><br> | ||
Visualisation of a walk and run jointly using hierarchical structures. Again several points have been propagated through the hierarchy. | ||
</center> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
function xyz = acclaim2xyzHierarchical(skel, channels, visIndex) | ||
|
||
% ACCLAIM2XYZHIERARCHICAL Compute XYZ values given skeleton structure and channels. | ||
% FORMAT | ||
% DESC Converts a series of joint angles (channel data) into xyz | ||
% coordinates for the given skeleton. | ||
% ARG skel : The skeleton being animated. | ||
% ARG channels : The channel data for this frame of animation. | ||
% ARG visIndex : visIndex indicates the index of the current subskel node. | ||
% RETURN xyz : the data structure containing the xyz value and rotation | ||
% matrix for each joint in the skeleton. | ||
% | ||
% COPYRIGHT : Andrew J. Moore and Neil D. Lawrence, 2006, 2007 | ||
% | ||
% HGPLVM | ||
|
||
global dependencyVisData; | ||
|
||
%/~ | ||
% hasDependency = 0; | ||
% isMaster = 0; | ||
% dependencyId = 0; | ||
% %check to see if root node has a dependency. | ||
% for i=1:size(dependencyVisData) | ||
% if (strcmp(skel.tree(1).name, dependencyVisData(i).name) | ||
% %check to see if this is a master or a dependent. | ||
% if dependencyVisData(i).masterNodeIndex == visIndex | ||
% isMaster = 1; | ||
% dependencyId = i; | ||
% else | ||
% xyzStruct(1).rot = dependencyVisData(i).rot; | ||
% xyzStruct(1).xyz = dependencyVisData(i).xyz; | ||
% hasDependency = 1; | ||
% end | ||
% end | ||
% end | ||
% if ~hasDependency | ||
%~/ | ||
rotVal = skel.tree(1).orientation; | ||
for i = 1:length(skel.tree(1).rotInd) | ||
rind = skel.tree(1).rotInd(i); | ||
if rind | ||
rotVal(i) = rotVal(i) + channels(rind); | ||
end | ||
end | ||
xyzStruct(1).rot = rotationMatrix(deg2rad(rotVal(1)), ... | ||
deg2rad(rotVal(2)), ... | ||
deg2rad(rotVal(3)), ... | ||
skel.tree(1).axisOrder); | ||
|
||
xyzStruct(1).xyz = skel.tree(1).offset; | ||
%/~ | ||
% end | ||
%~/ | ||
|
||
for i = 1:length(skel.tree(1).posInd) | ||
pind = skel.tree(1).posInd(i); | ||
if pind | ||
xyzStruct(1).xyz(i) = xyzStruct(1).xyz(i) + channels(pind); | ||
end | ||
end | ||
xyzStruct(1) = checkForDependency(1, visIndex, xyzStruct(1)); | ||
|
||
|
||
for i = 1:length(skel.tree(1).children) | ||
ind = skel.tree(1).children(i); | ||
xyzStruct = getChildXyz(skel, xyzStruct, ind, channels); | ||
end | ||
xyz = reshape([xyzStruct(:).xyz], 3, length(skel.tree))'; | ||
|
||
function xyzStruct = getChildXyz(skel, xyzStruct, ind, channels) | ||
|
||
% GETCHILDXYZ | ||
|
||
parent = skel.tree(ind).parent; | ||
children = skel.tree(ind).children; | ||
rotVal = zeros(1, 3); | ||
for j = 1:length(skel.tree(ind).rotInd) | ||
rind = skel.tree(ind).rotInd(j); | ||
if rind | ||
rotVal(j) = channels(rind); | ||
else | ||
rotVal(j) = 0; | ||
end | ||
end | ||
tdof = rotationMatrix(deg2rad(rotVal(1)), ... | ||
deg2rad(rotVal(2)), ... | ||
deg2rad(rotVal(3)), ... | ||
skel.tree(ind).order); | ||
|
||
torient = rotationMatrix(deg2rad(skel.tree(ind).axis(1)), ... | ||
deg2rad(skel.tree(ind).axis(2)), ... | ||
deg2rad(skel.tree(ind).axis(3)), ... | ||
skel.tree(ind).axisOrder); | ||
torientInv = rotationMatrix(deg2rad(-skel.tree(ind).axis(1)), ... | ||
deg2rad(-skel.tree(ind).axis(2)), ... | ||
deg2rad(-skel.tree(ind).axis(3)), ... | ||
skel.tree(ind).axisOrder(end:-1:1)); | ||
xyzStruct(ind).rot = torientInv*tdof*torient*xyzStruct(parent).rot; | ||
xyzStruct(ind).xyz = xyzStruct(parent).xyz + (skel.tree(ind).offset*xyzStruct(ind).rot); | ||
|
||
xyzStruct(ind) = checkForDependency(ind, visIndex, xyzStruct(ind)); | ||
|
||
for n = 1:length(children) | ||
cind = children(n); | ||
xyzStruct = getChildXyz(skel, xyzStruct, cind, channels); | ||
end | ||
|
||
end | ||
|
||
function xyzStruct = checkForDependency(ind, visIndex, xyzStruct) | ||
|
||
% CHECKFORDEPENDENCY | ||
|
||
%/~ | ||
%below prob shite | ||
%0 = no dependency | ||
%1 = dependency, is dependent | ||
%2 = dependency, is master | ||
%~/ | ||
for k=1:length(dependencyVisData) | ||
if (strcmp(skel.tree(ind).name, dependencyVisData(k).name)) | ||
%check to see if this is a master or a dependent. | ||
if dependencyVisData(k).masterNodeIndex == visIndex | ||
% It is master. | ||
dependencyVisData(k).rot = xyzStruct.rot; | ||
dependencyVisData(k).xyz = xyzStruct.xyz; | ||
else | ||
%hot fix, but question is, why might the dependency master info be | ||
%requested before is has been assigned? | ||
if ~isempty(dependencyVisData(k).rot) | ||
% It is a dependent | ||
xyzStruct.rot = dependencyVisData(k).rot; | ||
xyzStruct.xyz = dependencyVisData(k).xyz; | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
function [subskel, channelIndices] = acclaimGetSubSkel(skel, newRootName, children, stoplist) | ||
|
||
% ACCLAIMGETSUBSKEL Gets a sub-skeleton from a larger acclaim format skeleton. | ||
% FORMAT | ||
% DESC gets a sub-skeleton from a larger skeleton given the | ||
% original skeleton, the root of the new skeleton and the joints | ||
% from the root to be included in the sub-skeleton. | ||
% ARG skel : Original skeleton to take a subskel from. | ||
% ARG newRootName : Name of the joint from skel which will be the | ||
% root of the new subskel. | ||
% ARG children : Cell array containing the names of joints/bones | ||
% below newRootName which are to be included in the subskel (omitting this will add all children of newRootName). | ||
% ARG stoplist : Cell array containing the names of joints/bones. If any | ||
% joint is explored which has a name on the stoplist, then this | ||
% joint and its child joints are not added to the new subskel. | ||
% RETURN subkel : the sub-skeleton as specificed by the given | ||
% arguments. | ||
% RETURN channelIndices : the relevant channel indices associated with the | ||
% sub-skeleton. | ||
% | ||
% COPYRIGHT : Andrew J. Moore and Neil D. Lawrence, 2006, 2007 | ||
% | ||
% SEEALSO : skelReverseLookup | ||
|
||
% HGPLVM | ||
|
||
%/~ | ||
% Andy, this is based on your skelGetSubSkel -- Neil | ||
%~/ | ||
IND_ROOT = 1; %assume the index of a root node is always 1. | ||
|
||
if nargout>1 | ||
getSubChannels = 1; | ||
channelIndices = []; | ||
else | ||
getSubChannels = 0; | ||
end | ||
if nargin < 4 | ||
stoplist = {}; | ||
elseif ~iscell(stoplist) | ||
error('The ''stoplist'' parameter must be passed as a cell array.'); | ||
end | ||
if nargin > 2 | ||
if ~iscell(children) | ||
error('The ''children'' parameter must be passed as a cell array.'); | ||
end | ||
else | ||
children = {}; | ||
end | ||
|
||
%Copy over key skel info | ||
subskel.type = skel.type; | ||
|
||
jointIndex = skelReverseLookup(skel, newRootName); | ||
newIndex = 1; %global store of the current flat index of the subskel tree array. | ||
|
||
%If the children parameter is defined, prune from the skel any child indices not | ||
%in children. | ||
if size(children, 1) > 0 | ||
for n=1:length(children) | ||
childJointIndices(n) = skelReverseLookup(skel, children(n)); | ||
end | ||
count = 1; | ||
for m=1:length(skel.tree(jointIndex).children) | ||
bJointMatch = 0; | ||
for n=1:length(childJointIndices) | ||
if childJointIndices(n) == skel.tree(jointIndex).children(m) | ||
bJointMatch = 1; | ||
end | ||
end | ||
if bJointMatch | ||
prunedChildren(count) = skel.tree(jointIndex).children(m); | ||
count = count + 1; | ||
end | ||
end | ||
skel.tree(jointIndex).children = prunedChildren; | ||
end | ||
|
||
%if the root of the subskel is not the root of the original skel, need to | ||
%calculate the position offset of the new subskel from the original root | ||
if not(strcmp(newRootName,'root')) | ||
%calculate the cumulative offset of the root of the subskel from the | ||
%original skel root. | ||
rootOffset = skel.tree(jointIndex).offset; | ||
%BEGIN - calculate the offset in relation to the whole skel. should now | ||
%be done at run time - | ||
%nodeIndex = skel.tree(jointIndex).parent; | ||
%while nodeIndex > 0 | ||
% rootOffset = rootOffset + skel.tree(nodeIndex).offset; | ||
% nodeIndex = skel.tree(nodeIndex).parent; | ||
%end | ||
%END | ||
subskel.tree(IND_ROOT) = skel.tree(jointIndex); | ||
subskel.tree(IND_ROOT).offset = rootOffset; | ||
subskel.tree(IND_ROOT).orientation = skel.tree(IND_ROOT).orientation; | ||
%need to add in the posInd (x,y,z), setting to the original roots value | ||
subskel.tree(IND_ROOT).posInd = skel.tree(IND_ROOT).posInd; | ||
else | ||
subskel.tree(IND_ROOT) = skel.tree(IND_ROOT); | ||
end | ||
%copy over position data from orig skel root to the new subskel root | ||
if getSubChannels | ||
channelIndices = [channelIndices 1:3]; | ||
nextChanIndex = 4; | ||
end | ||
|
||
|
||
%Note that the rotation indices attribute, rotInd, of each bone contains | ||
%the indices of the channel data for each DoF. | ||
|
||
recurseTree(jointIndex, 0, true); %set parent index to the orig skel root. | ||
|
||
function z = recurseTree(skelIndex, subskelParentIndex, continueRecursion) | ||
%skelIndex - index in skel of the current node to copy. | ||
%subskelParentIndex - the index in subskel of this node's parent. | ||
if nargin < 3 | ||
continueRecursion = true; | ||
end | ||
thisNodeIndex = newIndex; | ||
|
||
%need to re calculate the parent and child indices | ||
if subskelParentIndex > 0 | ||
subskel.tree(thisNodeIndex) = skel.tree(skelIndex); | ||
subskel.tree(thisNodeIndex).parent = subskelParentIndex; % re-set this node's parent | ||
end | ||
if getSubChannels | ||
%copy the old channel data over, and update the rotInd's to the | ||
%new positions in the subchannels matrix. | ||
for i = 1:length(subskel.tree(thisNodeIndex).rotInd) | ||
if subskel.tree(thisNodeIndex).rotInd(i) | ||
channelIndices = [channelIndices subskel.tree(thisNodeIndex).rotInd(i)]; | ||
subskel.tree(thisNodeIndex).rotInd(i) = nextChanIndex; | ||
nextChanIndex = nextChanIndex + 1; | ||
end | ||
end | ||
end | ||
|
||
newIndex = newIndex + 1; | ||
numChildren = length(skel.tree(skelIndex).children); | ||
unblockedChildCounter = 1; | ||
%clear the current children copied from subskel, and recalulate the | ||
%new child indicies | ||
subskel.tree(thisNodeIndex).children = []; | ||
% if continueRecursion if false, recurse through the children. | ||
if continueRecursion | ||
for i = 1:numChildren | ||
childSkelIndex = skel.tree(skelIndex).children(i); | ||
if inStoplist(skel.tree(childSkelIndex).name) | ||
% Find children, but don't recurse through them. | ||
recurseFurther = false; | ||
else | ||
recurseFurther = true; | ||
end | ||
childSubskelIndex = recurseTree(childSkelIndex, ... | ||
thisNodeIndex, ... | ||
recurseFurther); | ||
subskel.tree(thisNodeIndex).children(unblockedChildCounter) = ... | ||
childSubskelIndex; | ||
unblockedChildCounter = unblockedChildCounter + 1; | ||
end | ||
end | ||
z = thisNodeIndex; %return the id of this node, used for setting child id's on parent. | ||
end | ||
|
||
%function inStoplist | ||
%newRootName - the name of a joint | ||
%Returns 0 or 1 to indicate if jointName is in the stoplist | ||
function result = inStoplist(jointName) | ||
result = false; | ||
for i = 1:length(stoplist) | ||
if strcmp(jointName, stoplist(i)) | ||
result = true; | ||
return; | ||
end | ||
end | ||
|
||
end | ||
|
||
end | ||
|
||
|
||
|
||
|
||
|
||
|
Oops, something went wrong.