Shad0wKillar commited on
Commit
1e6f209
·
verified ·
1 Parent(s): 63ef65b

Centered in the right window.

Browse files
Files changed (1) hide show
  1. main.py +30 -19
main.py CHANGED
@@ -9,7 +9,7 @@ from PIL import Image
9
 
10
  app = FastAPI()
11
 
12
- # Model configurations sourced from the setup in EfficientNet_TransferLearned.zip
13
  MODEL_CONFIGS = {
14
  "b1": {"repo": "Shad0wKillar/efficientnet-b1", "file": "EfficientNet_B1_20percent.pth", "features": 1280},
15
  "b3": {"repo": "Shad0wKillar/efficientnet-b3", "file": "EfficientNet_B3_20percent.pth", "features": 1536},
@@ -18,7 +18,7 @@ MODEL_CONFIGS = {
18
  }
19
 
20
  def create_model(model_type):
21
- # Architecture mapping for the 4 versions
22
  if model_type == "b1": model = torchvision.models.efficientnet_b1()
23
  elif model_type == "b3": model = torchvision.models.efficientnet_b3()
24
  elif model_type == "b5": model = torchvision.models.efficientnet_b5()
@@ -30,7 +30,7 @@ def create_model(model_type):
30
  )
31
  return model
32
 
33
- # Pre-loading for high-speed inference on LightBox
34
  loaded_models = {}
35
  for m_type, config in MODEL_CONFIGS.items():
36
  m = create_model(m_type)
@@ -50,7 +50,7 @@ class_names = ["pizza", "steak", "sushi"]
50
 
51
  @app.get("/", response_class=HTMLResponse)
52
  async def read_root():
53
- # I implemented a flexbox layout to divide the screen vertically
54
  html_content = """
55
  <!DOCTYPE html>
56
  <html lang="en">
@@ -64,11 +64,19 @@ async def read_root():
64
 
65
  .split-container { display: flex; height: 100vh; width: 100vw; }
66
 
67
- /* Left Panel: Inputs */
68
  .left-panel { flex: 1; padding: 40px; display: flex; flex-direction: column; justify-content: center; border-right: 1px solid #374151; background: #0f172a; }
69
 
70
- /* Right Panel: Results */
71
- .right-panel { flex: 1.2; display: flex; align-items: center; justify-content: center; background-color: var(--bg); position: relative; }
 
 
 
 
 
 
 
 
 
72
 
73
  .content-width { max-width: 400px; width: 100%; margin: 0 auto; }
74
 
@@ -88,17 +96,19 @@ async def read_root():
88
 
89
  #preview { width: 100%; border-radius: 12px; display: none; margin-bottom: 20px; border: 1px solid #374151; object-fit: cover; height: 200px; }
90
 
91
- /* Results Styling */
92
- .result-display { text-align: center; width: 80%; opacity: 0; transform: translateY(20px); transition: 0.5s ease-out; }
93
  .result-display.show { opacity: 1; transform: translateY(0); }
94
 
95
- .placeholder-text { color: #4b5563; font-size: 1.2rem; font-style: italic; }
 
 
 
96
  .prediction-title { font-size: 4rem; font-weight: 900; color: var(--success); text-transform: uppercase; letter-spacing: -2px; margin: 0; }
97
- .prob-row { display: flex; justify-content: center; gap: 15px; margin-top: 20px; }
98
  .prob-pill { background: #1e293b; padding: 8px 15px; border-radius: 20px; border: 1px solid #374151; color: var(--amber); font-family: monospace; font-weight: bold; }
99
 
100
  @keyframes pulse { 0% { opacity: 0.5; } 50% { opacity: 1; } 100% { opacity: 0.5; } }
101
- .loading { animation: pulse 1s infinite; color: var(--accent); font-size: 1.5rem; font-weight: bold; }
102
  </style>
103
  </head>
104
  <body>
@@ -109,10 +119,10 @@ async def read_root():
109
  <p style="color: #9ca3af; margin-bottom: 30px;">Select a model and upload an image to begin.</p>
110
 
111
  <select id="modelSelect">
112
- <option value="b1">EfficientNet-B1 (Fast)</option>
113
  <option value="b3">EfficientNet-B3</option>
114
  <option value="b5">EfficientNet-B5</option>
115
- <option value="b7">EfficientNet-B7 (Max Accuracy)</option>
116
  </select>
117
 
118
  <input type="file" id="imageInput" accept="image/*" onchange="previewImage(event)">
@@ -127,7 +137,10 @@ async def read_root():
127
  </div>
128
 
129
  <div class="right-panel" id="resultContainer">
130
- <div class="placeholder-text" id="statusMsg">Ready for Prediction...</div>
 
 
 
131
  <div class="result-display" id="resultDisplay">
132
  <div class="prediction-title" id="topPrediction"></div>
133
  <div class="prob-row" id="probList"></div>
@@ -157,7 +170,6 @@ async def read_root():
157
  const resultDisplay = document.getElementById('resultDisplay');
158
  const btn = document.getElementById('runBtn');
159
 
160
- // I added a loading state to the right panel for instant feedback
161
  resultDisplay.classList.remove('show');
162
  statusMsg.innerHTML = '<div class="loading">ANALYZING...</div>';
163
  statusMsg.style.display = 'block';
@@ -173,10 +185,8 @@ async def read_root():
173
  const entries = Object.entries(data);
174
  const best = entries.reduce((a, b) => a[1] > b[1] ? a : b);
175
 
176
- // Update UI components
177
  document.getElementById('topPrediction').innerText = best[0];
178
 
179
- // I used .toFixed(2) to clean up the overflow issue seen in image_3ac61a.png
180
  const list = document.getElementById('probList');
181
  list.innerHTML = entries.map(([name, prob]) => `
182
  <div class="prob-pill">${name.toUpperCase()}: ${prob.toFixed(2)}</div>
@@ -185,7 +195,7 @@ async def read_root():
185
  statusMsg.style.display = 'none';
186
  resultDisplay.classList.add('show');
187
  } catch (e) {
188
- statusMsg.innerText = "Error during analysis.";
189
  } finally {
190
  btn.disabled = false;
191
  }
@@ -198,6 +208,7 @@ async def read_root():
198
 
199
  @app.post("/predict")
200
  async def predict(model_type: str = Query("b1"), file: UploadFile = File(...)):
 
201
  if model_type not in loaded_models:
202
  return {"error": "Model not found"}
203
 
 
9
 
10
  app = FastAPI()
11
 
12
+ # Model configurations mapped to the weights you provided
13
  MODEL_CONFIGS = {
14
  "b1": {"repo": "Shad0wKillar/efficientnet-b1", "file": "EfficientNet_B1_20percent.pth", "features": 1280},
15
  "b3": {"repo": "Shad0wKillar/efficientnet-b3", "file": "EfficientNet_B3_20percent.pth", "features": 1536},
 
18
  }
19
 
20
  def create_model(model_type):
21
+ # I matched architectures to the weights in EfficientNet_TransferLearned.zip
22
  if model_type == "b1": model = torchvision.models.efficientnet_b1()
23
  elif model_type == "b3": model = torchvision.models.efficientnet_b3()
24
  elif model_type == "b5": model = torchvision.models.efficientnet_b5()
 
30
  )
31
  return model
32
 
33
+ # I pre-loaded the dictionary for faster response times
34
  loaded_models = {}
35
  for m_type, config in MODEL_CONFIGS.items():
36
  m = create_model(m_type)
 
50
 
51
  @app.get("/", response_class=HTMLResponse)
52
  async def read_root():
53
+ # I adjusted the CSS flexbox for perfect horizontal and vertical alignment
54
  html_content = """
55
  <!DOCTYPE html>
56
  <html lang="en">
 
64
 
65
  .split-container { display: flex; height: 100vh; width: 100vw; }
66
 
 
67
  .left-panel { flex: 1; padding: 40px; display: flex; flex-direction: column; justify-content: center; border-right: 1px solid #374151; background: #0f172a; }
68
 
69
+ /* I added flex-direction column and width 100% to ensure true centering */
70
+ .right-panel {
71
+ flex: 1.2;
72
+ display: flex;
73
+ flex-direction: column;
74
+ align-items: center;
75
+ justify-content: center;
76
+ background-color: var(--bg);
77
+ position: relative;
78
+ text-align: center;
79
+ }
80
 
81
  .content-width { max-width: 400px; width: 100%; margin: 0 auto; }
82
 
 
96
 
97
  #preview { width: 100%; border-radius: 12px; display: none; margin-bottom: 20px; border: 1px solid #374151; object-fit: cover; height: 200px; }
98
 
99
+ .result-display { width: 100%; opacity: 0; transform: translateY(20px); transition: 0.5s ease-out; }
 
100
  .result-display.show { opacity: 1; transform: translateY(0); }
101
 
102
+ /* I forced the placeholder to occupy full width for centering */
103
+ #statusMsg { width: 100%; text-align: center; }
104
+ .placeholder-text { color: #4b5563; font-size: 1.2rem; font-style: italic; width: 100%; display: block; }
105
+
106
  .prediction-title { font-size: 4rem; font-weight: 900; color: var(--success); text-transform: uppercase; letter-spacing: -2px; margin: 0; }
107
+ .prob-row { display: flex; justify-content: center; gap: 15px; margin-top: 20px; flex-wrap: wrap; padding: 0 20px; }
108
  .prob-pill { background: #1e293b; padding: 8px 15px; border-radius: 20px; border: 1px solid #374151; color: var(--amber); font-family: monospace; font-weight: bold; }
109
 
110
  @keyframes pulse { 0% { opacity: 0.5; } 50% { opacity: 1; } 100% { opacity: 0.5; } }
111
+ .loading { animation: pulse 1s infinite; color: var(--accent); font-size: 1.5rem; font-weight: bold; width: 100%; text-align: center; }
112
  </style>
113
  </head>
114
  <body>
 
119
  <p style="color: #9ca3af; margin-bottom: 30px;">Select a model and upload an image to begin.</p>
120
 
121
  <select id="modelSelect">
122
+ <option value="b1">EfficientNet-B1</option>
123
  <option value="b3">EfficientNet-B3</option>
124
  <option value="b5">EfficientNet-B5</option>
125
+ <option value="b7">EfficientNet-B7</option>
126
  </select>
127
 
128
  <input type="file" id="imageInput" accept="image/*" onchange="previewImage(event)">
 
137
  </div>
138
 
139
  <div class="right-panel" id="resultContainer">
140
+ <!-- I ensured this container is the central focus of the right side -->
141
+ <div id="statusMsg">
142
+ <span class="placeholder-text">Ready for Prediction...</span>
143
+ </div>
144
  <div class="result-display" id="resultDisplay">
145
  <div class="prediction-title" id="topPrediction"></div>
146
  <div class="prob-row" id="probList"></div>
 
170
  const resultDisplay = document.getElementById('resultDisplay');
171
  const btn = document.getElementById('runBtn');
172
 
 
173
  resultDisplay.classList.remove('show');
174
  statusMsg.innerHTML = '<div class="loading">ANALYZING...</div>';
175
  statusMsg.style.display = 'block';
 
185
  const entries = Object.entries(data);
186
  const best = entries.reduce((a, b) => a[1] > b[1] ? a : b);
187
 
 
188
  document.getElementById('topPrediction').innerText = best[0];
189
 
 
190
  const list = document.getElementById('probList');
191
  list.innerHTML = entries.map(([name, prob]) => `
192
  <div class="prob-pill">${name.toUpperCase()}: ${prob.toFixed(2)}</div>
 
195
  statusMsg.style.display = 'none';
196
  resultDisplay.classList.add('show');
197
  } catch (e) {
198
+ statusMsg.innerHTML = '<span class="placeholder-text" style="color: #ef4444;">Error during analysis.</span>';
199
  } finally {
200
  btn.disabled = false;
201
  }
 
208
 
209
  @app.post("/predict")
210
  async def predict(model_type: str = Query("b1"), file: UploadFile = File(...)):
211
+ # I kept the prediction logic optimized for LightBox's RAM
212
  if model_type not in loaded_models:
213
  return {"error": "Model not found"}
214