Avan commited on
Commit
1d928c1
1 Parent(s): bba89b9

Upload 4 files

Browse files
Files changed (4) hide show
  1. app.py +191 -0
  2. params.npz +3 -0
  3. requirements.txt +6 -0
  4. settings.yaml +83 -0
app.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # %%
2
+ import gradio as gr
3
+ from sklearn import preprocessing
4
+ import collections
5
+ import SimpleITK as sitk
6
+ from radiomics import featureextractor
7
+ import os
8
+ import numpy as np
9
+ from sklearn.preprocessing import StandardScaler
10
+
11
+ # %%
12
+
13
+
14
+ def resize_image_itk(itkimage, newSize, resamplemethod=sitk.sitkLinear):
15
+
16
+ resampler = sitk.ResampleImageFilter()
17
+ originSize = itkimage.GetSize() # 原来的体素块尺寸
18
+ # print(originSize)
19
+ originSpacing = itkimage.GetSpacing()
20
+ newSize = np.array(newSize, float)
21
+ factor = originSize / newSize
22
+ newSpacing = originSpacing * factor
23
+ newSize = newSize.astype(np.int0) # spacing肯定不能是整数
24
+ resampler.SetReferenceImage(itkimage) # 需要重新采样的目标图像
25
+ resampler.SetSize(newSize.tolist())
26
+ resampler.SetOutputSpacing(newSpacing.tolist())
27
+ resampler.SetTransform(sitk.Transform(3, sitk.sitkIdentity))
28
+ resampler.SetInterpolator(resamplemethod)
29
+ itkimgResampled = resampler.Execute(itkimage) # 得到重新采样后的图像
30
+ # print(itkimgResampled.GetSize())
31
+
32
+ return itkimgResampled
33
+
34
+
35
+ def load_image(img):
36
+
37
+ # imgfilePath = os.path.join(img_path, img_name)
38
+ imgfilePath = img
39
+ if not os.path.isfile(imgfilePath):
40
+ print('Error: IMAGE DIR READ FAILED!')
41
+
42
+ # mskfilePath = imgfilePath + '.img'
43
+ '''
44
+ # 读取.dcm Series
45
+ reader = sitk.ImageSeriesReader()
46
+ dcm_series = reader.GetGDCMSeriesFileNames(imgfilePath)
47
+ reader.SetFileNames(dcm_series)
48
+ image = reader.Execute()
49
+ mask = sitk.ReadImage(mskfilePath)
50
+ '''
51
+ # 读取.png或.jpeg图像——可在此处更换读取IO适应不同格式图像
52
+ if imgfilePath[-4:] == '.png':
53
+ image = sitk.ReadImage(
54
+ imgfilePath, imageIO="PNGImageIO", outputPixelType=sitk.sitkInt16)
55
+ else:
56
+ image = sitk.ReadImage(
57
+ imgfilePath, imageIO="JPEGImageIO", outputPixelType=sitk.sitkInt16)
58
+
59
+ # resize_img = resize_image_itk(image, newSize=(512, 512))
60
+
61
+ # img_array = sitk.GetArrayFromImage(resize_img)
62
+
63
+ return image # np.asarray(image)
64
+
65
+
66
+ def feature_extractor(img):
67
+
68
+ image = load_image(img)
69
+ params = 'settings.yaml'
70
+ if os.path.isfile(params):
71
+ extractor = featureextractor.RadiomicsFeatureExtractor(
72
+ params)
73
+
74
+ else:
75
+ settings = {}
76
+ settings['binWidth'] = 25
77
+ settings['resampledPixelSpacing'] = [3, 3, 3]
78
+ settings['interpolator'] = sitk.sitkBSpline
79
+ settings['enableCExtensions'] = True
80
+
81
+ extractor = featureextractor.RadiomicsFeatureExtractor(**settings)
82
+
83
+ headers = None
84
+ featureVector = collections.OrderedDict()
85
+
86
+ # image = sitk.GetImageFromArray(img_array)
87
+ img_array = sitk.GetArrayFromImage(image)
88
+ mask = sitk.GetImageFromArray(np.ones_like(img_array), isVector=True)
89
+
90
+ mask.CopyInformation(image)
91
+
92
+ row = []
93
+ # try:
94
+ featureVector.update(extractor.execute(
95
+ image, mask, label=1)) # 提取特征ROI区域 label=1,2,3,4
96
+ if headers is None:
97
+ headers = list(featureVector.keys()) # [22:]
98
+
99
+ for h in headers:
100
+ row.append(featureVector.get(h, "N/A"))
101
+ # except Exception:
102
+ # print('Error: FEATURE EXTRACTION FAILED!')
103
+
104
+ return np.array(row[22:])
105
+
106
+
107
+ def tansig(x):
108
+ return (2/(1+np.exp(-2*x)))-1
109
+
110
+
111
+ def to_proba(output):
112
+ output = output-np.min(output)
113
+ ret = (output-np.min(output))/(np.max(output)-np.min(output))
114
+ return ret
115
+
116
+
117
+ def softmax(x):
118
+ x = x-np.min(x)
119
+ ex = np.exp(x)
120
+ return ex/ex.sum()
121
+
122
+
123
+ labels = ['covid', 'nofindings', 'pneumonia']
124
+
125
+
126
+ def predict(test_img):
127
+
128
+ params = np.load('params.npz')
129
+ N1 = params['N1']
130
+ N2 = params['N2']
131
+ Beta1OfEachWindow = params['Beta1OfEachWindow']
132
+ ymax = params['ymax']
133
+ ymin = params['ymin']
134
+ minOfEachWindow = params['minOfEachWindow']
135
+ distOfMaxAndMin = params['distOfMaxAndMin']
136
+ weightOfEnhanceLayer = params['weightOfEnhanceLayer']
137
+ parameterOfShrink = params['parameterOfShrink']
138
+ OutputWeight = params['OutputWeight']
139
+
140
+ test_x = feature_extractor(test_img).reshape(1, -1)
141
+ scaler = StandardScaler()
142
+ test_x = scaler.fit_transform(test_x)
143
+ print(test_x.shape)
144
+ # test_x = np.expand_dims(test_x, axis=0)
145
+ # print(test_x.shape)
146
+ test_x = preprocessing.scale(test_x, axis=1)
147
+
148
+ FeatureOfInputDataWithBiasTest = np.hstack(
149
+ [test_x, 0.1 * np.ones((test_x.shape[0], 1))])
150
+ OutputOfFeatureMappingLayerTest = np.zeros(
151
+ [test_x.shape[0], N2 * N1])
152
+
153
+ for i in range(N2):
154
+ outputOfEachWindowTest = np.dot(
155
+ FeatureOfInputDataWithBiasTest, Beta1OfEachWindow[i])
156
+ OutputOfFeatureMappingLayerTest[:, N1*i: N1*(i+1)] = (ymax - ymin)*(
157
+ outputOfEachWindowTest - minOfEachWindow[i]) / distOfMaxAndMin[i] - ymin
158
+
159
+ InputOfEnhanceLayerWithBiasTest = np.hstack(
160
+ [OutputOfFeatureMappingLayerTest, 0.1 * np.ones((OutputOfFeatureMappingLayerTest.shape[0], 1))])
161
+ tempOfOutputOfEnhanceLayerTest = np.dot(
162
+ InputOfEnhanceLayerWithBiasTest, weightOfEnhanceLayer)
163
+
164
+ OutputOfEnhanceLayerTest = tansig(
165
+ tempOfOutputOfEnhanceLayerTest * parameterOfShrink)
166
+
167
+ InputOfOutputLayerTest = np.hstack(
168
+ [OutputOfFeatureMappingLayerTest, OutputOfEnhanceLayerTest])
169
+
170
+ OutputOfTest = np.dot(InputOfOutputLayerTest, OutputWeight)
171
+ # print(OutputOfTest.shape)
172
+ OutputOfTest = np.squeeze(OutputOfTest)
173
+ proba = OutputOfTest # softmax(OutputOfTest)
174
+ confidences = {labels[i]: float(proba[i]) for i in range(3)}
175
+ # np.argmax(OutputOfTest, axis=1) # np.array(OutputOfTest)
176
+ return confidences
177
+
178
+
179
+ # %%
180
+ # pth = '01E392EE-69F9-4E33-BFCE-E5C968654078.jpeg'
181
+ # predict(pth)
182
+
183
+ # %%
184
+
185
+ demo = gr.Interface(fn=predict,
186
+ inputs=gr.Image(type="filepath"),
187
+ outputs=gr.Label()
188
+ )
189
+ demo.launch(share=False)
190
+
191
+ # %%
params.npz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1eccc3eea4d4ee28bdb68bcb253f2ebf5f8545ce97685dc26a043d731cda911a
3
+ size 135798
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ gradio==3.22.1
2
+ numpy==1.21.6
3
+ pyradiomics==3.0.1
4
+ radiomics==0.1
5
+ scikit_learn==1.2.2
6
+ SimpleITK==2.2.1
settings.yaml ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This is an example of settings that can be used as a starting point for analyzing CT data. This is only intended as a
2
+ # starting point and is not likely to be the optimal settings for your dataset. Some points in determining better values
3
+ # are added as comments where appropriate
4
+
5
+ # When adapting and using these settings for an analysis, be sure to add the PyRadiomics version used to allow you to
6
+ # easily recreate your extraction at a later timepoint:
7
+
8
+ # ############################# Extracted using PyRadiomics version: <version> ######################################
9
+
10
+ imageType:
11
+ Original: {}
12
+ #LoG:
13
+ # sigma: [1.0, 2.0] #, 3.0, 4.0, 5.0] # If you include sigma values >5, remember to also increase the padDistance.
14
+ Wavelet: {}
15
+
16
+ featureClass:
17
+ # redundant Compactness 1, Compactness 2 an Spherical Disproportion features are disabled by default, they can be
18
+ # enabled by specifying individual feature names (as is done for glcm) and including them in the list.
19
+ #shape:
20
+ firstorder:
21
+ glcm: # Disable SumAverage by specifying all other GLCM features available
22
+ - "Autocorrelation"
23
+ - "JointAverage"
24
+ - "ClusterProminence"
25
+ - "ClusterShade"
26
+ - "ClusterTendency"
27
+ - "Contrast"
28
+ - "Correlation"
29
+ - "DifferenceAverage"
30
+ - "DifferenceEntropy"
31
+ - "DifferenceVariance"
32
+ - "JointEnergy"
33
+ - "JointEntropy"
34
+ - "Imc1"
35
+ - "Imc2"
36
+ - "Idm"
37
+ - "Idmn"
38
+ - "Id"
39
+ - "Idn"
40
+ - "InverseVariance"
41
+ - "MaximumProbability"
42
+ - "SumEntropy"
43
+ - "SumSquares"
44
+ #glrlm:
45
+ #glszm:
46
+ gldm:
47
+
48
+ setting:
49
+ # Normalization:
50
+ # most likely not needed, CT gray values reflect absolute world values (HU) and should be comparable between scanners.
51
+ # If analyzing using different scanners / vendors, check if the extracted features are correlated to the scanner used.
52
+ # If so, consider enabling normalization by uncommenting settings below:
53
+ #normalize: true
54
+ #normalizeScale: 500 # This allows you to use more or less the same bin width.
55
+
56
+ # Resampling:
57
+ # Usual spacing for CT is often close to 1 or 2 mm, if very large slice thickness is used,
58
+ # increase the resampled spacing.
59
+ # On a side note: increasing the resampled spacing forces PyRadiomics to look at more coarse textures, which may or
60
+ # may not increase accuracy and stability of your extracted features.
61
+ #interpolator: "sitkBSpline"
62
+ #resampledPixelSpacing: [1, 1]
63
+ # padDistance: 10 # Extra padding for large sigma valued LoG filtered images
64
+
65
+ # Mask validation:
66
+ # correctMask and geometryTolerance are not needed, as both image and mask are resampled, if you expect very small
67
+ # masks, consider to enable a size constraint by uncommenting settings below:
68
+ #minimumROIDimensions: 2
69
+ #minimumROISize: 50
70
+
71
+ # Image discretization:
72
+ # The ideal number of bins is somewhere in the order of 16-128 bins. A possible way to define a good binwidt is to
73
+ # extract firstorder:Range from the dataset to analyze, and choose a binwidth so, that range/binwidth remains approximately
74
+ # in this range of bins.
75
+ binWidth: 25
76
+
77
+ # first order specific settings:
78
+ #voxelArrayShift: 1000 # Minimum value in HU is -1000, shift +1000 to prevent negative values from being squared.
79
+
80
+ # Misc:
81
+ # default label value. Labels can also be defined in the call to featureextractor.execute, as a commandline argument,
82
+ # or in a column "Label" in the input csv (batchprocessing)
83
+ label: 1