backprojectionDDb_mex_cuda.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. %% Author: Rodrigo de Barros Vimieiro
  3. % Date: March, 2019
  4. % rodrigo.vimieiro@gmail.com
  5. % =========================================================================
  6. %{
  7. % -------------------------------------------------------------------------
  8. % backprojectionDDb_mex_CUDA(proj,param)
  9. % -------------------------------------------------------------------------
  10. % DESCRIPTION:
  11. % This function reconstruct the 3D volume from projections, based on
  12. % the Distance-Driven principle. It works by calculating the overlap
  13. % in X and Y axis of the volume and the detector boundaries.
  14. % The geometry is for DBT with half cone-beam. All parameters are set
  15. % in "ParameterSettings" code.
  16. %
  17. % INPUT:
  18. %
  19. % - proj = 2D projections for each angle
  20. % - param = Parameter of all geometry
  21. % - nProj = projection number to be backprojected
  22. %
  23. % OUTPUT:
  24. %
  25. % - data3d = reconstructed volume.
  26. %
  27. % Reference:
  28. % - Branchless Distance Driven Projection and Backprojection,
  29. % Samit Basu and Bruno De Man (2006)
  30. % - GPU Acceleration of Branchless Distance Driven Projection and
  31. % Backprojection, Liu et al (2016)
  32. % - GPU-Based Branchless Distance-Driven Projection and Backprojection,
  33. % Liu et al (2017)
  34. % - A GPU Implementation of Distance-Driven Computed Tomography,
  35. % Ryan D. Wagner (2017)
  36. % ---------------------------------------------------------------------
  37. % Copyright (C) <2019> <Rodrigo de Barros Vimieiro>
  38. %
  39. % This program is free software: you can redistribute it and/or modify
  40. % it under the terms of the GNU General Public License as published by
  41. % the Free Software Foundation, either version 3 of the License, or
  42. % (at your option) any later version.
  43. %
  44. % This program is distributed in the hope that it will be useful,
  45. % but WITHOUT ANY WARRANTY; without even the implied warranty of
  46. % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  47. % GNU General Public License for more details.
  48. %
  49. % You should have received a copy of the GNU General Public License
  50. % along with this program. If not, see <http://www.gnu.org/licenses/>.
  51. %}
  52. % =========================================================================
  53. %% 3-D Distance Driven Back-projection Code
  54. */
  55. #include "backprojectionDDb_mex_cuda.h"
  56. /****************************************************************************
  57. * function: mexFunction() - Matlab interface function. *
  58. * INPUTS: *
  59. * nlhs - Number of expected output mxArrays, specified as an integer. *
  60. * plhs[] - Array of pointers to the expected mxArray output arguments. *
  61. * nrhs - Number of input mxArrays, specified as an integer. *
  62. * prhs[] - Array of pointers to the mxArray input arguments. *
  63. ****************************************************************************/
  64. void mexFunction(int nlhs, mxArray *plhs[],
  65. int nrhs, const mxArray *prhs[]) {
  66. /* Check for proper number of arguments */
  67. if (nrhs != 3) {
  68. mexErrMsgIdAndTxt("MATLAB:mexcpp:nargin",
  69. "backprojection_mex requires three input arguments.");
  70. }
  71. if (nlhs != 1) {
  72. mexErrMsgIdAndTxt("MATLAB:mexcpp:nargout",
  73. "backprojection_mex requires one output argument.");
  74. }
  75. /* Check if the input is of proper type */
  76. if (!mxIsDouble(prhs[0])) {
  77. mexErrMsgIdAndTxt("MATLAB:mexcpp:typeargin",
  78. "First argument has to be double.");
  79. }
  80. if (!mxIsStruct(prhs[1])) {
  81. mexErrMsgIdAndTxt("MATLAB:mexcpp:typeargin",
  82. "Second argument has to be a struct.");
  83. }
  84. if (!mxIsDouble(prhs[2])) {
  85. mexErrMsgIdAndTxt("MATLAB:mexcpp:typeargin",
  86. "Third argument has to be double.");
  87. }
  88. double* const pProj = (double*)(mxGetPr(prhs[0])); // This variable has to come as single/double
  89. double* const pTubeAngleD = mxGetPr(mxGetField(prhs[1], 0, "tubeDeg"));
  90. double* const pDetAngleD = mxGetPr(mxGetField(prhs[1], 0, "detectorDeg"));
  91. const int unsigned nProj = (const int)mxGetScalar(mxGetField(prhs[1], 0, "nProj"));
  92. const int unsigned nPixX = (const int)mxGetScalar(mxGetField(prhs[1], 0, "nx"));
  93. const int unsigned nPixY = (const int)mxGetScalar(mxGetField(prhs[1], 0, "ny"));
  94. const int unsigned nSlices = (const int)mxGetScalar(mxGetField(prhs[1], 0, "nz"));
  95. const int unsigned nDetX = (const int)mxGetScalar(mxGetField(prhs[1], 0, "nu"));
  96. const int unsigned nDetY = (const int)mxGetScalar(mxGetField(prhs[1], 0, "nv"));
  97. const double dx = (const double)mxGetScalar(mxGetField(prhs[1], 0, "dx"));
  98. const double dy = (const double)mxGetScalar(mxGetField(prhs[1], 0, "dy"));
  99. const double dz = (const double)mxGetScalar(mxGetField(prhs[1], 0, "dz"));
  100. const double du = (const double)mxGetScalar(mxGetField(prhs[1], 0, "du"));
  101. const double dv = (const double)mxGetScalar(mxGetField(prhs[1], 0, "dv"));
  102. const double DSD = (const double)mxGetScalar(mxGetField(prhs[1], 0, "DSD"));
  103. const double DDR = (const double)mxGetScalar(mxGetField(prhs[1], 0, "DDR"));
  104. const double DAG = (const double)mxGetScalar(mxGetField(prhs[1], 0, "DAG"));
  105. const double idXProj = (const double)mxGetScalar(prhs[2]);
  106. mwSize NRow = mxGetM(prhs[0]);
  107. mwSize NCol = mxGetN(prhs[0]);
  108. mwSize NElemVol = mxGetNumberOfElements(prhs[0]);
  109. /* Check if the input is in proper size */
  110. if (NRow != nDetY) {
  111. mexErrMsgIdAndTxt("MATLAB:mexcpp:typeargin",
  112. "First argument needs to have the same number of rows as in the configuration file.");
  113. }
  114. if (NCol / nProj != nDetX) {
  115. mexErrMsgIdAndTxt("MATLAB:mexcpp:typeargin",
  116. "First argument needs to have the same number of columns as in the configuration file.");
  117. }
  118. if (idXProj >= nProj ){
  119. mexErrMsgIdAndTxt("MATLAB:mexcpp:typeargin",
  120. "Third argument needs to be less than the proj number (0->nproj-1)");
  121. }
  122. // Cast double vectors to single
  123. double* const pTubeAngle = (double*)mxMalloc(nProj * sizeof(double));
  124. double* const pDetAngle = (double*)mxMalloc(nProj * sizeof(double));
  125. for (unsigned int n = 0; n < nProj; n++) {
  126. pTubeAngle[n] = (double)pTubeAngleD[n];
  127. pDetAngle[n] = (double)pDetAngleD[n];
  128. }
  129. //mexPrintf("Nx:%d Ny:%d Nz:%d \nNu:%d Nv:%d \nDx:%.2f Dy:%.2f Dz:%.2f \nDu:%.2f Dv:%.2f \nDSD:%.2f DDR:%.2f \n", nPixX, nPixY, nSlices, nDetX, nDetY, dx, dy, dz, du, dv, DSD, DDR);
  130. // Output memory allocation
  131. mwSize dims[3] = { nPixY,nPixX,nSlices };
  132. plhs[0] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
  133. double* const pVolume = (double*)mxGetData(plhs[0]);
  134. backprojectionDDb(pVolume, pProj, pTubeAngle, pDetAngle, idXProj, nProj, nPixX, nPixY, nSlices, nDetX, nDetY, dx, dy, dz, du, dv, DSD, DDR, DAG);
  135. mxFree(pTubeAngle);
  136. mxFree(pDetAngle);
  137. return;
  138. }