Check morphing the pelvis

Dear AnyBody community

I have a question regarding morphing the pelvis. I followed the tutorial 'Personalizing Your Model' and managed to morph both the (left and right) thigh and the shank. However, for the pelvis when I want to check the morphing, the scaled mesh and the target mesh do not overlay properly (similar to the problem noticed by max in Custom scaling of the pelvis? - #6 by toerholm).

Nevertheless, I already included


in the transformation.
I also read the following (Morphing of the pelvis - #3 by CDzialo) forum post but did not manage to solve my problem.

I included the morphing by adding 4 anyscripts:

HumanModel.Scaling.GeometricalScaling = {
  #include "PelvisScaling.any"
  #include "CheckPelvisMorphing.any"
  #include "FemurScaling.any" 
  #include "CheckFemurMorphing.any"
  #include "TibiaScaling.any"
  #include "CheckTibiaMorphing.any"


With PelvisScaling.any:

// Generic AnyBody bone created from a template mesh
#path SOURCE_PELVIS "pelvisammr2.stl"

// Target bone created from the same template mesh
#path TARGET_PELVIS "D:\AnyBody\gm-foot\PersonScaling\N19\Pelvis_SSM.stl"

#define CUSTOM_SCALING_PelvisSeg

PelvisSeg = {
  #include "ScaleFunctionPelvis2.any"
  AnyFunTransform3D &ScaleFunction = MyScalingFunctionPelvis;


// Finding source and target landmarks automatically from provided STL of the same topoolgy

  AnyFile src = SOURCE_PELVIS;
  AnyFile trg = TARGET_PELVIS;
  AnyInt size = STL_Size(src, 1);                          // get size of the stl 
  AnyInt VertNum = 1000;                                   // specify number of landmarks to be extracted automatically
  //AnyInt VertNum = 10000;
  AnyInt vertices = iarr(1,VertNum)*floor(size[0]/VertNum);// evenly space landmarks in the index field
  AnyMatrix P0 = STL_Vertices(src, vertices , 1);          // extract vertices with given indices
  AnyMatrix P1 = 0.001*STL_Vertices(trg, vertices , 1);    // conversion from mm to m
//  AnyFunTransform3D &TSeg2ScaleFrame = Main.HumanModel.Scaling.GeometricalScaling.PelvisSeg.TSeg2ScaleFrame;   
  //Linear Affine transformation
  AnyFunTransform3DLin2 reg = 
    // Points0 = .Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.PelvisSeg.Scale_Trunk_Pelvis.ScaleAfterInterfaceMorphingDef.Scale.T0(.P0);
    // Points0 = .TSeg2ScaleFrame(.P0);
    Points0 = .TSeg2ScaleFrame(.P0);
    Points1 = .P1;
  // Non-linear transformation --> Radial Basis Functions (RBF)
  // Need to optimize these settings
  AnyFunTransform3DRBF rbf = 
    PreTransforms = {&.reg};
    RBFDef.Type = RBF_Triharmonic;  
    PolynomDegree = 1;
    Points0 = .reg.Points0;
    Points1 = .reg.Points1;
    BoundingBoxOnOff = On;
    BoundingBox.Type = BB_Cartesian;
    BoundingBox.DivisionFactorXYZ ={1,1,1}*3;
  //STL To STL
  //Morphing using the surface information --> will deform all related soft tissue attachment points
  AnyFunTransform3DSTL STLTransform =
    PreTransforms = {&.rbf};
    PolynomDegree = 1;
    RBFDef.Type = RBF_Triharmonic;
    AnyFixedRefFrame Input = {
      AnySurfSTL SourceSurf = {
        FileName = ...src;
        ScaleXYZ = {1, 1, 1};
        AnyFunTransform3D&pre = ...TSeg2ScaleFrame;
      AnySurfSTL TargetSurf = {
        FileName = ...trg;
        ScaleXYZ = 0.001*{1, 1, 1};
    SurfaceObjects0 = {&Input.SourceSurf};
    SurfaceObjects1 = {&Input.TargetSurf};
    NumPoints = 1500;
    BoundingBox.ScaleXYZ = {2,2,2};
    BoundingBox.DivisionFactorXYZ = {1,1,1};
    BoundingBoxOnOff = On;
  AnyFunTransform3DLin2 ReverseTransform = 
    Points0 = .reg.Points1;
    Points1 = .reg.Points0;
  AnyFunTransform3DIdentity MyScalingFunctionPelvis = {
    PreTransforms = {&.STLTransform, &.ReverseTransform};

and finally to check the morphing CheckPelvisMorphing.any

Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.PelvisSeg = {

  AnyRefNode targetstl = {
    AnyFunTransform3DIdentity RegistrationTranform = {
      PreTransforms = {&Main.HumanModel.Scaling.GeometricalScaling.PelvisSeg.ReverseTransform,

  AnyDrawSurf target_pelvis = {
    AnyFunTransform3D &reg = .RegistrationTranform;    

I added the used pelvis stl (pelvisammr2.stl).
I also tried to use the stl provided by Christine in following forum post (Morphing of the pelvis - #3 by CDzialo). However, then I ended up with a completely wrong morphed pelvis (see below):

Is there anyone who experienced a similar problem before? Any ideas how I could solve this problem?

Kind regards
Kate (2.7 MB)

Hi Kate,

The problem might be that when looking for landmarks using the closest point method on thin geometries could lead to strange selection. I typically avoid using STL step for pelvis bone and for other thin structures. Could you please try to use Christine's solution and not use STL for morphing? Use this:

AnyFunTransform3DIdentity MyScalingFunctionPelvis = {
PreTransforms = {&.RBFTransform, &.ReverseTransform};

Secondly, I know that you can generate a fixed topology STLs (like Jan did), and then you could also use vertices as landmarks since they would match the source. This should also give a more stable and regular solution.

Kind regards,

Dear Pavel

Thank you for your reply! I included the rbf transform in my scaling function.
However, my main problem is that when I try to check whether the pelvis is morphed correctly, the scaled mesh and target mesh do not overlay properly. I want to use the transformation (to move the pelvis target to the location of the pelvis in the model) for something else as well. I use the 'CheckPelvisMorphing.any', as a check for this transformation and therefore, I cannot just compare the pelvis morphologies. Would you have any suggestions for this problem?

Kind regards

Hi Kate,

Seems that we talk about two different issues. As I can see - there is a problem with the morphing at the first instance. Having a fixed topology morphing scheme improves the scaling process itself. And using RBF should help scaling of the pelvis.

Secondly, if you want to see the morphing - create the following node in your segmental ref. frame. You can then add an AnyDrawSurf or AnyDrawSTL object directly to this node and your surfaces should align for visual check:

AnyRefNode CT = {
  AnyFixedRefFrame Global={
    AnyRefNode Ref1 = {
      // points in CT ref. frame 
      AnyFloat u0 = Points[0];//target
      AnyFloat ux1 = Points[1];//target
      AnyFloat ux2 = Points[2];//target
      sRel = u0;  
      ARel = RotMat(u0,ux1,ux2);\
    AnyRefNode Ref2 = {
      // points in segmental ref. frame after scaling 
      AnyFloat u0 = Points[0];  //scaled source
      AnyFloat ux1 = Points[1]; //scaled source
      AnyFloat ux2 = Points[2]; //scaled source
      sRel = u0;  
      ARel = RotMat(u0,ux1,ux2);
  AnyFunTransform3DLin CT2ANY =  {
    ScaleMat = .Global.Ref2.ARel * .Global.Ref1.ARel';
    Offset = .Global.Ref2.sRel * ScaleMat - .Global.Ref1.sRel;
  sRel = CT2ANY({0.0,0.0,0.0});
  ARel = RotMat(CT2ANY({0.0,0.0,0.0}),CT2ANY({1.0,0.0,0.0}),CT2ANY({0.0,1.0,0.0}));

  AnyDrawSurf MY_CT_SURFACE = {…};

Using the inverse transformation from the pipeline will not perfectly work, because you will try aligning non-scaled points with the source pointcloud (which has a different shape).

I hope this helps.

Kind regards,

Hi Kate,

Heres a little update as we have started investigating what is going on and we think we are closing in on the problem.
Our hypothesis is that the morphing is mixed between the leg pelvis and the trunk pelvis.

The model is made up of multiple different bodymodels that are put together and the TLEM2 dataset includes a pelvis while the lumbar model also includes a pelvis. For completeness there is a option to switch between the two pelvis' dependent on what users are interested in - one might be keen on the complete TLEM2 and others might be interested in more detailed lumbar spine.

We are still looking into the issue to see if we can give a more elaborate answer, but we believe that some of your points used the Scale_Trunk_Pelvis where they should have used the Scale_Leg_Pelvis function instead.
Here is an image where I switched the scale function on the CT.Ref2 u0,ux1, ux2 points.

Here is a snippet of what we changed:

AnyRefNode Ref2 = {
  AnyFloat u0 = ...Scale_Leg_Pelvis(p0);  //scaled source
  AnyFloat ux1 = ...Scale_Leg_Pelvis(px1); //scaled source
  AnyFloat ux2 = ...Scale_Leg_Pelvis(px2); //scaled source

We will keep you posted when we can give a more full answer

Best regards,

Dear Bjorn

Sorry for the late reply!
Indeed switching the Scale to Scale_Leg_Pelvis solved the problem. Thank you!

Meanwhile, I also tried to morph the feet. I made sure that the target mesh was in correspondence with the AnyBody mesh and used all the vertices as landmarks. However, the feet do not morph well (see figure below) I used the same procedure as mentioned in my first post. Would anyone have suggestions to improve the morphing process?

Kind regards
Kate Duquesne