Hi everyone,Â
I'm trying to make a non-rigid registration to make point-to-point correspondences between the reference and my all meshes. I succeeded but it's really not perfect. I'm building the ssm of a scapula and I'd like the details, especially at the glenoid, to be precise enough.
From what I've understood from the tutorials, this happens at the level of the kernels, but I tested several combinations and chose the one that seemed best, but it's not great.
I'm attaching my code and a picture of what I can get as a result (scapula in pink is the reuslt of non-rigid registration).
Thank you in advance!
(ps: sorry for my english but i'm a french student.. :) )
Â
Here my code :
val zeroMean = Field(EuclideanSpace3D, (_: Point[_3D]) => EuclideanVector.zeros[_3D])
  val kernelCoarse = GaussianKernel3D(86*10)
  val kernelFine = GaussianKernel3D(30*3)
  val kernelfinal = kernelCoarse+kernelFine
  val kernel = DiagonalKernel3D(kernelfinal, outputDim = 3)
  val gp = GaussianProcess(zeroMean, kernel)
  val interpolator = TriangleMeshInterpolator3D[EuclideanVector[_3D]]()
  val lowRankGP = LowRankGaussianProcess.approximateGPCholesky(
   reference,
   gp,
   relativeTolerance = 0.005,
   interpolator = interpolator
  )
  val modelGroup = ui.createGroup("model")
  val gpView = ui.addTransformation(modelGroup, lowRankGP, "gp")
  def doRegistration(
            lowRankGP: LowRankGaussianProcess[_3D, EuclideanVector[_3D]],
            referenceMesh: TriangleMesh[_3D],
            targetICP: TriangleMesh[_3D],
            initialCoefficients: DenseVector[Double],
            regParameters: RegistrationParameters): DenseVector[Double] = {
   val transformationSpace = GaussianProcessTransformationSpace(lowRankGP)
   val fixedImage = referenceMesh.operations.toDistanceImage
   val movingImage = targetICP.operations.toDistanceImage
   val sampler = FixedPointsUniformMeshSampler3D(referenceMesh, numberOfPoints = regParameters.numberOfSampledPoints)
   val metric = MeanSquaresMetric(
    fixedImage,
    movingImage,
    transformationSpace,
    sampler)
   val optimizer = LBFGSOptimizer(maxNumberOfIterations = regParameters.numberOfIterations)
   val regularizer = L2Regularizer(transformationSpace)
   val registration = Registration(
    metric,
    regularizer,
    regularizationWeight = regParameters.regularizationWeight,
    optimizer
   )
   val registrationIterator = registration.iterator(initialCoefficients)
   val visualizingRegistrationIterator = for ((it, itnum) <- registrationIterator.zipWithIndex) yield {
    //println(s"object value in iteration $itnum is ${it.value}")
    gpView.coefficients = it.parameters
    it
   }
   val registrationResult = visualizingRegistrationIterator.toSeq.last
   registrationResult.parameters
  }
  val initialCoefficients = DenseVector.zeros[Double](lowRankGP.rank)
  val allPoints = reference.pointSet.numberOfPoints
  case class RegistrationParameters(regularizationWeight: Double, numberOfIterations: Int, numberOfSampledPoints: Int)
  val registrationParameters = Seq(
   RegistrationParameters(regularizationWeight = 1e-1, numberOfIterations = 50, numberOfSampledPoints = 1000),
   RegistrationParameters(regularizationWeight = 1e-2, numberOfIterations = 50, numberOfSampledPoints = 2000),
   RegistrationParameters(regularizationWeight = 1e-4, numberOfIterations = 100, numberOfSampledPoints = 4000),
   RegistrationParameters(regularizationWeight = 1e-6, numberOfIterations = 100, numberOfSampledPoints = 10000)
  )