dicomrt_rasterizeVoi.m 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. function [ROIS] = dicomrt_rasterizeVoi(VOI, ct, ct_xmesh, ct_ymesh, ct_zmesh)
  2. % See also: dicomrt_build3dVOI()
  3. % Check input
  4. % % % Commented for ease of downsample
  5. % % % [ct_temp,type_ct,label,PatientPosition]=dicomrt_checkinput(ct);
  6. % % % ct=dicomrt_varfilter(ct_temp);
  7. [VOI_temp]=dicomrt_checkinput(VOI);
  8. VOI=dicomrt_varfilter(VOI_temp);
  9. % TODO check VOI has to be 2D and along z
  10. % TODO(?) check x,y,zmesh has to be monotonic and unique
  11. % assistant variables
  12. xdim = length(ct_xmesh);
  13. ydim = length(ct_ymesh);
  14. zdim = length(ct_zmesh);
  15. voi2use = 1:size(VOI,1);
  16. [XMESH YMESH] = meshgrid(ct_xmesh, ct_ymesh);
  17. % Progress bar data
  18. h = waitbar(0, 'Rasterizing', 'Name', 'dicomrt_rasterizeVoi');
  19. for kk = 1:length(voi2use)
  20. waitbar(kk./length(voi2use), h, ['Rasterizing: ', VOI{kk,1}]);
  21. % For each voi create a matrix with just 1 and 0
  22. rasterVOI = zeros(xdim, ydim, zdim, 'int8');
  23. num_curves = numel(VOI{kk,2});
  24. for k = 1:num_curves
  25. % the N x 3 curve matrix
  26. curve = VOI{kk,2}{k};
  27. % skip empty curves
  28. numPoints = size(curve,1);
  29. if numPoints < 3
  30. continue;
  31. end
  32. % z coordinate of current VOI
  33. voi_z = VOI{kk,2}{k}(1,3);
  34. % find the appropriate slice
  35. % TODO can simplify this once I'm more confident
  36. dist_z = abs(ct_zmesh-voi_z);
  37. slice = find(dist_z == min(dist_z));
  38. % slice = find(abs(ct_zmesh-voi_z) < dz);
  39. if isempty(slice)
  40. warning('Can not find matching slice');
  41. error('Closest slice found at %f cm', min(abs(ct_zmesh-voi_z)));
  42. elseif numel(slice) > 1
  43. warning('Multiple matching slices found');
  44. elseif dist_z(slice) >= abs(ct_zmesh(1)-ct_zmesh(2))
  45. error('Closest slice found at %f cm', min(abs(ct_zmesh-voi_z)));
  46. end
  47. % binary mask of current curve
  48. if exist('InPolygon', 'file') == 3
  49. % favor the mex function for performance
  50. BW = InPolygon(XMESH,YMESH,curve(:,1),curve(:,2));
  51. else
  52. BW = inpolygon(XMESH,YMESH,curve(:,1),curve(:,2));
  53. end
  54. % merge with existing curve
  55. rasterVOI(:,:,slice) = int8(xor(BW, rasterVOI(:,:,slice)));
  56. end
  57. % Create contour polygon on X and Y plane
  58. Xcurves = cell(0);
  59. for slice = 1:size(rasterVOI, 1)
  60. B = bwboundaries(squeeze(rasterVOI(slice,:,:)));
  61. if ~isempty(B)
  62. for ii = 1:numel(B)
  63. % Here x, y, z vertices means coordinate along 1st, 2nd and 3rd dimension,
  64. % respectively as in line Xcurves{end+1} = cat(2, x, y, z);
  65. x_vertices = ct_xmesh(slice) * ones(size(B{ii}, 1), 1);
  66. y_vertices = interp1(1:numel(ct_ymesh), ct_ymesh, B{ii}(:,1));
  67. z_vertices = interp1(1:numel(ct_zmesh), ct_zmesh, B{ii}(:,2));
  68. Xcurves{end+1} = cat(2, x_vertices, y_vertices, z_vertices);
  69. end
  70. end
  71. end
  72. Ycurves = cell(0);
  73. for slice = 1:size(rasterVOI, 2)
  74. B = bwboundaries(squeeze(rasterVOI(:,slice,:)));
  75. if ~isempty(B)
  76. for ii = 1:numel(B)
  77. y_vertices = ct_ymesh(slice) * ones(size(B{ii}, 1), 1);
  78. x_vertices = interp1(1:numel(ct_xmesh), ct_xmesh, B{ii}(:,1));
  79. z_vertices = interp1(1:numel(ct_zmesh), ct_zmesh, B{ii}(:,2));
  80. Ycurves{end+1} = cat(2, x_vertices, y_vertices, z_vertices);
  81. end
  82. end
  83. end
  84. % Save the ROIs struct
  85. % ROIS{kk}.BW = rasterVOI;
  86. ROIS{kk}.name = VOI{kk,1};
  87. ROIS{kk}.Xcurves = Xcurves;
  88. ROIS{kk}.Ycurves = Ycurves;
  89. % legacy nomenclature: num_curves and curves both refer to Z dimension
  90. ROIS{kk}.num_curves = num_curves;
  91. for k = 1:num_curves
  92. ROIS{kk}.curves{k} = VOI{kk,2}{k};
  93. end
  94. ROIS{kk}.ind = int32(find(rasterVOI));
  95. ROIS{kk}.dim = [xdim ydim zdim];
  96. ROIS{kk}.pixdim = [abs(ct_xmesh(2)-ct_xmesh(1)) abs(ct_ymesh(2)-ct_ymesh(1)) abs(ct_zmesh(2)-ct_zmesh(1))];
  97. ROIS{kk}.start = [ct_xmesh(1) ct_ymesh(1) ct_zmesh(1)];
  98. ROIS{kk}.start_ind = '(1,1,1)';
  99. end
  100. delete(h);