diff --git a/ShoulderCase/@MusclesContainer/createRotatorCuffSlicesMatthieu.m b/ShoulderCase/@MusclesContainer/createRotatorCuffSlicesMatthieu.m index 45fc3b0..77dc9e4 100644 --- a/ShoulderCase/@MusclesContainer/createRotatorCuffSlicesMatthieu.m +++ b/ShoulderCase/@MusclesContainer/createRotatorCuffSlicesMatthieu.m @@ -1,87 +1,107 @@ function createRotatorCuffSlicesMatthieu(obj,sliceName) % This function and its results might be reffered as % Matthieu algorithm and Matthieu slices in some studies. % % This method has been written to simplify, improve, and make reusable % the Nathan's slicing algorithm written in createRotatorCuffSlicesNathan(). % This means: % - taking advantage of the MATLAB obliqueslice() method wich wasn't available % when Nathan's algorithm has been written. % - encapsulating the slicing data and methods in a DicomVolumeSlicer object. % - being able to orient a slice according to dicom points coordinates. % - being able to crop the slice according to dicom points coordinates % and cropping dimensions given in the dicom set units. % % Images and pixel spacings are saved at: % shoulder/dataDev/*/*/*/SCase-IPP/CT-SCase-IPP/matlab/shoulder/muscles/oblique_slice/ assert(not(obj.shoulder.scapula.coordSys.isEmpty),'Scapula coordinate system not measured.'); - [imageForSegmentation,imageForMeasurements,imagesPixelSpacings] = getSlices(obj); + [imageForSegmentation,imageForMeasurements,imagesPixelSpacings,imagesPixelCoordinates] = getSlices(obj); saveImages(obj,imageForSegmentation,imageForMeasurements,sliceName); saveImagesPixelSpacings(obj,imagesPixelSpacings,sliceName); end -function [slice8Bit,slice16Bit,slicesPixelSpacings] = getSlices(obj) +function [slice8Bit,slice16Bit,slicePixelSpacings,slicePixelCoordinates] = getSlices(obj) SCase = obj.shoulder.SCase; scapula = obj.shoulder.scapula; path = SCase.dataDicomPath; try rotatorCuffSlicer = DicomVolumeSlicer(SCase.getSmoothDicomPath); catch rotatorCuffSlicer = DicomVolumeSlicer(SCase.dataDicomPath); end % The 3D volume must be normalised for the slices not to be distorted rotatorCuffSlicer.setMinimalResolutionDividedBy(2); rotatorCuffSlicer.normaliseVolume; rotatorCuffSlicer.slice(scapula.coordSys.origin,scapula.coordSys.ML); % The following lines set the slice to display a 300x300 mm area around the % scapula with the "Y" shape of the scapula oriented up rotatorCuffSlicer.orientSliceUpwardVector(scapula.coordSys.origin,scapula.coordSys.IS); rotatorCuffSlicer.crop(scapula.coordSys.origin-100*scapula.coordSys.IS,300,300); % Rotator cuff segmentation code requires 1024x1024 pixels images if size(rotatorCuffSlicer.sliced,1) > size(rotatorCuffSlicer.sliced,2) rotatorCuffSlicer.resize([1024 nan]); else rotatorCuffSlicer.resize([nan 1024]); end rotatorCuffSlicer.addEmptyBackgroundToSlice(1024,1024); rawSlice = rotatorCuffSlicer.sliced; rotatorCuffSlicer.rescaleSliceToUint8; slice8Bit = rotatorCuffSlicer.sliced; rotatorCuffSlicer.sliced = rawSlice; rotatorCuffSlicer.rescaleSliceToInt16; slice16Bit = rotatorCuffSlicer.sliced; + % Extract the pixels coordinates in space + slicePixelIndices = arrayfun(@(x,y,z) [max(1,round(x)),max(1,round(y)),max(1,round(z))],... + rotatorCuffSlicer.slicedX,... + rotatorCuffSlicer.slicedY,... + rotatorCuffSlicer.slicedZ,... + "UniformOutput", false); + % Pixels of points outside the volume are arbitrarily set to be [1 1 1]. The final + % coordinates will be set to nan. + slicePixelIndices(not(rotatorCuffSlicer.pointsInVolume)) = {[1 1 1]}; + slicePixelCoordinates = cellfun(@(pointIndices) rotatorCuffSlicer.getPointCoordinates(pointIndices),... + slicePixelIndices, "UniformOutput", false); + slicePixelCoordinates(not(rotatorCuffSlicer.pointsInVolume)) = {nan}; + % Flip the slices for right and left shoulders to give similar slices if obj.shoulder.side=='L' slice8Bit=rot90(flipud(slice8Bit),2); slice16Bit=rot90(flipud(slice16Bit),2); + slicePixelCoordinates=rot90(flipud(slicePixelCoordinates),2); end - slicesPixelSpacings = rotatorCuffSlicer.slicedPixelSpacings; + slicePixelSpacings = rotatorCuffSlicer.slicedPixelSpacings; end function saveImages(obj,imageForSegmentation,imageForMeasurements,sliceName) imwrite(imageForSegmentation,... - fullfile(obj.slicesDataPath,[sliceName '_ForSegmentation.png'])); + fullfile(obj.slicesDataPath,[sliceName '_ForSegmentation.png'])); save(fullfile(obj.slicesDataPath,[sliceName '_ForMeasurements.mat']),... - 'imageForMeasurements'); + 'imageForMeasurements'); end function saveImagesPixelSpacings(obj,imagesPixelSpacings,sliceName) save(fullfile(obj.slicesDataPath,[sliceName '_PixelSpacings.mat']),... - 'imagesPixelSpacings'); + 'imagesPixelSpacings'); end + + +function saveImagesPixelCoordinates(obj,imagesPixelCoordinates,sliceName) + save(fullfile(obj.slicesDataPath,[sliceName '_PixelCoordinates.mat']),... + 'imagesPixelCoordinates'); +end \ No newline at end of file