void HxCPDSpatialGraphWarp::applyNLDeformationToSlice( SpatialGraphSelection& slice, HxSpatialGraph* spatialGraph, const McDArray<McVec3f>& origCoords, const McDArray<McVec3f>& shiftedCoords) { McWatch watch; watch.start(); MovingLeastSquares mls; mls.setAlpha(portAlphaForMLS.getValue()); mls.setLandmarks(origCoords, shiftedCoords); ma::SliceSelector ssh(spatialGraph, "TransformInfo"); SpatialGraphSelection fullSliceSelection; ssh.getSlice(ssh.getSliceAttributeValueFromIndex(1), fullSliceSelection); for (int i = 0; i < fullSliceSelection.getNumSelectedEdges(); i++) { int edge = fullSliceSelection.getSelectedEdge(i); McDArray<McVec3f> newEdgePoints; for (int j = 0; j < spatialGraph->getNumEdgePoints(edge); j++) { McVec3f edgePoint = spatialGraph->getEdgePoint(edge, j); warpPoint(edgePoint, edgePoint, mls); newEdgePoints.append(edgePoint); } spatialGraph->setEdgePoints(edge, newEdgePoints); } for (int i = 0; i < fullSliceSelection.getNumSelectedVertices(); i++) { int curVertex = fullSliceSelection.getSelectedVertex(i); McVec3f curCoord = spatialGraph->getVertexCoords(curVertex); McVec3f curCoordWarped; warpPoint(curCoord, curCoordWarped, mls); spatialGraph->setVertexCoords(curVertex, curCoordWarped); // Add new segments that indicate shift. if (slice.isSelectedVertex(curVertex)) { int newVertex = spatialGraph->addVertex(curCoord); McDArray<McVec3f> edgePoints(2); edgePoints[0] = curCoord; edgePoints[1] = curCoordWarped; spatialGraph->addEdge(newVertex, curVertex, edgePoints); } } std::cout << "\n Apply deformation took " << watch.stop() << " seconds."; }
void HxMovingLeastSquaresWarp::compute() { if (!portAction.wasHit()) return; HxUniformScalarField3* fromImage = (HxUniformScalarField3*)portFromImage.getSource(); HxLandmarkSet* pointSet = hxconnection_cast<HxLandmarkSet>(portData); if (!fromImage) return; /* It is ok to warp without landmarks, if method is rigid and input has a transformation */ if (!pointSet) { return; } else if (pointSet->getNumSets() < 2) { theMsg->printf( "Error: LandmarkWarp data has to contain at least 2 sets."); return; } HxUniformScalarField3* outputImage; HxUniformVectorField3* outputVectorField = 0; outputImage = createOutputDataSet(); outputVectorField = createOutputVectorDataSet(); float* outputImageData = (float*)outputImage->lattice().dataPtr(); McDArray<McVec2d> landmarks1, landmarks2; prepareLandmarks(landmarks1, landmarks2); MovingLeastSquares mls; mls.setAlpha(portAlpha.getValue()); mls.setLandmarks(landmarks2, landmarks1); const McDim3l& dims = outputImage->lattice().getDims(); McVec3f voxelSizeInOutputImage = outputImage->getVoxelSize(); const McBox3f& bboxOfOutputImage = outputImage->getBoundingBox(); const McBox3f& bboxOfFromImage = fromImage->getBoundingBox(); #ifdef _OPENMP #pragma omp parallel for #endif for (int i = 0; i < dims[0]; i++) { HxLocation3* locationInFromImage = fromImage->createLocation(); std::cout << "\n" << i << " of " << dims[0]; for (int j = 0; j < dims[1]; j++) { McVec2d currentPositionInOutput = McVec2d( bboxOfOutputImage[0] + (float)(i)*voxelSizeInOutputImage.x, bboxOfOutputImage[2] + (float)(j)*voxelSizeInOutputImage.y); McVec2d warpedCoordInFromImage = mls.interpolate(currentPositionInOutput); McVec3f displacement = McVec3f( warpedCoordInFromImage.x - currentPositionInOutput.x, warpedCoordInFromImage.y - currentPositionInOutput.y, 0); displacement = displacement * -1; locationInFromImage->move(McVec3f(warpedCoordInFromImage.x, warpedCoordInFromImage.y, bboxOfFromImage[4])); float resultValue[1]; fromImage->eval(*locationInFromImage, resultValue); unsigned long pos = latticePos(i, j, 0, dims); outputImageData[pos] = resultValue[0]; outputVectorField->lattice().set(i, j, 0, displacement.getValue()); } delete locationInFromImage; } outputImage->touch(); outputImage->fire(); }