Hands - getting started

Hey, I’m just getting started with WrapX. Very cool! I’m working with hand poses including curled fingers and I’m wondering if there are any examples or tutorials to help me get going.

My initial tests make me think I need to place control points along the inner and outer surfaces of the fingers to help maintain the volume and prevent flattening and “smushing”. Any tips would be greatly appreciated.

Thanks for any info!

  • Jance

I’m trying to figure out (using the simpleWrap example) how to load a set of control points for the baseMesh from a file and then manually set the corresponding points for a scan. My goal is to wrap the same hand pose base mesh to several differently posed hand scans.

I made a little script to set and save the base mesh points, and I can load them in, but I don’t know how to have it show me the split window so I have the visual reference to place the scan points.

Here’s my hacked script so far (no, I’m not much of a coder at all :frowning: ). I’ve commented out the sections I don’t need at the moment.

Thanks for any help!

  • Jance
import wrap

# 1. Loading Basemesh
print "Loading basemesh..."
basemeshFileName = wrap.openFileDialog("Select Basemesh",filter = "OBJ-file (*.obj)",dir = wrap.demoModelsPath)
basemesh = wrap.Geom(basemeshFileName)
print "OK"

# 2. Loading Scan
print "Loading scan..."
scanFileName = wrap.openFileDialog("Select Scan",filter = "OBJ-file (*.obj)",dir = wrap.demoModelsPath)
scaleFactor = 1000
scan = wrap.Geom(scanFileName,scaleFactor = scaleFactor)
scan.wireframe = False
print "OK"

# print "Loading texture..."
# textureFileName = wrap.openFileDialog("Select Scan\'s Texture",filter = "Image (*.jpg *.png *.bmp *.tga)",dir = wrap.demoModelsPath)
# if textureFileName is not None:
#    scan.texture = wrap.Image(textureFileName)
#    scan.texture.show()
#    print "OK"
# else:
#    print "No texture set"

# 3. Rigid Alignment
print "Rigid alignment..."
(pointsScan, pointsBasemesh) = wrap.selectPoints(scan,basemesh)
rigidTransformation = wrap.rigidAlignment(basemesh,pointsBasemesh,scan,pointsScan,matchScale = True)
basemesh.transform(rigidTransformation)
basemesh.fitToView()
print "OK"

# 4. Non-rigid Registration
# print "Non-rigid Registration..."
# (controlPointsScan,controlPointsBasemesh) = wrap.selectPoints(scan,basemesh)
# freePolygonsBasemesh = wrap.selectPolygons(basemesh)
# basemesh = wrap.nonRigidRegistration(basemesh,scan,controlPointsBasemesh,controlPointsScan,freePolygonsBasemesh,minNodes = 15,initialRadiusMultiplier = 1.0,smoothnessFinal = 0.1,maxIterations = 20)
# print "OK"

# 4a. Load base control points from file - ja
print "Load base control points from file..."
fileName = wrap.openFileDialog("Open base control points file", filter = "TXT-file (*.txt)")
(controlPointsBasemesh) = wrap.loadPoints(fileName)

# 4b. Non-rigid Registration - ja
print "Non-rigid Registration..."
(controlPointsScan) = wrap.selectPoints(scan)
freePolygonsBasemesh = wrap.selectPolygons(basemesh)
basemesh = wrap.nonRigidRegistration(basemesh,scan,controlPointsBasemesh,controlPointsScan,freePolygonsBasemesh,minNodes = 15,initialRadiusMultiplier = 1.0,smoothnessFinal = 0.1,maxIterations = 20)
print "OK"

# 5. Subdivision
# print "Subdivision..."
# basemesh = wrap.subdivide(basemesh)
# print "OK"

# 6. Projection
print "Projection..."
disabledPolygons = wrap.selectPolygons(basemesh)
basemesh = wrap.projectMesh(basemesh,scan,maxRelativeDist = 1,disabledPolygonIndicesSrc = disabledPolygons)
print "OK"

# 7. Texture Transfer
# print "Texture transfer..."
# if scan.texture is not None:
#    basemesh.texture = wrap.transferTexture(scan,scan.texture,basemesh,(2048,2048),maxRelativeDist = 3)
#    basemesh.texture.extrapolate()
# print "OK"

# 8. Saving Result
print "Saving result..."
fileName = wrap.saveFileDialog("Save resulting model",filter = "OBJ-file (*.obj)")
basemesh.save(fileName,scaleFactor = 1.0 / scaleFactor)
if scan.texture is not None:
    textureFileName = wrap.saveFileDialog("Save resulting texture",filter = "Image (*.jpg *.png *.bmp *.tga)")
    basemesh.texture.save(textureFileName)
print "OK"

Hello Jance,

Sorry for late responce. After loading control points from file

(controlPointsBasemesh) = wrap.loadPoints(fileName)

you can display wrap.selectPoints dialog passing your loaded points there http://www.russian3dscanner.com/docs/WrapX/wrapDialogs.html#wrap.selectPoints

controlPointsScan, controlPointsBasemesh = wrap.selectPoints(scan,basemesh,pointsLeft = [], pointsRight = controlPointsBasemesh)

Thank you!

So I’ve been experimenting and trying to learn the best strategy for these hand poses. I started with a fair number of points along the outer knuckle features, then kept adding points to try to help the result, and then went very simple with just 5 points. Any recommendations on how to get good and consistent results with various fairly extreme hand poses would be greatly appreciated! I’m just not sure exactly what to expect. I’ll post some reference images of what I’ve been trying.

Thanks!

A reference image of using about 60 points.

An image showing using just 5 control points.

Starting with just 5 points, the results are actually pretty good, for the overall volume. But there are some shape problems, like the inner knuckle seams.
Also for instance, the polys for the fingernails slide off to the side a bit for the more curved fingers. I assume I need to add more control points to define the fingernails. But it seems to quickly become dozens and dozens of points, and I’m wondering if that’s the expected strategy.

Hello Jance,

It’s just a guess, I can not check it without a test data, but try to tune minNodes parameter of wrap.nonRigidRegistration (
http://www.russian3dscanner.com/docs/WrapX/wrapFunctions.html#wrap.nonRigidRegistration)

The optimization goes through 3-4 iterations, picking more and more control nodes (white dots) on each step. If first step ends up squeezing the basemesh, all the following steps will fail too. minNodes parameter defines how many control nodes are on the very first step. By default it is 10. I suggest to try it with values 50, 200, 500 and add 5-10 more points on inner seams to the existing 5 on the last screenshot.

If you still don’t have good result you can send me the test data so that I could try to come up with good parameters.

Great, I will try this. Thanks so much!

It seems like the maxIterations needs to be a higher number along with the minNodes. Does that sound right? Still experimenting…

Strange, minNodes should not correlate with maxIterations.

Can you please try Wrap 2.3 on the same data? The algorithm of Wrap 2.3 is slightly outdated and works slower but because of different algorithm it has some advantage for your particular task.

I will look at Wrap next! In the meantime, just passing along some results with WrapX and noodling minNodes and maxIterations.

Looking ahead to whatever solution provide the best resulting shapes, I’m wondering about things like keeping the fingernail polys in the right place, for instance, especially among multiple poses. Even in cases where the overall volume and silhouette look good, it seems that I need to keep adding control points for specific areas like fingernails. But then that’s kind of a rabbit hole and I end up with dozens of points.

Still learning!

Hello Jance,

I’ve made a couple of tests. Wrap 2.3 algorithm is definitely more suitable for this tast.

http://russian3dscanner.com/images/JancePreview02.jpg

First hand was wrapped with no problem on default presets. The secon one required me to set Final rigidness parameter to 0.35. It made result quite smooth but in some areas it did not match the shape of the scan close enough.

http://russian3dscanner.com/images/JancePreview03.jpg

After that I used WrapX to project geometry to match scan precisely.

http://russian3dscanner.com/images/JancePreview01.jpg

Interesting! I will dive into this. Thanks so much!

After your suggestion, I’ve also been working with Wrap and getting promising results, and I had also already tested taking my Wrap result into WrapX for a final match, so I’m glad my instincts weren’t way off!

  • Jance