Files changed (4) hide show
  1. index.html +46 -0
  2. main.py +11 -21
  3. style.css +79 -0
  4. utils/page_utils.py +51 -0
index.html ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <link rel="stylesheet" href="file/style.css" />
5
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
6
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
7
+ <link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap" rel="stylesheet" />
8
+ <title>Bilateral View Hypercomplex Breast Classification</title>
9
+ </head>
10
+ <body>
11
+ <div class="container">
12
+ <h1 class="title">Bilateral View Hypercomplex Breast Classification</h1>
13
+ <h2 class="subtitle">Kalbe Digital Lab</h2>
14
+ <section class="overview">
15
+ <div class="grid-container">
16
+ <h3 class="overview-heading"><span class="vl">Overview</span></h3>
17
+ <p class="overview-content">
18
+ Breast cancer classification using 2-views (bilateral) that compose a mammography exam, owing to the correlations contained in mammography views, which present crucial information for identifying tumors.
19
+ <br />
20
+ Reference: <a href="https://arxiv.org/abs/2204.05798" target="_blank">https://arxiv.org/abs/2204.05798</a>
21
+ </p>
22
+ </div>
23
+ <div class="grid-container">
24
+ <h3 class="overview-heading"><span class="vl">Dataset</span></h3>
25
+ <div>
26
+ <p class="overview-content">The model is trained using CBIS <a href="https://pubmed.ncbi.nlm.nih.gov/22078258/" target="_blank">INBReast Dataset</a></p>
27
+ <ul>
28
+ <li>Target: Lesions (masses, calcifications, asymmetries, and distortions)</li>
29
+ <li>Task: Classification</li>
30
+ <li>Modality: Grayscale</li>
31
+ </ul>
32
+ </div>
33
+ </div>
34
+ <div class="grid-container">
35
+ <h3 class="overview-heading"><span class="vl">Model Architecture</span></h3>
36
+ <div>
37
+ <p class="overview-content">Parameterized Hypercomplex ResNets-18 Variants (PHYResNet).</p>
38
+ <img class="content-image" src="file/figures/phresnet18.png" alt="model-architecture" />
39
+ </div>
40
+ </div>
41
+ </section>
42
+ <h3 class="overview-heading"><span class="vl">Demo</span></h3>
43
+ <p class="overview-content">Please select the example below or upload 2 pairs of mammography exam result.</p>
44
+ </div>
45
+ </body>
46
+ </html>
main.py CHANGED
@@ -8,7 +8,7 @@ import torch
8
  from PIL import Image
9
 
10
  from models import phc_models
11
- from utils import utils
12
 
13
  device = torch.device('cpu')
14
  if torch.cuda.is_available():
@@ -193,26 +193,16 @@ def predict_bilateral(cc_file, mlo_file):
193
 
194
  def run():
195
  """Run Gradio App."""
196
- with open('DESCRIPTION.md', encoding='utf-8') as f:
197
- description = f.read()
198
-
199
- with gr.Blocks() as demo:
 
 
 
 
200
  with gr.Column():
201
- gr.Markdown(
202
- """
203
- <h1 style="text-align: center;">Bilateral View Hypercomplex Breast Classification</h1>
204
- """
205
- )
206
- with gr.Row():
207
- gr.Markdown(description)
208
- gr.Markdown(
209
- """
210
- ## Model Architecture
211
- <img src="file/figures/phresnet18.png" width=auto>
212
-
213
- Parameterized Hypercomplex ResNets-18 Variants (PHYResNet).
214
- """
215
- )
216
  with gr.Row():
217
  with gr.Column():
218
  cc_file = gr.File(file_count='single',
@@ -220,8 +210,8 @@ def run():
220
  mlo_file = gr.File(file_count='single',
221
  file_types=SUPPORTED_IMG_EXT, label='MLO View')
222
  with gr.Row():
223
- process_btn = gr.Button('Process')
224
  clear_btn = gr.Button('Clear')
 
225
  with gr.Column():
226
  output_gallery = gr.Gallery(
227
  label='Highlighted Area').style(grid=[2], height='auto')
 
8
  from PIL import Image
9
 
10
  from models import phc_models
11
+ from utils import utils, page_utils
12
 
13
  device = torch.device('cpu')
14
  if torch.cuda.is_available():
 
193
 
194
  def run():
195
  """Run Gradio App."""
196
+ with open('index.html', encoding='utf-8') as f:
197
+ html_content = f.read()
198
+
199
+ with gr.Blocks(theme=gr.themes.Default(primary_hue=page_utils.KALBE_THEME_COLOR, secondary_hue=page_utils.KALBE_THEME_COLOR).set(
200
+ button_primary_background_fill='*primary_600',
201
+ button_primary_background_fill_hover='*primary_500',
202
+ button_primary_text_color='white',
203
+ )) as demo:
204
  with gr.Column():
205
+ gr.HTML(html_content)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  with gr.Row():
207
  with gr.Column():
208
  cc_file = gr.File(file_count='single',
 
210
  mlo_file = gr.File(file_count='single',
211
  file_types=SUPPORTED_IMG_EXT, label='MLO View')
212
  with gr.Row():
 
213
  clear_btn = gr.Button('Clear')
214
+ process_btn = gr.Button('Process', variant="primary")
215
  with gr.Column():
216
  output_gallery = gr.Gallery(
217
  label='Highlighted Area').style(grid=[2], height='auto')
style.css ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * {
2
+ box-sizing: border-box;
3
+ }
4
+
5
+ body {
6
+ font-family: 'Source Sans Pro', sans-serif;
7
+ font-size: 16px;
8
+ }
9
+
10
+ .container {
11
+ width: 100%;
12
+ margin: 0 auto;
13
+ }
14
+
15
+ .title {
16
+ font-size: 24px !important;
17
+ font-weight: 600 !important;
18
+ letter-spacing: 0em;
19
+ text-align: center;
20
+ color: #374159 !important;
21
+ }
22
+
23
+ .subtitle {
24
+ font-size: 24px !important;
25
+ font-style: italic;
26
+ font-weight: 400 !important;
27
+ letter-spacing: 0em;
28
+ text-align: center;
29
+ color: #1d652a !important;
30
+ padding-bottom: 0.5em;
31
+ }
32
+
33
+ .overview-heading {
34
+ font-size: 24px !important;
35
+ font-weight: 600 !important;
36
+ letter-spacing: 0em;
37
+ text-align: left;
38
+ }
39
+
40
+ .overview-content {
41
+ font-size: 14px !important;
42
+ font-weight: 400 !important;
43
+ line-height: 30px !important;
44
+ letter-spacing: 0em;
45
+ text-align: left;
46
+ }
47
+
48
+ .content-image {
49
+ width: 100% !important;
50
+ height: auto !important;
51
+ }
52
+
53
+ .vl {
54
+ border-left: 5px solid #1d652a;
55
+ padding-left: 20px;
56
+ color: #1d652a !important;
57
+ }
58
+
59
+ .grid-container {
60
+ display: grid;
61
+ grid-template-columns: 1fr 2fr;
62
+ gap: 20px;
63
+ align-items: flex-start;
64
+ margin-bottom: 0.7em;
65
+ }
66
+
67
+ @media screen and (max-width: 768px) {
68
+ .container {
69
+ width: 90%;
70
+ }
71
+
72
+ .grid-container {
73
+ display: block;
74
+ }
75
+
76
+ .overview-heading {
77
+ font-size: 18px !important;
78
+ }
79
+ }
utils/page_utils.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Optional
2
+
3
+
4
+ class ColorPalette:
5
+ """Color Palette Container."""
6
+ all = []
7
+
8
+ def __init__(
9
+ self,
10
+ c50: str,
11
+ c100: str,
12
+ c200: str,
13
+ c300: str,
14
+ c400: str,
15
+ c500: str,
16
+ c600: str,
17
+ c700: str,
18
+ c800: str,
19
+ c900: str,
20
+ c950: str,
21
+ name: Optional[str] = None,
22
+ ):
23
+ self.c50 = c50
24
+ self.c100 = c100
25
+ self.c200 = c200
26
+ self.c300 = c300
27
+ self.c400 = c400
28
+ self.c500 = c500
29
+ self.c600 = c600
30
+ self.c700 = c700
31
+ self.c800 = c800
32
+ self.c900 = c900
33
+ self.c950 = c950
34
+ self.name = name
35
+ ColorPalette.all.append(self)
36
+
37
+
38
+ KALBE_THEME_COLOR = ColorPalette(
39
+ name='kalbe',
40
+ c50='#f2f9e8',
41
+ c100='#dff3c4',
42
+ c200='#c2e78d',
43
+ c300='#9fd862',
44
+ c400='#7fc93f',
45
+ c500='#3F831C',
46
+ c600='#31661a',
47
+ c700='#244c13',
48
+ c800='#18340c',
49
+ c900='#0c1b06',
50
+ c950='#050a02',
51
+ )