a b/tool/Code/utilities/image_processing.py
1
# Copyright 2019 Population Health Sciences and Image Analysis, German Center for Neurodegenerative Diseases(DZNE)
2
#
3
#    Licensed under the Apache License, Version 2.0 (the "License");
4
#    you may not use this file except in compliance with the License.
5
#    You may obtain a copy of the License at
6
#
7
#        http://www.apache.org/licenses/LICENSE-2.0
8
#
9
#    Unless required by applicable law or agreed to in writing, software
10
#    distributed under the License is distributed on an "AS IS" BASIS,
11
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
#    See the License for the specific language governing permissions and
13
#    limitations under the License.
14
15
import numpy as np
16
from skimage.measure import label
17
18
19
def largets_connected_componets(labels):
20
    """Calculate the largest connected component, all the labels are unified to one
21
    Args:
22
        labels: ndarray (int or float) label image or volume
23
        neighbors : {4, 8}, int, optional
24
        Whether to use 4- or 8-“connectivity”. In 3D, 4-“connectivity” means connected pixels have to share face, whereas with 8-“connectivity”,
25
        they have to share only edge or vertex. Deprecated, use ``connectivity`` instead.
26
27
28
    Returns:
29
        out :ndarray, the input array only with the largest connected component
30
"""
31
    mask = np.copy(labels)
32
    mask[labels > 0] = 1
33
    connected_labels, num = label(mask,connectivity=3,background=0, return_num=True)
34
    #0 is background data, so check with out zero
35
    #largestCC = np.argmax(np.bincount(connected_labels.flat)[1:])
36
    if num !=1 :
37
        unique, counts = np.unique(connected_labels, return_counts=True)
38
        largest=np.argmax(counts[1:]) + 1 #0 is background data, so check with out zero
39
        mask[connected_labels != largest] = 0
40
41
    mask = np.array(mask, dtype=np.int8)
42
43
    return labels * mask
44
45
46
def swap_axes(data,plane):
47
    if plane == 'axial':
48
        return  data
49
    elif plane == 'frontal':
50
        data = np.swapaxes(data, 1, 0)
51
        return data
52
    elif plane == 'sagital':
53
        data = np.swapaxes(data, 2, 0)
54
        return data
55
56
def check_size(data,patch_size):
57
58
    x_low=int(np.floor(-1*(data.shape[1]-patch_size[0])/2))
59
    x_high=int(np.ceil(-1*(data.shape[1]-patch_size[0])/2))
60
61
62
63
    y_low=int(np.floor(-1*(data.shape[2]-patch_size[1])/2))
64
    y_high=int(np.ceil(-1*(data.shape[2]-patch_size[1])/2))
65
66
    new_arr=np.zeros((data.shape[0],patch_size[0],patch_size[1]))
67
68
    new_arr[:,x_low:patch_size[0]-x_high,y_low:patch_size[1]-y_high]=data[:,:,:]
69
70
    return new_arr
71
72
def change_data_plane(arr, plane='axial',return_index=False):
73
    if plane == 'axial':
74
        if return_index:
75
            return arr,0, arr.shape[0]
76
        else:
77
            return arr
78
79
    elif plane == 'frontal' or plane == 'coronal':
80
            if len(arr.shape) == 4:
81
                new_arr = np.zeros((arr.shape[1], arr.shape[1], arr.shape[2],arr.shape[3]))
82
                for slice in range(arr.shape[3]):
83
                    aux_arr=arr[:,:,:,slice]
84
                    aux_arr = np.swapaxes(aux_arr, 1, 0)
85
                    idx_low = int((new_arr.shape[1] / 2) - (aux_arr.shape[1] / 2))
86
                    idx_high = int((new_arr.shape[1] / 2) + (aux_arr.shape[1] / 2))
87
                    new_arr[:, idx_low:idx_high, :,slice] = aux_arr
88
                if return_index:
89
                    return new_arr,idx_low,idx_high
90
                else:
91
                    return new_arr
92
            else:
93
                new_arr = np.zeros((arr.shape[1], arr.shape[1], arr.shape[2]))
94
                arr = np.swapaxes(arr, 1, 0)
95
                idx_low = int((new_arr.shape[1] / 2) - (arr.shape[1] / 2))
96
                idx_high = int((new_arr.shape[1] / 2) + (arr.shape[1] / 2))
97
                new_arr[:, idx_low:idx_high, :] = arr
98
                if return_index:
99
                    return new_arr,idx_low,idx_high
100
                else:
101
                    return new_arr
102
    elif plane == 'sagital' or plane == 'sagittal':
103
            if len(arr.shape)== 4:
104
                new_arr = np.zeros((arr.shape[2], arr.shape[1], arr.shape[2],arr.shape[3]))
105
                for slice in range(arr.shape[3]):
106
                    aux_arr=arr[:,:,:,slice]
107
                    aux_arr = np.swapaxes(aux_arr, 2, 0)
108
109
                    idx_low = int((new_arr.shape[2] / 2) - (aux_arr.shape[2] / 2))
110
                    idx_high = int((new_arr.shape[2] / 2) + (aux_arr.shape[2] / 2))
111
112
                    new_arr[:, :, idx_low:idx_high,slice] = aux_arr[:]
113
                if return_index:
114
                    return new_arr,idx_low,idx_high
115
                else:
116
                    return new_arr
117
            else:
118
                new_arr = np.zeros((arr.shape[2], arr.shape[1], arr.shape[2]))
119
                arr = np.swapaxes(arr, 2, 0)
120
121
                idx_low = int((new_arr.shape[2] / 2) - (arr.shape[2] / 2))
122
                idx_high = int((new_arr.shape[2] / 2) + (arr.shape[2] / 2))
123
124
                new_arr[:, :, idx_low:idx_high] = arr
125
                if return_index:
126
                    return new_arr,idx_low,idx_high
127
                else:
128
                    return new_arr
129
130
def find_labels(arr):
131
    idx=(np.where(arr > 0))
132
    min_idx=np.min(idx[0])
133
    max_idx=np.max(idx[0])
134
    return max_idx,min_idx