tbuyuktanir commited on
Commit
f3e324b
·
verified ·
1 Parent(s): 4e85093

Upload 7 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ images/CMU-1-Small-Region.svs filter=lfs diff=lfs merge=lfs -text
37
+ images/sample_wsi_small.svs filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from read_whole_sliding_images import *
2
+ from stain_normalization import *
3
+ import gradio as gr
4
+ wsi2png = gr.Interface(fn=wsi2png, inputs=gr.inputs.File(), outputs=gr.outputs.Image(type='numpy'),
5
+ examples=wsi2png_examples)
6
+ bound_png = gr.Interface(fn=read_bounds_of_image, inputs=gr.inputs.Image(type='numpy'),
7
+ outputs=gr.outputs.Image(type='numpy'), examples=read_bounds_examples)
8
+
9
+
10
+ inp1 = gr.inputs.File()
11
+ inp2 = gr.Slider(1, 10, 4, step=0.25, label="Resolution")
12
+ mask_wsi = gr.Interface(fn=mask_image, inputs=[inp1, inp2], outputs=gr.outputs.Image(type='numpy'), examples=[mask_wsi_examples])
13
+
14
+ normalize_wsi = gr.Interface(fn=normalize_stain, inputs=gr.inputs.File(), outputs=gr.outputs.Image(type='numpy'),
15
+ examples=[stain_normalization_wsi_examples])
16
+
17
+
18
+ demo = gr.TabbedInterface([wsi2png, bound_png, mask_wsi, normalize_wsi], ["WSI2PNG", "Bound Image", "Mask WSI",
19
+ "Normalize Stain"])
20
+
21
+ if __name__ == "__main__":
22
+ demo.launch(show_api=True, auth=("patho", "vis"))
images/CMU-1-Small-Region.svs ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ed92d5a9f2e86df67640d6f92ce3e231419ce127131697fbbce42ad5e002c8a7
3
+ size 1938955
images/sample_wsi_small.png ADDED
images/sample_wsi_small.svs ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ed92d5a9f2e86df67640d6f92ce3e231419ce127131697fbbce42ad5e002c8a7
3
+ size 1938955
read_whole_sliding_images.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import matplotlib.pyplot as plt
2
+ from tiatoolbox.data import small_svs
3
+ from tiatoolbox.wsicore.wsireader import WSIReader
4
+ import gradio as gr
5
+ from pprint import pprint
6
+ from PIL import Image
7
+
8
+ wsi2png_examples = [['images/sample_wsi_small.svs']]
9
+
10
+
11
+ def wsi2png(wsi_file):
12
+ print(wsi_file.name)
13
+ reader = WSIReader.open(wsi_file.name)
14
+ reader.info.objective_power = 1.0
15
+ info_dict = reader.info.as_dict()
16
+ pprint(info_dict)
17
+ thumbnail = reader.slide_thumbnail(resolution=0.1, units="mpp")
18
+ return thumbnail
19
+
20
+
21
+ read_bounds_examples = [['images/sample_wsi_small.png']]
22
+
23
+
24
+ def read_bounds_of_image(image):
25
+ return image
26
+
27
+
28
+ mask_wsi_examples = [['images/sample_wsi_small.svs']]
29
+
30
+
31
+ def mask_image(wsi_file, resolution):
32
+ reader = WSIReader.open(wsi_file.name)
33
+ mask_reader = reader.tissue_mask(resolution=resolution, units="mpp")
34
+ mask_thumbnail = mask_reader.slide_thumbnail(resolution=resolution, units="power")
35
+ mask_thumbnail *= 255
36
+ return mask_thumbnail
requirements.txt ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==23.2.1
2
+ alabaster==0.7.16
3
+ albumentations==1.3.1
4
+ altair==5.3.0
5
+ annotated-types==0.7.0
6
+ anyio==4.4.0
7
+ appnope==0.1.4
8
+ argon2-cffi==23.1.0
9
+ argon2-cffi-bindings==21.2.0
10
+ arrow==1.3.0
11
+ asciitree==0.3.3
12
+ asttokens==2.4.1
13
+ async-lru==2.0.4
14
+ attrs==23.2.0
15
+ Babel==2.15.0
16
+ beautifulsoup4==4.12.3
17
+ bleach==6.1.0
18
+ blinker==1.8.2
19
+ bokeh==3.3.2
20
+ certifi==2024.7.4
21
+ cffi==1.16.0
22
+ charset-normalizer==3.3.2
23
+ click==8.1.7
24
+ comm==0.2.2
25
+ contourpy==1.2.1
26
+ cycler==0.12.1
27
+ debugpy==1.8.2
28
+ decorator==5.1.1
29
+ defusedxml==0.7.1
30
+ dicomweb-client==0.59.1
31
+ dnspython==2.6.1
32
+ docutils==0.20.1
33
+ email_validator==2.2.0
34
+ exceptiongroup==1.2.2
35
+ executing==2.0.1
36
+ fastapi==0.111.1
37
+ fastapi-cli==0.0.4
38
+ fasteners==0.19
39
+ fastjsonschema==2.20.0
40
+ ffmpy==0.3.2
41
+ filelock==3.13.1
42
+ Flask==3.0.0
43
+ Flask-Cors==4.0.0
44
+ fonttools==4.53.1
45
+ fqdn==1.5.1
46
+ fsspec==2024.6.1
47
+ Glymur==0.12.8
48
+ gradio==3.50.0
49
+ gradio_client==0.6.1
50
+ h11==0.14.0
51
+ httpcore==1.0.5
52
+ httptools==0.6.1
53
+ httpx==0.27.0
54
+ huggingface-hub==0.24.2
55
+ idna==3.7
56
+ imagecodecs==2023.9.18
57
+ imageio==2.34.2
58
+ imagesize==1.4.1
59
+ importlib_metadata==8.2.0
60
+ importlib_resources==6.4.0
61
+ ipykernel==6.29.5
62
+ ipython==8.18.1
63
+ isoduration==20.11.0
64
+ itsdangerous==2.2.0
65
+ jedi==0.19.1
66
+ Jinja2==3.1.4
67
+ joblib==1.3.2
68
+ json5==0.9.25
69
+ jsonpointer==3.0.0
70
+ jsonschema==4.23.0
71
+ jsonschema-specifications==2023.12.1
72
+ jupyter-events==0.10.0
73
+ jupyter-lsp==2.2.5
74
+ jupyter_client==8.6.2
75
+ jupyter_core==5.7.2
76
+ jupyter_server==2.14.2
77
+ jupyter_server_terminals==0.5.3
78
+ jupyterlab==4.0.9
79
+ jupyterlab_pygments==0.3.0
80
+ jupyterlab_server==2.27.3
81
+ kiwisolver==1.4.5
82
+ lazy_loader==0.4
83
+ llvmlite==0.41.1
84
+ lxml==5.2.2
85
+ markdown-it-py==3.0.0
86
+ MarkupSafe==2.1.5
87
+ matplotlib==3.8.2
88
+ matplotlib-inline==0.1.7
89
+ mdurl==0.1.2
90
+ mistune==3.0.2
91
+ mpmath==1.3.0
92
+ nbclient==0.10.0
93
+ nbconvert==7.16.4
94
+ nbformat==5.10.4
95
+ nest-asyncio==1.6.0
96
+ networkx==3.2.1
97
+ notebook_shim==0.2.4
98
+ numba==0.58.1
99
+ numcodecs==0.12.1
100
+ numpy==1.26.2
101
+ opencv-python==4.8.0.76
102
+ opencv-python-headless==4.10.0.84
103
+ openslide-python==1.3.1
104
+ orjson==3.10.6
105
+ overrides==7.7.0
106
+ packaging==24.1
107
+ pandas==2.1.4
108
+ pandocfilters==1.5.1
109
+ parso==0.8.4
110
+ pexpect==4.9.0
111
+ Pillow==10.1.0
112
+ platformdirs==4.2.2
113
+ prometheus_client==0.20.0
114
+ prompt_toolkit==3.0.47
115
+ psutil==6.0.0
116
+ ptyprocess==0.7.0
117
+ pure_eval==0.2.3
118
+ pycparser==2.22
119
+ pydantic==2.8.2
120
+ pydantic_core==2.20.1
121
+ pydicom==2.4.4
122
+ pydub==0.25.1
123
+ Pygments==2.18.0
124
+ pynndescent==0.5.13
125
+ pyparsing==3.1.2
126
+ python-dateutil==2.9.0.post0
127
+ python-dotenv==1.0.1
128
+ python-json-logger==2.0.7
129
+ python-multipart==0.0.9
130
+ pytz==2024.1
131
+ PyYAML==6.0.1
132
+ pyzmq==26.0.3
133
+ qudida==0.0.4
134
+ referencing==0.35.1
135
+ requests==2.31.0
136
+ retrying==1.3.4
137
+ rfc3339-validator==0.1.4
138
+ rfc3986-validator==0.1.1
139
+ rich==13.7.1
140
+ rpds-py==0.19.1
141
+ ruff==0.5.5
142
+ scikit-image==0.24.0
143
+ scikit-learn==1.3.2
144
+ scipy==1.11.4
145
+ semantic-version==2.10.0
146
+ Send2Trash==1.8.3
147
+ shapely==2.0.2
148
+ shellingham==1.5.4
149
+ SimpleITK==2.3.1
150
+ six==1.16.0
151
+ sniffio==1.3.1
152
+ snowballstemmer==2.2.0
153
+ soupsieve==2.5
154
+ Sphinx==7.2.6
155
+ sphinxcontrib-applehelp==1.0.8
156
+ sphinxcontrib-devhelp==1.0.6
157
+ sphinxcontrib-htmlhelp==2.0.6
158
+ sphinxcontrib-jsmath==1.0.1
159
+ sphinxcontrib-qthelp==1.0.8
160
+ sphinxcontrib-serializinghtml==1.1.10
161
+ stack-data==0.6.3
162
+ starlette==0.37.2
163
+ sympy==1.13.1
164
+ terminado==0.18.1
165
+ threadpoolctl==3.5.0
166
+ tiatoolbox==1.5.1
167
+ tifffile==2023.12.9
168
+ tinycss2==1.3.0
169
+ tomli==2.0.1
170
+ tomlkit==0.12.0
171
+ toolz==0.12.1
172
+ torch==2.1.2
173
+ torchvision==0.16.2
174
+ tornado==6.4.1
175
+ tqdm==4.66.1
176
+ traitlets==5.14.3
177
+ typer==0.12.3
178
+ types-python-dateutil==2.9.0.20240316
179
+ typing_extensions==4.12.2
180
+ tzdata==2024.1
181
+ umap-learn==0.5.5
182
+ uri-template==1.3.0
183
+ urllib3==2.2.2
184
+ uvicorn==0.30.3
185
+ uvloop==0.19.0
186
+ watchfiles==0.22.0
187
+ wcwidth==0.2.13
188
+ webcolors==24.6.0
189
+ webencodings==0.5.1
190
+ websocket-client==1.8.0
191
+ websockets==11.0.3
192
+ Werkzeug==3.0.3
193
+ wsidicom==0.17.0
194
+ xyzservices==2024.6.0
195
+ zarr==2.16.1
196
+ zipp==3.19.2
stain_normalization.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ # Clear logger to use tiatoolbox.logger
4
+ import logging
5
+
6
+ if logging.getLogger().hasHandlers():
7
+ logging.getLogger().handlers.clear()
8
+
9
+ from pathlib import Path
10
+
11
+ import matplotlib as mpl
12
+ import matplotlib.pyplot as plt
13
+ import requests
14
+ import skimage.color
15
+
16
+ from tiatoolbox import data, logger
17
+ from tiatoolbox.tools import stainnorm
18
+ from tiatoolbox.wsicore import wsireader
19
+ from PIL import Image
20
+ import numpy as np
21
+
22
+ stain_normalization_wsi_examples = [['images/sample_wsi_small.svs']]
23
+
24
+ def normalize_stain(source_wsi_file, output):
25
+ # create a file handler
26
+ wsi_reader = wsireader.WSIReader.open(input_img=source_wsi_file.name)
27
+ wsi_info = wsi_reader.info.as_dict()
28
+ # we will print out each info line by line
29
+ print(*list(wsi_info.items()), sep="\n") # noqa: T201
30
+ wsi_thumb = wsi_reader.slide_thumbnail(resolution=1.25, units="power")
31
+ sample = wsi_reader.read_region(
32
+ location=[800, 1600],
33
+ level=0,
34
+ size=[800, 800], # in X, Y
35
+ )
36
+ target_image = data.stain_norm_target()
37
+ method_name_list = ["Reinhard", "Ruifrok", "Macenko", "Vahadane"]
38
+ plt.subplot(2, 3, 1)
39
+ plt.imshow(sample)
40
+ plt.title("Source Image")
41
+ plt.axis("off")
42
+ plt.subplot(2, 3, 4)
43
+ plt.imshow(target_image)
44
+ plt.title("Target Image")
45
+ plt.axis("off")
46
+
47
+ pos = [2, 3, 5, 6]
48
+ for idx, method_name in enumerate(method_name_list):
49
+ stain_normalizer = stainnorm.get_normalizer(method_name)
50
+ stain_normalizer.fit(target_image)
51
+
52
+ normed_sample = stain_normalizer.transform(sample.copy())
53
+ plt.subplot(2, 3, pos[idx])
54
+ plt.imshow(normed_sample)
55
+ plt.title(method_name.capitalize())
56
+ plt.axis("off")
57
+ plt.tight_layout()
58
+ # plt.show()
59
+ img = plt.savefig('tmp/test.png')
60
+ image = Image.open('tmp/test.png')
61
+ numpy_array = np.array(image)
62
+ return numpy_array