supli6669 commited on
Commit ·
d58a6b4
1
Parent(s): eabcd68
fix: patch B1, B5, B7, B8, B9 (state guards, dead callback, face size tuple, dashboard loss, esc key)
Browse files- app.py +20 -12
- pipeline.py +8 -4
app.py
CHANGED
|
@@ -242,6 +242,19 @@ if 'history' not in st.session_state:
|
|
| 242 |
if 'dark_mode' not in st.session_state:
|
| 243 |
st.session_state.dark_mode = True
|
| 244 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 245 |
def apply_theme():
|
| 246 |
"""Apply dark/light theme based on user preference."""
|
| 247 |
if not st.session_state.dark_mode:
|
|
@@ -269,16 +282,6 @@ def apply_theme():
|
|
| 269 |
</style>
|
| 270 |
""", unsafe_allow_html=True)
|
| 271 |
|
| 272 |
-
def progress_callback(stage, progress, message):
|
| 273 |
-
"""Callback function to update progress state from pipeline."""
|
| 274 |
-
if not st.session_state.progress_state.get('cancelled', False):
|
| 275 |
-
st.session_state.progress_state = {
|
| 276 |
-
'stage': stage,
|
| 277 |
-
'progress': progress,
|
| 278 |
-
'message': message,
|
| 279 |
-
'active': True,
|
| 280 |
-
'cancelled': False
|
| 281 |
-
}
|
| 282 |
|
| 283 |
@st.cache_resource(show_spinner=False, hash_funcs={LocalAIEnhancerPipeline: lambda _: None})
|
| 284 |
def get_pipeline():
|
|
@@ -322,7 +325,7 @@ document.addEventListener('keydown', function(e) {
|
|
| 322 |
}
|
| 323 |
// Esc: Cancel processing
|
| 324 |
if (e.key === 'Escape') {
|
| 325 |
-
const cancelButton = document.
|
| 326 |
if (cancelButton) {
|
| 327 |
cancelButton.click();
|
| 328 |
}
|
|
@@ -358,7 +361,12 @@ def get_training_status():
|
|
| 358 |
if "iter:" in line and "epoch:" in line:
|
| 359 |
match = re.search(r"epoch:\s*(\d+),\s*iter:\s*([\d,]+)", line)
|
| 360 |
eta_match = re.search(r"eta:\s*([\d:]+)", line)
|
| 361 |
-
loss_match =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
|
| 363 |
if match:
|
| 364 |
epoch = int(match.group(1))
|
|
|
|
| 242 |
if 'dark_mode' not in st.session_state:
|
| 243 |
st.session_state.dark_mode = True
|
| 244 |
|
| 245 |
+
# App state lifecycle management
|
| 246 |
+
for key, default in [
|
| 247 |
+
('processing', False),
|
| 248 |
+
('enhanced_img', None),
|
| 249 |
+
('processing_error', None),
|
| 250 |
+
('process_duration', None),
|
| 251 |
+
('start_time', None),
|
| 252 |
+
('last_run_params', None),
|
| 253 |
+
('history_added_for', None),
|
| 254 |
+
]:
|
| 255 |
+
if key not in st.session_state:
|
| 256 |
+
st.session_state[key] = default
|
| 257 |
+
|
| 258 |
def apply_theme():
|
| 259 |
"""Apply dark/light theme based on user preference."""
|
| 260 |
if not st.session_state.dark_mode:
|
|
|
|
| 282 |
</style>
|
| 283 |
""", unsafe_allow_html=True)
|
| 284 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 285 |
|
| 286 |
@st.cache_resource(show_spinner=False, hash_funcs={LocalAIEnhancerPipeline: lambda _: None})
|
| 287 |
def get_pipeline():
|
|
|
|
| 325 |
}
|
| 326 |
// Esc: Cancel processing
|
| 327 |
if (e.key === 'Escape') {
|
| 328 |
+
const cancelButton = Array.from(document.querySelectorAll('button')).find(b => b.textContent.includes('Cancel'));
|
| 329 |
if (cancelButton) {
|
| 330 |
cancelButton.click();
|
| 331 |
}
|
|
|
|
| 361 |
if "iter:" in line and "epoch:" in line:
|
| 362 |
match = re.search(r"epoch:\s*(\d+),\s*iter:\s*([\d,]+)", line)
|
| 363 |
eta_match = re.search(r"eta:\s*([\d:]+)", line)
|
| 364 |
+
loss_match = (
|
| 365 |
+
re.search(r"cross_entropy_loss:\s*([\d.e+-]+)", line) or
|
| 366 |
+
re.search(r"l_g_pix:\s*([\d.e+-]+)", line) or
|
| 367 |
+
re.search(r"l_g_percep:\s*([\d.e+-]+)", line) or
|
| 368 |
+
re.search(r"loss:\s*([\d.e+-]+)", line)
|
| 369 |
+
)
|
| 370 |
|
| 371 |
if match:
|
| 372 |
epoch = int(match.group(1))
|
pipeline.py
CHANGED
|
@@ -438,6 +438,10 @@ class LocalAIEnhancerPipeline:
|
|
| 438 |
h, w_img, _ = face_helper.input_img.shape
|
| 439 |
h_up, w_up = int(h * upscale), int(w_img * upscale)
|
| 440 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 441 |
# Initialize background image (upsampled background)
|
| 442 |
if bg_img is None:
|
| 443 |
upsample_img = cv2.resize(face_helper.input_img, (w_up, h_up), interpolation=cv2.INTER_LANCZOS4)
|
|
@@ -456,16 +460,16 @@ class LocalAIEnhancerPipeline:
|
|
| 456 |
restored_face_up = self.bg_upsampler_instance.enhance(restored_face, outscale=upscale)[0]
|
| 457 |
else:
|
| 458 |
# Fallback to Lanczos if no Real-ESRGAN instance loaded or face_upsample is disabled
|
| 459 |
-
restored_face_up = cv2.resize(restored_face, (
|
| 460 |
|
| 461 |
# Blend with original cropped face to preserve original high-resolution details when w > 0
|
| 462 |
if w > 0.0:
|
| 463 |
-
original_face_up = cv2.resize(cropped_face, (
|
| 464 |
restored_face_up = cv2.addWeighted(original_face_up, w, restored_face_up, 1.0 - w, 0.0)
|
| 465 |
|
| 466 |
inv_aff /= upscale
|
| 467 |
inv_aff[:, 2] *= upscale
|
| 468 |
-
face_size = (
|
| 469 |
inv_restored = cv2.warpAffine(restored_face_up, inv_aff, (w_up, h_up))
|
| 470 |
else:
|
| 471 |
# Blend with original cropped face to preserve original high-resolution details when w > 0
|
|
@@ -475,7 +479,7 @@ class LocalAIEnhancerPipeline:
|
|
| 475 |
# Add an offset to inverse affine matrix, for more precise back alignment
|
| 476 |
extra_offset = 0
|
| 477 |
inv_aff[:, 2] += extra_offset
|
| 478 |
-
face_size =
|
| 479 |
inv_restored = cv2.warpAffine(restored_face, inv_aff, (w_up, h_up))
|
| 480 |
|
| 481 |
# Create boundary mask
|
|
|
|
| 438 |
h, w_img, _ = face_helper.input_img.shape
|
| 439 |
h_up, w_up = int(h * upscale), int(w_img * upscale)
|
| 440 |
|
| 441 |
+
# Normalize face size to tuple just in case it is an integer in some facexlib versions
|
| 442 |
+
fs = face_helper.face_size
|
| 443 |
+
raw_face_size = fs if isinstance(fs, tuple) else (fs, fs)
|
| 444 |
+
|
| 445 |
# Initialize background image (upsampled background)
|
| 446 |
if bg_img is None:
|
| 447 |
upsample_img = cv2.resize(face_helper.input_img, (w_up, h_up), interpolation=cv2.INTER_LANCZOS4)
|
|
|
|
| 460 |
restored_face_up = self.bg_upsampler_instance.enhance(restored_face, outscale=upscale)[0]
|
| 461 |
else:
|
| 462 |
# Fallback to Lanczos if no Real-ESRGAN instance loaded or face_upsample is disabled
|
| 463 |
+
restored_face_up = cv2.resize(restored_face, (raw_face_size[0] * upscale, raw_face_size[1] * upscale), interpolation=cv2.INTER_LANCZOS4)
|
| 464 |
|
| 465 |
# Blend with original cropped face to preserve original high-resolution details when w > 0
|
| 466 |
if w > 0.0:
|
| 467 |
+
original_face_up = cv2.resize(cropped_face, (raw_face_size[0] * upscale, raw_face_size[1] * upscale), interpolation=cv2.INTER_LANCZOS4)
|
| 468 |
restored_face_up = cv2.addWeighted(original_face_up, w, restored_face_up, 1.0 - w, 0.0)
|
| 469 |
|
| 470 |
inv_aff /= upscale
|
| 471 |
inv_aff[:, 2] *= upscale
|
| 472 |
+
face_size = (raw_face_size[0] * upscale, raw_face_size[1] * upscale)
|
| 473 |
inv_restored = cv2.warpAffine(restored_face_up, inv_aff, (w_up, h_up))
|
| 474 |
else:
|
| 475 |
# Blend with original cropped face to preserve original high-resolution details when w > 0
|
|
|
|
| 479 |
# Add an offset to inverse affine matrix, for more precise back alignment
|
| 480 |
extra_offset = 0
|
| 481 |
inv_aff[:, 2] += extra_offset
|
| 482 |
+
face_size = raw_face_size
|
| 483 |
inv_restored = cv2.warpAffine(restored_face, inv_aff, (w_up, h_up))
|
| 484 |
|
| 485 |
# Create boundary mask
|