In my studies, I'm trying to apply this shape model to 3D reconstruct faces from 2D images to aid craniofacial surgery, similar to the applications in this course. So far, I've been able to use the model to perform fitting on a 2D image. Looking at our results so far, the faces modelled have a great match for nose, & eyes but the cheeks look too thin or too wide.
We think this is because the fitting is only using the default 12 landmarks around the eyes, nose, mouth and single chin point. Would you/anyone else be able to provide some insight on how I could add more jawline landmarks? I am not sure how to define more landmarks because each one has a specified name.
The 12 I currently use are: center.chin.tip, center.nose.tip, right.nose.wing.tip, left.nose.wing.tip, right.eye.corner_outer, right.eye.corner_inner, left.eye.corner_inner, left.eye.corner_outer, right.lips.corner, center.lips.upper.outer, left.lips.corner, center.lips.lower.outer.
I found out that there were more, summing up to a total of 40 landmarks, which includes the eyebrows, more of the nose and mouth, etc, but I see that there is still very little for the jawline and cheeks. Would there be more landmarks that I am missing or do you have a suggestion for how I could add more?
Any help is greatly appreciated!
Thank you,
Jerry
val initLMSamples: IndexedSeq[RenderParameter] = poseFitter.iterator(init10).take(1000).toIndexedSeq
object JerryLiu extends App{
scalismo.initialize()
val momoFile = new File("/afs/csail.mit.edu/u/e/egger/unibas/model2015/model2017-1_bfm_nomouth.h5")
val momoURI = momoFile.toURI
val momo = MoMoIO.read(momoURI).get.neutralModel
println(momo.landmarks.contains("right.cheek.eye"))
MoMoIO.write(momo, new File("/tmp/model2017-1_face12_nomouth_new.h5"))
val readmomo = MoMoIO.read(new File("/tmp/model2017-1_face12_nomouth_new.h5")).get
println("-")
println(readmomo.landmarks.contains("right.cheek.eye"))
val modelRenderer = MoMoRenderer(momo)
val landmarks = momo.landmarks
var newLandmarks = landmarks + ("right.cheek.eye" -> Landmark("right.cheek.eye",Point3D(-70.25, 30.19, 47.24),None,None))
val newmomo = momo.withLandmarks(newLandmarks)
MoMoIO.write(newmomo, new File("/tmp/model2017-1_face12_nomouth_new2.h5"))
println("-")
println(newmomo.landmarks.contains("right.cheek.eye"))
val readnewmomo = MoMoIO.read(new File("/tmp/model2017-1_face12_nomouth_new2.h5")).get
println("-")
println(readnewmomo.landmarks.contains("right.cheek.eye"))
}
var newLandmarks = landmarks + ("right.cheek.eye" -> Landmark("right.cheek.eye",momo.referenceMesh.pointSet.findClosestPoint(Point3D(-70.25, 30.19, 47.24)).point,None,None))
During rendering it takes the id of that point from the reference - that would fail if the point is not on the reference.
perfect. Let us know if there are more issues - I'm happy to help.
I hope the additional landmarks improve your results. You can also play around with the uncertainty of the landmarks and adapt them to the image size at hand and the uncertainty of the landmarks. Perhaps it even makes sense to use different uncertainties for the newly added points by using two different landmark evaluators.
Best
Bernhard