projectionDDb_mex_cuda.cpp 6.3 KB

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