Haojiacheng commited on
Commit
0e260f6
·
1 Parent(s): 11b9213

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +178 -0
app.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import matplotlib.pyplot as plt
4
+
5
+ from monai.losses import DiceCELoss
6
+ from monai.inferers import sliding_window_inference
7
+ from monai.transforms import (
8
+ EnsureChannelFirstd,
9
+ Compose,
10
+ LoadImaged,
11
+ Orientationd,
12
+ ScaleIntensityRanged,
13
+ Rotate90d,
14
+ )
15
+ from monai.networks.nets import UNETR
16
+
17
+ from monai.data import (
18
+ SmartCacheDataset,
19
+ )
20
+
21
+ import numpy as np
22
+ import torch
23
+
24
+ import gradio as gr
25
+ import matplotlib.pyplot as plt
26
+ import torch
27
+ import nibabel as nib
28
+ import numpy as np
29
+ import SimpleITK as sitk
30
+
31
+ def dcm2nii(dcms_path, nii_path):
32
+ # 1.构建dicom序列文件阅读器,并执行(即将dicom序列文件“打包整合”)
33
+ reader = sitk.ImageSeriesReader()
34
+ dicom_names = reader.GetGDCMSeriesFileNames(dcms_path)
35
+ reader.SetFileNames(dicom_names)
36
+ image2 = reader.Execute()
37
+ # 2.将整合后的数据转为array,并获取dicom文件基本信息
38
+ image_array = sitk.GetArrayFromImage(image2) # z, y, x
39
+ origin = image2.GetOrigin() # x, y, z
40
+ print(origin)
41
+ spacing = image2.GetSpacing() # x, y, z
42
+ print(spacing)
43
+ direction = image2.GetDirection() # x, y, z
44
+ print(direction)
45
+
46
+ # 3.将array转为img,并保存为.nii.gz
47
+ image3 = sitk.GetImageFromArray(image_array)
48
+ image3.SetSpacing(spacing)
49
+ image3.SetDirection(direction)
50
+ image3.SetOrigin(origin)
51
+ sitk.WriteImage(image3, nii_path)
52
+
53
+ def calculate_volume(mask_image_path):
54
+ # 读取分割结果的图像文件
55
+ mask_image = sitk.ReadImage(mask_image_path)
56
+
57
+ # 获取图像的大小、原点和间距
58
+ size = mask_image.GetSize()
59
+ origin = mask_image.GetOrigin()
60
+ spacing = mask_image.GetSpacing()
61
+
62
+ # 将 SimpleITK 图像转换为 NumPy 数组
63
+ mask_array = sitk.GetArrayFromImage(mask_image)
64
+
65
+ # if len(np.unique(mask_array)) != 5:
66
+ # print(mask_image_path[-15:-12])
67
+ # print(np.unique(mask_array))
68
+
69
+ # 计算非零像素的数量
70
+ one_voxels = (mask_array == 1).sum()
71
+ two_voxels = (mask_array == 2).sum()
72
+ three_voxels = (mask_array == 3).sum()
73
+ four_voxels = (mask_array == 4).sum()
74
+ # print(one_voxels,two_voxels,three_voxels,four_voxels)
75
+ # 计算像素的体积(以立方毫米为单位)
76
+ voxel_volume_mm3 = spacing[0] * spacing[1] * spacing[2]
77
+
78
+ # 计算体积(以 mm³ 为单位)
79
+ V_Right_ventricular_cistern = one_voxels * voxel_volume_mm3 / 1000.0
80
+ V_Right_cerebral_sulcus = two_voxels * voxel_volume_mm3 / 1000.0
81
+ V_Left_ventricular_cistern = three_voxels * voxel_volume_mm3 / 1000.0
82
+ V_Left_cerebral_sulcus = four_voxels * voxel_volume_mm3 / 1000.0
83
+ # 如果需要以其他单位(例如 cm³)显示,请进行适当的单位转换
84
+ # volume_cm3 = volume_mm3 / 1000.0
85
+
86
+ return size,spacing,V_Right_ventricular_cistern, V_Right_cerebral_sulcus, V_Left_ventricular_cistern, V_Left_cerebral_sulcus
87
+
88
+ def process_nii_file(input_nii_file, dicom_file, slice, mode):
89
+
90
+ if mode == "Step1:Segment":
91
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
92
+ root_dir = "./"
93
+ model = UNETR(
94
+ in_channels=1,
95
+ out_channels=5,
96
+ img_size=(96, 96, 16),
97
+ feature_size=16,
98
+ hidden_size=768,
99
+ mlp_dim=3072,
100
+ num_heads=12,
101
+ pos_embed="perceptron",
102
+ norm_name="instance",
103
+ res_block=True,
104
+ dropout_rate=0.0,
105
+ ).to(device)
106
+ model.load_state_dict(torch.load(os.path.join(root_dir, "best_metric_model67v2.pth")))
107
+
108
+ test_transforms = Compose(
109
+ [
110
+ LoadImaged(keys=["image"]),
111
+ EnsureChannelFirstd(keys=["image"]),
112
+ Orientationd(keys=["image"], axcodes="RAS"),
113
+ ScaleIntensityRanged(
114
+ keys=["image"],
115
+ a_min=-50,
116
+ a_max=100,
117
+ b_min=0.0,
118
+ b_max=1.0,
119
+ clip=True,
120
+ ),
121
+ Rotate90d(keys=["image"], k=1)
122
+ # ResizeWithPadOrCropd(keys=["image"], spatial_size=(512, 512, 16)),
123
+ ]
124
+ )
125
+ test_file = [{'image':input_nii_file.name}]
126
+ # test_file = [{'image':r'F:\sth\23Fall\fcpro\brain_image_copy\image\60020599.nii.gz'}]
127
+ test_image = SmartCacheDataset(data=test_file, transform=test_transforms)[0]['image']
128
+
129
+ with torch.no_grad():
130
+
131
+ inputs = torch.unsqueeze(test_image, 1).cuda()
132
+
133
+ val_outputs = sliding_window_inference(inputs, (96, 96, 16), 8, model, overlap=0.8)
134
+
135
+ # Display the images
136
+ fig1 = plt.figure()
137
+ plt.title("image")
138
+ plt.axis('off') # Remove axis
139
+ plt.imshow(inputs.cpu().numpy()[0, 0, :, :, slice], cmap="gray")
140
+
141
+ fig2 = plt.figure()
142
+ plt.title("output")
143
+ plt.axis('off') # Remove axis
144
+ plt.imshow(torch.argmax(val_outputs, dim=1).detach().cpu()[0, :, :, slice])
145
+
146
+ val_outputs = torch.argmax(val_outputs, dim=1).detach().cpu()[0, :, :, :]
147
+ val_outputs = val_outputs.numpy().astype('int16')
148
+ # val_outputs = np.transpose(val_outputs, (2, 1, 0))
149
+ val_outputs = np.rot90(val_outputs, k=3)
150
+ val_outputs = nib.Nifti1Image(val_outputs, np.eye(4))
151
+ nib.save(val_outputs, f'D:/{input_nii_file.name[-15:-7]}_mask.nii.gz')
152
+
153
+ return ["指定切片分割结果如下, mask文件已保存至D:/", fig1, fig2]
154
+
155
+ if mode == "Step2:Volumn":
156
+ maskFilePath = input_nii_file.name
157
+ size,spacing,V_Right_ventricular_cistern, V_Right_cerebral_sulcus, V_Left_ventricular_cistern, V_Left_cerebral_sulcus = calculate_volume(maskFilePath)
158
+
159
+ vol = f"""右侧脑室脑池的体积为{V_Right_ventricular_cistern}cm³\n 右侧脑沟的体积为{V_Right_cerebral_sulcus}cm³\n 左侧脑室脑池的体积为{V_Left_ventricular_cistern}cm³\n 左侧脑沟的体积为{V_Left_cerebral_sulcus}cm³"""
160
+ fig1 = plt.figure()
161
+ fig2 = plt.figure()
162
+ return [vol, fig1, fig2]
163
+
164
+ # Define the Gradio interface
165
+ iface = gr.Interface(
166
+ fn=process_nii_file,
167
+ inputs=
168
+ [gr.File(file_count='single', file_types=['.nii.gz']),
169
+ gr.inputs.Slider(0, 24, default=8, label="Select Slice", step=1),
170
+ gr.Radio(
171
+ ["Step1:Segment", "Step2:Volumn"], label="mode"
172
+ ),
173
+ ],
174
+
175
+ outputs=[gr.Text(label="Output"), gr.Plot(label="image"), gr.Plot(label="mask")], # Display both "image" and "output"
176
+ )
177
+
178
+ iface.launch(share=True)