|
1 | | -function outputImage = labelClusters(sourceImage, peakThreshold, extendThreshold) |
| 1 | +function outputImage = labelClusters(varargin) |
| 2 | + % |
| 3 | + % Returns a binary mask for an image after applying voxel wise threshold and |
| 4 | + % an optional cluster size threshold |
| 5 | + % |
| 6 | + % USAGE:: |
| 7 | + % |
| 8 | + % outputImage = thresholdToMask(inputImage, peakThreshold, clusterSize) |
| 9 | + % |
| 10 | + % :param inputImage: |
| 11 | + % :type inputImage: path |
| 12 | + % :param peakThreshold: |
| 13 | + % :type peakThreshold: float |
| 14 | + % :param clusterSize: |
| 15 | + % :type clusterSize: integer >= 0 (Default: 0) |
| 16 | + % |
| 17 | + % :returns: - :outputImage: (string) |
| 18 | + % |
| 19 | + % See also getClusters, sortAndLabelClusters |
2 | 20 | % |
3 | 21 | % Adapted from: |
4 | 22 | % https://en.wikibooks.org/wiki/SPM/How-to#How_to_remove_clusters_under_a_certain_size_in_a_binary_mask? |
5 | 23 | % |
6 | 24 | % (C) Copyright 2021 CPP ROI developers |
7 | 25 |
|
8 | | - hdr = spm_vol(sourceImage); |
| 26 | + default_clusterSize = 0; |
| 27 | + |
| 28 | + isFile = @(x) exists(x, 'file') == 2; |
| 29 | + isPositive = @(x) isinteger(x) && X >= 0; |
| 30 | + |
| 31 | + p = inputParser; |
| 32 | + |
| 33 | + addRequired(p, 'inputImage', isFile); |
| 34 | + addRequired(p, 'peakThreshold', @isnumeric); |
| 35 | + addOptional(p, 'clusterSize', default_clusterSize, isPositive); |
| 36 | + |
| 37 | + parse(p, varargin{:}); |
9 | 38 |
|
10 | | - [l2, num] = getClusters(hdr, peakThreshold); |
| 39 | + inputImage = p.Results.inputImage; |
| 40 | + peakThreshold = p.Results.peakThreshold; |
| 41 | + clusterSize = p.Results.clusterSize; |
| 42 | + |
| 43 | + [l2, num] = getClusters(inputImage, peakThreshold); |
11 | 44 |
|
12 | 45 | if ~num |
13 | 46 | warning('No clusters found.'); |
14 | 47 | return |
15 | 48 | end |
16 | 49 |
|
17 | | - vol = sortAndLabelClusters(l2, num, extendThreshold); |
| 50 | + vol = sortAndLabelClusters(l2, num, clusterSize); |
18 | 51 |
|
19 | 52 | % Write new image with cluster laebelled with their voxel size |
20 | | - p = bids.internal.parse_filename(sourceImage); |
| 53 | + p = bids.internal.parse_filename(inputImage); |
21 | 54 | p.suffix = 'dseg'; % discrete segmentation |
22 | 55 |
|
| 56 | + hdr = spm_vol(inputImage); |
23 | 57 | bidsFile = bids.File(p); |
24 | 58 | hdr.fname = spm_file(hdr.fname, 'filename', bidsFile.filename); |
25 | 59 |
|
|
31 | 65 | bids.util.jsonencode(json.filename, json.content); |
32 | 66 |
|
33 | 67 | end |
34 | | - |
35 | | -function [l2, num] = getClusters(hdr, peakThreshold) |
36 | | - data = spm_read_vols(hdr); |
37 | | - [l2, num] = spm_bwlabel(double(data > peakThreshold), 26); |
38 | | -end |
39 | | - |
40 | | -function vol = sortAndLabelClusters(l2, num, extendThreshold) |
41 | | - |
42 | | - % Extent threshold, and sort clusters by their extent |
43 | | - % Label corresponds to their rank |
44 | | - [n, ni] = sort(histc(l2(:), 0:num), 1, 'descend'); |
45 | | - vol = zeros(size(l2)); |
46 | | - n = n(2:end); |
47 | | - ni = ni(2:end) - 1; |
48 | | - ni = ni(n >= extendThreshold); |
49 | | - n = n(n >= extendThreshold); |
50 | | - for i = 1:length(n) |
51 | | - vol(l2 == ni(i)) = i; |
52 | | - end |
53 | | - |
54 | | - fprintf('Selected %d clusters (out of %d) in image.\n', length(n), num); |
55 | | - for i = 1:length(n) |
56 | | - fprintf('Cluster label %i ; size: %i voxels\n', i, n(i)); |
57 | | - end |
58 | | - |
59 | | -end |
|
0 commit comments