1 #include "milxQtRegistrationAlgos.h" 2 #include "milxQtRegistration.h" 23 char referenceName[FILENAME_MAX + 1],
24 floatingName[FILENAME_MAX + 1],
25 outputName[FILENAME_MAX + 1];
27 strncpy(referenceName, params.referenceName.toLatin1().constData(), FILENAME_MAX);
28 strncpy(floatingName, params.floatingName.toLatin1().constData(), FILENAME_MAX);
29 strncpy(outputName, params.outputName.toLatin1().constData(), FILENAME_MAX);
32 bool result = reg.RegisterAffineITK(std::string(referenceName),
33 std::string(floatingName),
34 std::string(outputName),
35 false, std::string(
""),
41 emit
error(
"affine()",
"Itk affine registration error");
50 char referenceName[FILENAME_MAX + 1],
51 floatingName[FILENAME_MAX + 1],
52 outputName[FILENAME_MAX + 1];
54 strncpy(referenceName, params.referenceName.toLatin1().constData(), FILENAME_MAX);
55 strncpy(floatingName, params.floatingName.toLatin1().constData(), FILENAME_MAX);
56 strncpy(outputName, params.outputName.toLatin1().constData(), FILENAME_MAX);
58 bool result = reg.RegisterMilxNonRigid(std::string(referenceName),
59 std::string(floatingName),
60 std::string(outputName),
67 emit
error(
"demon()",
"Itk demon registration error");
75 future = QtConcurrent::run(
this, &milxQtRegistrationAlgos::cpp2def, params);
80 future = QtConcurrent::run(
this, &milxQtRegistrationAlgos::f3d, params);
85 future = QtConcurrent::run(
this, &milxQtRegistrationAlgos::aladin, params);
88 void milxQtRegistrationAlgos::average_async(QString outputName, QStringList filenames)
90 future = QtConcurrent::run(
this, &milxQtRegistrationAlgos::average, outputName, filenames);
95 future = QtConcurrent::run(
this, &milxQtRegistrationAlgos::similarities, image);
98 int milxQtRegistrationAlgos::average(QString outputName, QStringList filenames)
100 if (filenames.size() < 2) {
101 emit
error(
"average()",
"Error while computing average, invalid number of file: minimum 2");
107 int nbargs = filenames.count() + 2;
110 arguments = (
char * *)malloc(nbargs *
sizeof(
char *));
111 for (
int i = 0; i < nbargs; i++)
113 arguments[i] = (
char *)malloc(
sizeof(
char) * (FILENAME_MAX + 1));
123 path = filenames[i - 2];
126 QByteArray byteArray = path.toAscii();
127 strncpy(arguments[i], byteArray.data(), FILENAME_MAX);
131 std::string n(arguments[2]);
132 if (n.find(
".nii.gz") != std::string::npos ||
133 n.find(
".nii") != std::string::npos ||
134 n.find(
".hdr") != std::string::npos ||
135 n.find(
".img") != std::string::npos ||
136 n.find(
".img.gz") != std::string::npos)
140 nifti_image *tempImage = reg_io_ReadImageHeader(arguments[2]);
141 if (tempImage == NULL) {
143 for (
int j = 0; j < nbargs; j++) {
147 emit
error(
"average()",
"Error while computing average, the following image can not be read: \"" + QString(arguments[2]) +
"\".");
151 reg_checkAndCorrectDimension(tempImage);
154 nifti_image *averageImage = nifti_copy_nim_info(tempImage);
155 averageImage->scl_slope = 1.f;
156 averageImage->scl_inter = 0.f;
157 nifti_image_free(tempImage);
159 averageImage->datatype = NIFTI_TYPE_FLOAT32;
160 if (
sizeof(PrecisionTYPE) ==
sizeof(
double))
161 averageImage->datatype = NIFTI_TYPE_FLOAT64;
162 averageImage->nbyper =
sizeof(PrecisionTYPE);
163 averageImage->data = (
void *)calloc(averageImage->nvox, averageImage->nbyper);
165 int imageTotalNumber = 0;
166 for (
int i = 2; i<nbargs; ++i)
168 nifti_image *tempImage = reg_io_ReadImageFile(arguments[i]);
169 if (tempImage == NULL) {
171 for (
int j = 0; j < nbargs; j++) {
175 emit
error(
"average()",
"Error while computing average, the following image can not be read: \"" + QString(arguments[i]) +
"\".");
178 reg_checkAndCorrectDimension(tempImage);
179 if (
sizeof(PrecisionTYPE) ==
sizeof(
double))
180 reg_tools_changeDatatype<double>(tempImage);
181 else reg_tools_changeDatatype<float>(tempImage);
182 if (averageImage->nvox != tempImage->nvox) {
184 for (
int j = 0; j < nbargs; j++) {
188 emit
error(
"average()",
"Error while computing average, all images must have the same size. Error when processing: \"" + QString(arguments[i]) +
"\".");
194 reg_tools_addImageToImage(averageImage, tempImage, averageImage);
196 nifti_image_free(tempImage);
199 reg_tools_divideValueToImage(averageImage, averageImage, (
float)imageTotalNumber);
201 reg_io_WriteImageFile(averageImage, arguments[1]);
202 nifti_image_free(averageImage);
207 for (
int j = 0; j < nbargs; j++) {
211 emit
error(
"average()",
"Error while computing average, invalid filetype input (check accepted file extensions: .nii, .nii.gz, .hdr, .img, .img.gz)");
216 for (
int j = 0; j < nbargs; j++) {
220 emit averageCompleted();
226 char referenceName[FILENAME_MAX + 1],
227 defOutputName[FILENAME_MAX + 1],
228 cppOutputName[FILENAME_MAX + 1];
230 strncpy(referenceName, params.referenceName.toLatin1().constData(), FILENAME_MAX);
231 strncpy(defOutputName, params.defOutputName.toLatin1().constData(), FILENAME_MAX);
232 strncpy(cppOutputName, params.cppOutputName.toLatin1().constData(), FILENAME_MAX);
235 mat44 *affineTransformation = NULL;
236 nifti_image *referenceImage = NULL;
237 nifti_image *inputTransformationImage = NULL;
238 nifti_image *outputTransformationImage = NULL;
240 if (reg_isAnImageFileName(cppOutputName))
242 inputTransformationImage = reg_io_ReadImageFile(cppOutputName);
243 if (inputTransformationImage == NULL)
245 fprintf(stderr,
"[NiftyReg ERROR] Error when reading the provided transformation: %s\n",
249 reg_checkAndCorrectDimension(inputTransformationImage);
251 if (inputTransformationImage->intent_p1 == SPLINE_GRID ||
252 inputTransformationImage->intent_p1 == SPLINE_VEL_GRID)
254 referenceImage = reg_io_ReadImageHeader(referenceName);
255 if (referenceImage == NULL)
257 fprintf(stderr,
"[NiftyReg ERROR] Error when reading the reference image: %s\n",
261 reg_checkAndCorrectDimension(referenceImage);
267 affineTransformation = (mat44 *)malloc(
sizeof(mat44));
268 reg_tool_ReadAffineFile(affineTransformation, cppOutputName);
269 referenceImage = reg_io_ReadImageHeader(referenceName);
270 if (referenceImage == NULL)
272 emit
error(
"cpp2def()",
"Error while while computing deformation field, the reference image (\"" + QString(referenceName) +
"\") can not be read.");
275 reg_checkAndCorrectDimension(referenceImage);
278 if (affineTransformation != NULL ||
279 inputTransformationImage->intent_p1 == SPLINE_GRID ||
280 inputTransformationImage->intent_p1 == SPLINE_VEL_GRID)
283 outputTransformationImage = nifti_copy_nim_info(referenceImage);
284 outputTransformationImage->ndim = outputTransformationImage->dim[0] = 5;
285 outputTransformationImage->nt = outputTransformationImage->dim[4] = 1;
286 outputTransformationImage->nu = outputTransformationImage->dim[5] = outputTransformationImage->nz>1 ? 3 : 2;
287 outputTransformationImage->nvox = (size_t)outputTransformationImage->nx *
288 outputTransformationImage->ny * outputTransformationImage->nz *
289 outputTransformationImage->nt * outputTransformationImage->nu;
290 outputTransformationImage->nbyper =
sizeof(
float);
291 outputTransformationImage->datatype = NIFTI_TYPE_FLOAT32;
292 outputTransformationImage->intent_code = NIFTI_INTENT_VECTOR;
293 memset(outputTransformationImage->intent_name, 0, 16);
294 strcpy(outputTransformationImage->intent_name,
"NREG_TRANS");
295 outputTransformationImage->scl_slope = 1.f;
296 outputTransformationImage->scl_inter = 0.f;
301 outputTransformationImage = nifti_copy_nim_info(inputTransformationImage);
304 outputTransformationImage->data = (
void *)malloc
305 (outputTransformationImage->nvox*outputTransformationImage->nbyper);
308 if (affineTransformation != NULL)
310 reg_affine_getDeformationField(affineTransformation, outputTransformationImage);
314 switch (static_cast<int>(reg_round(inputTransformationImage->intent_p1)))
319 memcpy(outputTransformationImage->data, inputTransformationImage->data,
320 outputTransformationImage->nvox*outputTransformationImage->nbyper);
325 memcpy(outputTransformationImage->data, inputTransformationImage->data,
326 outputTransformationImage->nvox*outputTransformationImage->nbyper);
327 reg_getDeformationFromDisplacement(outputTransformationImage);
332 memset(outputTransformationImage->data,
334 outputTransformationImage->nvox*outputTransformationImage->nbyper);
335 reg_getDeformationFromDisplacement(outputTransformationImage);
337 reg_spline_getDeformationField(inputTransformationImage,
338 outputTransformationImage,
347 reg_defField_getDeformationFieldFromFlowField(inputTransformationImage,
348 outputTransformationImage,
355 reg_getDeformationFromDisplacement(outputTransformationImage);
357 reg_defField_getDeformationFieldFromFlowField(inputTransformationImage,
358 outputTransformationImage,
362 case SPLINE_VEL_GRID:
365 reg_spline_getDefFieldFromVelocityGrid(inputTransformationImage,
366 outputTransformationImage,
371 emit
error(
"cpp2def()",
"[NiftyReg ERROR] Unknown input transformation type");
375 outputTransformationImage->intent_p1 = DEF_FIELD;
376 outputTransformationImage->intent_p2 = 0;
380 reg_io_WriteImageFile(outputTransformationImage, defOutputName);
383 if (affineTransformation != NULL) free(affineTransformation);
384 if (referenceImage != NULL) nifti_image_free(referenceImage);
385 if (inputTransformationImage != NULL) nifti_image_free(inputTransformationImage);
386 if (outputTransformationImage != NULL) nifti_image_free(outputTransformationImage);
387 emit cpp2defCompleted();
395 char referenceName[FILENAME_MAX + 1],
396 floatingName[FILENAME_MAX + 1],
397 outputName[FILENAME_MAX + 1],
398 cppOutputName[FILENAME_MAX + 1];
400 strncpy(referenceName, params.referenceName.toLatin1().constData(), FILENAME_MAX);
401 strncpy(floatingName, params.floatingName.toLatin1().constData(), FILENAME_MAX);
402 strncpy(outputName, params.outputName.toLatin1().constData(), FILENAME_MAX);
403 strncpy(cppOutputName, params.cppOutputName.toLatin1().constData(), FILENAME_MAX);
405 int maxiterationNumber = params.maxit;
408 PrecisionTYPE spacing[3];
409 spacing[0] = params.spacing[0];
410 spacing[1] = params.spacing[1];
411 spacing[2] = params.spacing[2];
413 unsigned int levelNumber = params.ln;
414 unsigned int levelToPerform = params.lp;
415 bool noPyramid = params.nopy;
416 bool useSym = params.useSym;
422 nifti_image *referenceImage = NULL;
423 nifti_image *floatingImage = NULL;
425 referenceImage = reg_io_ReadImageFile(referenceName);
426 if (referenceImage == NULL)
428 emit
error(
"f3d()",
"F3D registration error: Error when reading the reference image \"" + QString(referenceName) +
"\".");
432 floatingImage = reg_io_ReadImageFile(floatingName);
433 if (floatingImage == NULL)
435 emit
error(
"f3d()",
"F3D registration error: Error when reading the floating image \"" + QString(floatingName) +
"\".");
444 reg_f3d<PrecisionTYPE> *REG = NULL;
448 REG =
new reg_f3d_sym<PrecisionTYPE>(referenceImage->nt, floatingImage->nt);
452 REG =
new reg_f3d<PrecisionTYPE>(referenceImage->nt, floatingImage->nt);
453 REG->SetReferenceImage(referenceImage);
454 REG->SetFloatingImage(floatingImage);
458 nifti_image *inputCCPImage = NULL;
459 nifti_image *referenceMaskImage = NULL;
460 nifti_image *floatingMaskImage = NULL;
462 int refBinNumber = 0;
463 int floBinNumber = 0;
467 REG->DoNotPrintOutInformation();
469 REG->SetMaximalIterationNumber(maxiterationNumber);
470 REG->SetSpacing(0, spacing[0]);
471 REG->SetSpacing(1, spacing[1]);
472 REG->SetSpacing(2, spacing[2]);
473 REG->SetLevelNumber(levelNumber);
474 REG->SetLevelToPerform(levelToPerform);
477 REG->DoNotUsePyramidalApproach();
484 nifti_image *outputControlPointGridImage = REG->GetControlPointPositionImage();
485 if (cppOutputName[0] ==
'\0') strcpy(cppOutputName,
"outputCPP.nii.gz");
486 memset(outputControlPointGridImage->descrip, 0, 80);
487 strcpy(outputControlPointGridImage->descrip,
"Control point position from NiftyReg (reg_f3d)");
488 if (strcmp(
"NiftyReg F3D2", REG->GetExecutableName()) == 0)
489 strcpy(outputControlPointGridImage->descrip,
"Velocity field grid from NiftyReg (reg_f3d2)");
490 reg_io_WriteImageFile(outputControlPointGridImage, cppOutputName);
491 nifti_image_free(outputControlPointGridImage);
492 outputControlPointGridImage = NULL;
495 if (REG->GetSymmetricStatus())
498 std::string b(cppOutputName);
499 if (b.find(
".nii.gz") != std::string::npos)
500 b.replace(b.find(
".nii.gz"), 7,
"_backward.nii.gz");
501 else if (b.find(
".nii") != std::string::npos)
502 b.replace(b.find(
".nii"), 4,
"_backward.nii");
503 else if (b.find(
".hdr") != std::string::npos)
504 b.replace(b.find(
".hdr"), 4,
"_backward.hdr");
505 else if (b.find(
".img.gz") != std::string::npos)
506 b.replace(b.find(
".img.gz"), 7,
"_backward.img.gz");
507 else if (b.find(
".img") != std::string::npos)
508 b.replace(b.find(
".img"), 4,
"_backward.img");
509 else if (b.find(
".png") != std::string::npos)
510 b.replace(b.find(
".png"), 4,
"_backward.png");
511 else if (b.find(
".nrrd") != std::string::npos)
512 b.replace(b.find(
".nrrd"), 5,
"_backward.nrrd");
513 else b.append(
"_backward.nii");
514 nifti_image *outputBackwardControlPointGridImage = REG->GetBackwardControlPointPositionImage();
515 memset(outputBackwardControlPointGridImage->descrip, 0, 80);
516 strcpy(outputBackwardControlPointGridImage->descrip,
"Backward Control point position from NiftyReg (reg_f3d)");
517 if (strcmp(
"NiftyReg F3D2", REG->GetExecutableName()) == 0)
518 strcpy(outputBackwardControlPointGridImage->descrip,
"Backward velocity field grid from NiftyReg (reg_f3d2)");
519 reg_io_WriteImageFile(outputBackwardControlPointGridImage, b.c_str());
520 nifti_image_free(outputBackwardControlPointGridImage);
521 outputBackwardControlPointGridImage = NULL;
525 nifti_image **outputWarpedImage = (nifti_image **)malloc(2 *
sizeof(nifti_image *));
526 outputWarpedImage[0] = NULL;
527 outputWarpedImage[1] = NULL;
528 outputWarpedImage = REG->GetWarpedImage();
529 if (outputName[0] ==
'\0') strcpy(outputName,
"outputResult.nii");
531 memset(outputWarpedImage[0]->descrip, 0, 80);
532 strcpy(outputWarpedImage[0]->descrip,
"Warped image using NiftyReg (reg_f3d)");
533 if (strcmp(
"NiftyReg F3D SYM", REG->GetExecutableName()) == 0)
535 strcpy(outputWarpedImage[0]->descrip,
"Warped image using NiftyReg (reg_f3d_sym)");
536 strcpy(outputWarpedImage[1]->descrip,
"Warped image using NiftyReg (reg_f3d_sym)");
538 if (strcmp(
"NiftyReg F3D2", REG->GetExecutableName()) == 0)
540 strcpy(outputWarpedImage[0]->descrip,
"Warped image using NiftyReg (reg_f3d2)");
541 strcpy(outputWarpedImage[1]->descrip,
"Warped image using NiftyReg (reg_f3d2)");
543 if (REG->GetSymmetricStatus())
545 if (outputWarpedImage[1] != NULL)
547 std::string b(outputName);
548 if (b.find(
".nii.gz") != std::string::npos)
549 b.replace(b.find(
".nii.gz"), 7,
"_backward.nii.gz");
550 else if (b.find(
".nii") != std::string::npos)
551 b.replace(b.find(
".nii"), 4,
"_backward.nii");
552 else if (b.find(
".hdr") != std::string::npos)
553 b.replace(b.find(
".hdr"), 4,
"_backward.hdr");
554 else if (b.find(
".img.gz") != std::string::npos)
555 b.replace(b.find(
".img.gz"), 7,
"_backward.img.gz");
556 else if (b.find(
".img") != std::string::npos)
557 b.replace(b.find(
".img"), 4,
"_backward.img");
558 else if (b.find(
".png") != std::string::npos)
559 b.replace(b.find(
".png"), 4,
"_backward.png");
560 else if (b.find(
".nrrd") != std::string::npos)
561 b.replace(b.find(
".nrrd"), 5,
"_backward.nrrd");
562 else b.append(
"_backward.nii");
563 reg_io_WriteImageFile(outputWarpedImage[1], b.c_str());
566 reg_io_WriteImageFile(outputWarpedImage[0], outputName);
567 if (outputWarpedImage[0] != NULL)
568 nifti_image_free(outputWarpedImage[0]);
569 outputWarpedImage[0] = NULL;
570 if (outputWarpedImage[1] != NULL)
571 nifti_image_free(outputWarpedImage[1]);
572 outputWarpedImage[1] = NULL;
573 free(outputWarpedImage);
574 outputWarpedImage = NULL;
576 cudaCommon_unsetCUDACard(&ctx);
582 if (referenceImage != NULL) nifti_image_free(referenceImage);
583 if (floatingImage != NULL) nifti_image_free(floatingImage);
587 int minutes = (int)floorf(
float(end - start) / 60.0f);
588 int seconds = (int)(end - start - 60 * minutes);
599 char referenceName[FILENAME_MAX + 1],
600 floatingName[FILENAME_MAX + 1],
601 outputName[FILENAME_MAX + 1];
603 strncpy(referenceName, params.referenceName.toLatin1().constData(), FILENAME_MAX);
604 strncpy(floatingName, params.floatingName.toLatin1().constData(), FILENAME_MAX);
605 strncpy(outputName, params.outputName.toLatin1().constData(), FILENAME_MAX);
607 int referenceImageFlag = 1;
608 int floatingImageFlag = 1;
609 int outputResultFlag = 1;
611 int maxIter = params.maxit;
612 int symFlag = params.useSym;
613 int nLevels = params.ln;
614 int levelsToPerform = params.lp;
615 float blockPercentage = params.percentBlock;
625 if (params.affineDirect)
631 char *outputAffineName = NULL;
632 int outputAffineFlag = 0;
634 char *referenceMaskName = NULL;
635 int referenceMaskFlag = 0;
640 float inlierLts=50.0f;
642 int interpolation = 1;
643 float floatingSigma = 0.0;
644 float referenceSigma=0.0;
646 if (!referenceImageFlag || !floatingImageFlag) {
648 emit
error(
"aladin()",
"Aladin registration error: The reference and the floating image have to be defined");
652 reg_aladin<PrecisionTYPE> *REG;
656 REG =
new reg_aladin_sym<PrecisionTYPE>;
657 fprintf(stdout,
"Using symmetric Aladin\n");
667 REG =
new reg_aladin<PrecisionTYPE>;
675 REG->SetMaxIterations(maxIter);
676 REG->SetNumberOfLevels(nLevels);
677 REG->SetLevelsToPerform(levelsToPerform);
678 REG->SetReferenceSigma(referenceSigma);
679 REG->SetFloatingSigma(floatingSigma);
680 REG->SetAlignCentre(alignCentre);
681 REG->SetPerformAffine(affineFlag);
682 REG->SetPerformRigid(rigidFlag);
683 REG->SetBlockPercentage(blockPercentage);
684 REG->SetInlierLts(inlierLts);
685 REG->SetInterpolation(interpolation);
687 if (REG->GetLevelsToPerform() > REG->GetNumberOfLevels())
688 REG->SetLevelsToPerform(REG->GetNumberOfLevels());
691 nifti_image *referenceHeader = reg_io_ReadImageFile(referenceName);
692 if (referenceHeader == NULL) {
694 emit
error(
"aladin()",
"Aladin registration error: Error when reading the reference image (\"" + QString(referenceName) +
"\").");
699 nifti_image *floatingHeader = reg_io_ReadImageFile(floatingName);
700 if (floatingHeader == NULL) {
702 emit
error(
"aladin()",
"Aladin registration error: Error when reading the floating image (\"" + QString(floatingName) +
"\").");
707 REG->SetInputReference(referenceHeader);
708 REG->SetInputFloating(floatingHeader);
711 nifti_image *referenceMaskImage = NULL;
712 if (referenceMaskFlag) {
713 referenceMaskImage = reg_io_ReadImageFile(referenceMaskName);
714 if (referenceMaskImage == NULL) {
716 emit
error(
"aladin()",
"Aladin registration error: Error when reading the reference mask image (\"" + QString(referenceMaskName) +
"\").");
720 for (
int i = 1; i <= referenceHeader->dim[0]; i++) {
721 if (referenceHeader->dim[i] != referenceMaskImage->dim[i]) {
723 emit
error(
"aladin()",
"Aladin registration error: The reference image and its mask do not have the same dimension.");
727 REG->SetInputMask(referenceMaskImage);
730 nifti_image *floatingMaskImage = NULL;
731 if (floatingMaskFlag && symFlag) {
732 floatingMaskImage = reg_io_ReadImageFile(floatingMaskName);
733 if (floatingMaskImage == NULL) {
735 emit
error(
"aladin()",
"Aladin registration error: Error when reading the floating mask image (\"" + QString(floatingMaskName) +
"\").");
739 for (
int i = 1; i <= floatingHeader->dim[0]; i++) {
740 if (floatingHeader->dim[i] != floatingMaskImage->dim[i]) {
742 emit
error(
"aladin()",
"Aladin registration error: Error the floating image and its mask do not have the same dimension.");
746 REG->SetInputFloatingMask(floatingMaskImage);
752 nifti_image *outputResultImage = REG->GetFinalWarpedImage();
753 if (!outputResultFlag) strcpy(outputName,
"outputResult.nii.gz");
754 reg_io_WriteImageFile(outputResultImage, outputName);
755 nifti_image_free(outputResultImage);
758 if (outputAffineFlag)
759 reg_tool_WriteAffineFile(REG->GetTransformationMatrix(), outputAffineName);
760 else reg_tool_WriteAffineFile(REG->GetTransformationMatrix(), (
char *)
"outputAffine.txt");
762 nifti_image_free(referenceHeader);
763 nifti_image_free(floatingHeader);
768 int minutes = (int)floorf((end - start) / 60.0f);
769 int seconds = (int)(end - start - 60 * minutes);
782 for (
int i = 0; i < 2; i++)
784 QString similarityOutput = image->
createFile(QDir::tempPath() + QDir::separator() +
"similarity_XXXXXX.txt");
785 char referenceName[FILENAME_MAX + 1],
786 floatingName[FILENAME_MAX + 1],
787 outputName[FILENAME_MAX + 1];
789 strncpy(referenceName, image->
reference->
getPath().toLatin1().constData(), FILENAME_MAX);
792 strncpy(floatingName, image->
getPath().toLatin1().constData(), FILENAME_MAX);
794 strncpy(floatingName, image->
getOutputPath().toLatin1().constData(), FILENAME_MAX);
796 strncpy(outputName, similarityOutput.toLatin1().constData(), FILENAME_MAX);
800 nifti_image *refImage = reg_io_ReadImageFile(referenceName);
801 if (refImage == NULL)
803 emit
error(
"similarity()",
"Similarity measure error: Error when reading the reference image (\"" + QString(referenceName) +
"\").");
806 reg_checkAndCorrectDimension(refImage);
807 reg_tools_changeDatatype<float>(refImage);
810 nifti_image *floImage = reg_io_ReadImageFile(floatingName);
811 if (floImage == NULL)
813 emit
error(
"similarity()",
"Similarity measure error: Error when reading the floating image (\"" + QString(floatingName) +
"\").");
816 reg_checkAndCorrectDimension(floImage);
817 reg_tools_changeDatatype<float>(floImage);
821 int refMaskVoxNumber = refImage->nx*refImage->ny*refImage->nz;
822 refMask = (
int *)calloc(refMaskVoxNumber,
sizeof(
int));
823 for (
int j = 0; j<refMaskVoxNumber; ++j) refMask[j] = j;
827 nifti_image *warpedFloImage = nifti_copy_nim_info(refImage);
828 warpedFloImage->ndim = warpedFloImage->dim[0] = floImage->ndim;
829 warpedFloImage->nt = warpedFloImage->dim[4] = floImage->nt;
830 warpedFloImage->nu = warpedFloImage->dim[5] = floImage->nu;
831 warpedFloImage->nvox = (size_t)warpedFloImage->nx * warpedFloImage->ny *
832 warpedFloImage->nz * warpedFloImage->nt * warpedFloImage->nu;
833 warpedFloImage->cal_min = floImage->cal_min;
834 warpedFloImage->cal_max = floImage->cal_max;
835 warpedFloImage->scl_inter = floImage->scl_inter;
836 warpedFloImage->scl_slope = floImage->scl_slope;
837 warpedFloImage->datatype = floImage->datatype;
838 warpedFloImage->nbyper = floImage->nbyper;
839 warpedFloImage->data = (
void *)malloc(warpedFloImage->nvox*warpedFloImage->nbyper);
842 nifti_image *defField = nifti_copy_nim_info(refImage);
843 defField->ndim = defField->dim[0] = 5;
844 defField->nt = defField->dim[4] = 1;
845 defField->nu = defField->dim[5] = refImage->nz>1 ? 3 : 2;
846 defField->nvox = (size_t)defField->nx * defField->ny *
847 defField->nz * defField->nt * defField->nu;
848 defField->datatype = NIFTI_TYPE_FLOAT32;
849 defField->nbyper =
sizeof(
float);
850 defField->data = (
void *)calloc(defField->nvox, defField->nbyper);
851 defField->scl_slope = 1.f;
852 defField->scl_inter = 0.f;
853 reg_tools_multiplyValueToImage(defField, defField, 0.f);
854 defField->intent_p1 = DISP_FIELD;
855 reg_getDeformationFromDisplacement(defField);
858 reg_resampleImage(floImage,
863 std::numeric_limits<float>::quiet_NaN());
864 nifti_image_free(defField);
866 FILE *outFile = NULL;
867 outFile = fopen(outputName,
"w");
871 float *refPtr =
static_cast<float *
>(refImage->data);
872 float *warPtr =
static_cast<float *
>(warpedFloImage->data);
873 double refMeanValue = 0.;
874 double warMeanValue = 0.;
875 refMaskVoxNumber = 0;
876 for (
size_t i = 0; i<refImage->nvox; ++i) {
877 if (refMask[i]>-1 && refPtr[i] == refPtr[i] && warPtr[i] == warPtr[i]) {
878 refMeanValue += refPtr[i];
879 warMeanValue += warPtr[i];
883 if (refMaskVoxNumber == 0)
884 fprintf(stderr,
"No active voxel\n");
885 refMeanValue /= (double)refMaskVoxNumber;
886 warMeanValue /= (double)refMaskVoxNumber;
887 double refSTDValue = 0.;
888 double warSTDValue = 0.;
890 for (
size_t i = 0; i<refImage->nvox; ++i) {
891 if (refMask[i]>-1 && refPtr[i] == refPtr[i] && warPtr[i] == warPtr[i]) {
892 refSTDValue += reg_pow2((
double)refPtr[i] - refMeanValue);
893 warSTDValue += reg_pow2((
double)warPtr[i] - warMeanValue);
894 measure += ((double)refPtr[i] - refMeanValue) *
895 ((double)warPtr[i] - warMeanValue);
898 refSTDValue /= (double)refMaskVoxNumber;
899 warSTDValue /= (double)refMaskVoxNumber;
900 measure /= sqrt(refSTDValue)*sqrt(warSTDValue)*
901 (double)refMaskVoxNumber;
903 fprintf(outFile,
"%g\n", measure);
904 else printf(
"NCC: %g\n", measure);
908 reg_lncc *lncc_object =
new reg_lncc();
909 for (
int j = 0; j < (refImage->nt < warpedFloImage->nt ? refImage->nt : warpedFloImage->nt); ++j)
910 lncc_object->SetActiveTimepoint(j);
911 lncc_object->InitialiseMeasure(refImage,
917 double measure = lncc_object->GetSimilarityMeasureValue();
919 fprintf(outFile,
"%g\n", measure);
920 else printf(
"LNCC: %g\n", measure);
925 reg_nmi *nmi_object =
new reg_nmi();
926 for (
int j = 0; j < (refImage->nt < warpedFloImage->nt ? refImage->nt : warpedFloImage->nt); ++j)
927 nmi_object->SetActiveTimepoint(i);
928 nmi_object->InitialiseMeasure(refImage,
934 double measure = nmi_object->GetSimilarityMeasureValue();
936 fprintf(outFile,
"%g\n", measure);
937 else printf(
"NMI: %g\n", measure);
942 reg_ssd *ssd_object =
new reg_ssd();
943 for (
int j = 0; j < (refImage->nt < warpedFloImage->nt ? refImage->nt : warpedFloImage->nt); ++j)
944 ssd_object->SetActiveTimepoint(i);
945 ssd_object->InitialiseMeasure(refImage,
951 double measure = ssd_object->GetSimilarityMeasureValue();
953 fprintf(outFile,
"%g\n", measure);
954 else printf(
"SSD: %g\n", measure);
962 nifti_image_free(refImage);
963 nifti_image_free(floImage);
967 QFile inputFile(similarityOutput);
968 if (inputFile.open(QIODevice::ReadOnly))
971 QTextStream in(&inputFile);
974 QString line = in.readLine();
976 double value = line.toDouble(&ok);
978 if (ok && lineNumber == 0) {
979 similarities.
ncc = value;
981 else if (ok && lineNumber == 1) {
982 similarities.
lncc = value;
984 else if (ok && lineNumber == 2) {
985 similarities.
nmi = value;
987 else if (ok && lineNumber == 3) {
988 similarities.
ssd = value;
1004 if (QFile::exists(similarityOutput))
1006 QFile::remove(similarityOutput);
1011 emit similaritiesComputed();
1021 future = QtConcurrent::run(
this, &milxQtRegistrationAlgos::elastix, params);
1028 args.append(
"smilx.exe");
1031 args.append(params.referenceName);
1034 args.append(params.floatingName);
1036 args.append(
"-out");
1037 args.append(params.outputFolder);
1040 args.append(params.parameterFile);
1043 typedef elx::ElastixMain ElastixMainType;
1044 typedef ElastixMainType::Pointer ElastixMainPointer;
1045 typedef std::vector< ElastixMainPointer > ElastixMainVectorType;
1046 typedef ElastixMainType::ObjectPointer ObjectPointer;
1047 typedef ElastixMainType::DataObjectContainerPointer DataObjectContainerPointer;
1048 typedef ElastixMainType::FlatDirectionCosinesType FlatDirectionCosinesType;
1050 typedef ElastixMainType::ArgumentMapType ArgumentMapType;
1051 typedef ArgumentMapType::value_type ArgumentMapEntryType;
1053 typedef std::pair< std::string, std::string > ArgPairType;
1054 typedef std::queue< ArgPairType > ParameterFileListType;
1055 typedef ParameterFileListType::value_type ParameterFileListEntryType;
1058 RegisterMevisDicomTiff();
1061 ElastixMainVectorType elastices;
1063 ObjectPointer transform = 0;
1064 DataObjectContainerPointer fixedImageContainer = 0;
1065 DataObjectContainerPointer movingImageContainer = 0;
1066 DataObjectContainerPointer fixedMaskContainer = 0;
1067 DataObjectContainerPointer movingMaskContainer = 0;
1068 FlatDirectionCosinesType fixedImageOriginalDirection;
1069 int returndummy = 0;
1070 unsigned long nrOfParameterFiles = 0;
1071 ArgumentMapType argMap;
1072 ParameterFileListType parameterFileList;
1073 bool outFolderPresent =
false;
1074 std::string outFolder =
"";
1075 std::string logFileName =
"";
1078 for (
unsigned int i = 1;
static_cast<long>(i) < (args.count() - 1); i += 2)
1080 std::string key(args[i].toStdString());
1081 std::string value(args[i + 1].toStdString());
1086 nrOfParameterFiles++;
1087 parameterFileList.push(
1088 ParameterFileListEntryType(key.c_str(), value.c_str()));
1091 std::ostringstream tempPname(
"");
1092 tempPname <<
"-p(" << nrOfParameterFiles <<
")";
1093 std::string tempPName = tempPname.str();
1094 argMap.insert(ArgumentMapEntryType(tempPName.c_str(), value.c_str()));
1101 const char last = value[value.size() - 1];
1102 if (last !=
'/' && last !=
'\\') {
1105 value = itksys::SystemTools::ConvertToOutputPath(value.c_str());
1111 if (itksys::SystemTools::StringStartsWith(value.c_str(),
"\"")
1112 && itksys::SystemTools::StringEndsWith(value.c_str(),
"\""))
1114 value = value.substr(1, value.length() - 2);
1118 outFolderPresent =
true;
1124 if (argMap.count(key.c_str()) == 0)
1126 argMap.insert(ArgumentMapEntryType(key.c_str(), value.c_str()));
1131 std::cerr <<
"WARNING!" << std::endl;
1132 std::cerr <<
"Argument " << key.c_str() <<
"is only required once." << std::endl;
1133 std::cerr <<
"Arguments " << key.c_str() <<
" " << value.c_str() <<
"are ignored" << std::endl;
1141 argMap.insert(ArgumentMapEntryType(
"-argv0", args[0].toStdString()));
1144 if (nrOfParameterFiles == 0)
1146 std::cerr <<
"ERROR: No CommandLine option \"-p\" given!" << std::endl;
1151 if (outFolderPresent)
1154 bool outFolderExists = itksys::SystemTools::FileIsDirectory(outFolder.c_str());
1155 if (!outFolderExists)
1157 std::cerr <<
"ERROR: the output directory \"" << outFolder <<
"\" does not exist." << std::endl;
1158 std::cerr <<
"You are responsible for creating it." << std::endl;
1179 std::cerr <<
"ERROR: No CommandLine option \"-out\" given!" << std::endl;
1185 emit
error(
"elastix()",
"Elastix registration error, error code: " + QString::number(returndummy) +
".");
1189 elxout << std::endl;
1192 tmr::Timer::Pointer totaltimer = tmr::Timer::New();
1193 totaltimer->StartTimer();
1194 elxout <<
"elastix is started at " << totaltimer->PrintStartTime()
1195 <<
".\n" << std::endl;
1199 itksys::SystemInformation info;
1202 info.RunMemoryCheck();
1203 elxout <<
"elastix runs at: " << info.GetHostname() << std::endl;
1204 elxout <<
" " << info.GetOSName() <<
" " 1205 << info.GetOSRelease() << (info.Is64Bits() ?
" (x64), " :
", ")
1206 << info.GetOSVersion() << std::endl;
1207 elxout <<
" with " << info.GetTotalPhysicalMemory() <<
" MB memory, and " 1208 << info.GetNumberOfPhysicalCPU() <<
" cores @ " 1209 <<
static_cast< unsigned int >(info.GetProcessorClockFrequency())
1210 <<
" MHz." << std::endl;
1216 for (
unsigned int i = 0; i < nrOfParameterFiles; i++)
1219 elastices.push_back(ElastixMainType::New());
1222 elastices[i]->SetInitialTransform(transform);
1223 elastices[i]->SetFixedImageContainer(fixedImageContainer);
1224 elastices[i]->SetMovingImageContainer(movingImageContainer);
1225 elastices[i]->SetFixedMaskContainer(fixedMaskContainer);
1226 elastices[i]->SetMovingMaskContainer(movingMaskContainer);
1227 elastices[i]->SetOriginalFixedImageDirectionFlat(fixedImageOriginalDirection);
1230 elastices[i]->SetElastixLevel(i);
1231 elastices[i]->SetTotalNumberOfElastixLevels(nrOfParameterFiles);
1234 if (argMap.count(
"-p"))
1240 ArgPairType argPair = parameterFileList.front();
1241 parameterFileList.pop();
1244 argMap.insert(ArgumentMapEntryType(argPair.first, argPair.second));
1247 elxout <<
"-------------------------------------------------------------------------" <<
"\n" << std::endl;
1248 elxout <<
"Running elastix with parameter file " << i
1249 <<
": \"" << argMap[
"-p"] <<
"\".\n" << std::endl;
1252 tmr::Timer::Pointer timer = tmr::Timer::New();
1253 timer->StartTimer();
1254 elxout <<
"Current time: " << timer->PrintStartTime() <<
"." << std::endl;
1257 returndummy = elastices[i]->Run(argMap);
1260 if (returndummy != 0)
1262 xl::xout[
"error"] <<
"Errors occurred!" << std::endl;
1263 emit
error(
"elastix()",
"Elastix registration error, error code: " + QString::number(returndummy) +
".");
1270 transform = elastices[i]->GetFinalTransform();
1271 fixedImageContainer = elastices[i]->GetFixedImageContainer();
1272 movingImageContainer = elastices[i]->GetMovingImageContainer();
1273 fixedMaskContainer = elastices[i]->GetFixedMaskContainer();
1274 movingMaskContainer = elastices[i]->GetMovingMaskContainer();
1275 fixedImageOriginalDirection = elastices[i]->GetOriginalFixedImageDirectionFlat();
1278 elxout <<
"Running elastix with parameter file " << i
1279 <<
": \"" << argMap[
"-p"] <<
"\", has finished.\n" << std::endl;
1283 elxout <<
"\nCurrent time: " << timer->PrintStopTime() <<
"." << std::endl;
1284 elxout <<
"Time used for running elastix with this parameter file: " 1285 << timer->PrintElapsedTimeDHMS() <<
".\n" << std::endl;
1292 elxout <<
"-------------------------------------------------------------------------" <<
"\n" << std::endl;
1295 totaltimer->StopTimer();
1296 elxout <<
"Total time elapsed: " << totaltimer->PrintElapsedTimeDHMS() <<
".\n" << std::endl;
1301 for (
unsigned int i = 0; i < nrOfParameterFiles; i++)
1307 fixedImageContainer = 0;
1308 movingImageContainer = 0;
1309 fixedMaskContainer = 0;
1310 movingMaskContainer = 0;
1313 ElastixMainType::UnloadComponents();
1316 elastixClean(params);
1327 QString src_basepath = params.outputFolder +
"/" +
"result.";
1334 src_path = src_basepath + QString::number(i) +
".nii";
1335 }
while (QFile::exists(src_path));
1341 src_path = src_basepath + QString::number(i) +
".nii";
1342 if (QFile::exists(params.outputName))
1344 QFile::remove(params.outputName);
1346 QFile::copy(src_path, params.outputName);
1347 QFile::remove(src_path);
1351 QDir directory(params.outputFolder);
1352 QStringList nameFilter;
1353 nameFilter <<
"elastix.log" <<
"IterationInfo.*" <<
"TransformParameters.*" <<
"result.*";
1354 QStringList fileList = directory.entryList(nameFilter);
1356 for (i = 0; i < fileList.size(); i++)
1358 QString filepath = params.outputFolder +
"/" + fileList[i];
1359 if (QFile::exists(filepath))
1361 QFile::remove(filepath);
Contain all the values of similarity measurement.
QFuture< int > future
Used to start the functions asynchroniously.
Contain all the informations and functions required to register an image.
void affine_async(milxQtRegistrationParams params)
Perform a ITK affine registration asynchroniously.
QString getPath()
Get the path of the file.
milxQtRegistrationAlgos(QObject *parent)
The standard constructor.
void error(QString functionName, QString errorMsg)
An error happened during the registration.
void registrationCompleted()
The registration has been completed.
double ncc
Normalized Cross Correlation.
QString createFile(QString pathtemplate)
Create a file and return the path.
milxQtSimilarities similarities_after
Similarities after the registration.
int demon(milxQtRegistrationParams params)
Perform a ITK demon registration.
double ssd
Sum Squared Difference.
int affine(milxQtRegistrationParams params)
Perform a ITK affine registration.
milxQtRegistration * reference
Reference image for the registration.
double nmi
Normalize mutual information.
milxQtSimilarities similarities_before
Similarities before the registration.
void demon_async(milxQtRegistrationParams params)
Perform a ITK demon registration asynchroniously.
double lncc
Localy Normalized Cross Correlation.
QString getOutputPath()
Return the path of the output file.