andevs commited on
Commit
fda4ae1
·
verified ·
1 Parent(s): 1961d09

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -35
app.py CHANGED
@@ -1,10 +1,9 @@
1
  #!/usr/bin/env python3
2
- # app.py - Background Remover v32.2.3
3
- # - ONNX arena OFF (BFC fragmentation was OOMing BiRefNet-lite at 896px)
4
- # - VEHICLE_RES_CAP 640, FRAME_MAX_DIM 640 (fits in CPU memory)
5
- # - Video default: silueta (fast enough for 50s proxy budget)
6
- # - Frames-batch: non-blocking + temporal alpha smoothing
7
- # - Bulk: original filename preserved, 50-cap server-side
8
 
9
  import io
10
  import time
@@ -19,7 +18,6 @@ import gc
19
  import shutil
20
  import zipfile
21
  import json
22
- import resource
23
  import uuid
24
  import base64
25
  import urllib.parse
@@ -33,9 +31,6 @@ import psutil
33
 
34
  # ============================================================
35
  # ONNX RUNTIME
36
- # Arena OFF. BFC fragmented on BiRefNet-lite's deformable ASPP
37
- # and produced 822MB single-buffer allocation failures at 896px.
38
- # Per-inference memory is now predictable at the cost of ~10% speed.
39
  # ============================================================
40
  try:
41
  import onnxruntime as _ort
@@ -422,16 +417,8 @@ class ContentClassifier:
422
  return 'complex'
423
 
424
 
425
- def limit_memory():
426
- try:
427
- soft, hard = resource.getrlimit(resource.RLIMIT_AS)
428
- resource.setrlimit(resource.RLIMIT_AS, (12 * 1024 * 1024 * 1024, hard))
429
- logger.info("Memory limit set to 12GB")
430
- except Exception as e:
431
- logger.warning(f"Could not set memory limit: {e}")
432
-
433
-
434
- limit_memory()
435
 
436
  os.environ["U2NET_HOME"] = "/tmp/u2net_models"
437
  os.environ["OMP_NUM_THREADS"] = "2"
@@ -860,7 +847,14 @@ def _prewarm_models():
860
  try:
861
  test_img = Image.new('RGB', (64, 64), (255, 255, 255))
862
  ImageDraw.Draw(test_img).rectangle([20, 20, 44, 44], fill=(220, 40, 40))
 
 
 
 
863
  for name, _ in PRELOAD_MODELS:
 
 
 
864
  session = model_manager.models.get(name)
865
  if session is None:
866
  continue
@@ -879,12 +873,13 @@ def _prewarm_models():
879
  logger.warning(f" {name} WRONG (center={ca} corner={corner})")
880
  except Exception as e:
881
  logger.warning(f" {name}: {type(e).__name__}: {e}")
 
882
  except Exception as e:
883
  logger.warning(f"Pre-warm skipped: {e}")
884
 
885
 
886
  logger.info("=" * 60)
887
- logger.info("Background Remover v32.2.3")
888
  logger.info("=" * 60)
889
  pre_download_models()
890
  initialize_models()
@@ -1019,8 +1014,6 @@ def analyze_image_complexity(image):
1019
  and cc_edge > 0.04
1020
  )
1021
 
1022
- # Vehicle path prefers BiRefNet-lite for quality on glossy surfaces.
1023
- # Falls back to Silueta if BiRefNet-lite isn't loaded.
1024
  if is_vehicle_like:
1025
  if has_birefnet:
1026
  return _route(
@@ -1259,7 +1252,7 @@ def process_image_sync(image_data, model_name=None, transparent=True,
1259
 
1260
 
1261
  # ============================================================
1262
- # VIDEO FRAME PIPELINE (BLOCKING WORKER + TEMPORAL SMOOTHING)
1263
  # ============================================================
1264
  def _process_frames_sync(raw_frames, resolved_model, transparent,
1265
  session_id: Optional[str] = None,
@@ -1362,7 +1355,7 @@ def _process_frames_sync(raw_frames, resolved_model, transparent,
1362
  # ============================================================
1363
  # FASTAPI
1364
  # ============================================================
1365
- app = FastAPI(title="Background Remover", version="32.2.3")
1366
  app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True,
1367
  allow_methods=["*"], allow_headers=["*"])
1368
 
@@ -1570,9 +1563,6 @@ async def process_bulk_images(
1570
  raise HTTPException(500, str(e)[:200])
1571
 
1572
 
1573
- # ============================================================
1574
- # FRAMES BATCH — non-blocking + hybrid temporal smoothing
1575
- # ============================================================
1576
  @app.post("/api/process/frames-batch")
1577
  async def process_frames_batch(
1578
  files: List[UploadFile] = File(...),
@@ -1734,6 +1724,7 @@ async def debug_env():
1734
  'matting_models': sorted(MATTING_MODELS),
1735
  'vehicle_res_cap': VEHICLE_RES_CAP,
1736
  'frame_max_dim': FRAME_MAX_DIM,
 
1737
  'alpha_smoothing': _alpha_cache_stats()}
1738
 
1739
 
@@ -1744,7 +1735,7 @@ async def home():
1744
  smoothing = _alpha_cache_stats()
1745
  return HTMLResponse(f"""
1746
  <!DOCTYPE html><html><head><meta charset="UTF-8">
1747
- <title>Background Remover v32.2.3</title>
1748
  <style>body{{font-family:system-ui;background:#0A0A0A;
1749
  color:#fff;min-height:100vh;display:flex;align-items:center;justify-content:center;
1750
  margin:0;padding:20px}}.c{{max-width:900px;background:#111;
@@ -1752,13 +1743,13 @@ async def home():
1752
  border:1px solid #222}}.s{{padding:15px;border-radius:12px;
1753
  margin:20px 0;background:#1a1a1a}}a{{color:#7ED957}}</style>
1754
  </head><body><div class="c">
1755
- <h1>Background Remover v32.2.3</h1>
1756
  <div class="s">AI online. {len(stats['loaded_models'])} models.
1757
  RAM {mem['percent']:.0f}% ({mem['used_mb']}/{mem['total_mb']}MB)</div>
1758
  <p>Default: <strong>ISNet</strong> · Vehicles/F1: <strong>BiRefNet-lite @ {VEHICLE_RES_CAP}px</strong></p>
1759
  <p>Video: <strong>{DEFAULT_VIDEO_MODEL}</strong> @ {FRAME_MAX_DIM}px · alpha smooth {smoothing['smooth_weight']}</p>
1760
  <p>Sessions cached: {smoothing['sessions']}/{smoothing['max_sessions']}</p>
1761
- <p>ONNX: arena=OFF</p>
1762
  <p><a href="/docs">API Docs</a></p>
1763
  </div></body></html>
1764
  """)
@@ -1781,7 +1772,7 @@ async def health_check():
1781
  'pymatting_available': PYMATTING_AVAILABLE,
1782
  'image_formats': ['png', 'jpg', 'jpeg', 'webp', 'bmp'],
1783
  'bulk_limit': 50,
1784
- 'version': '32.2.3',
1785
  'default_model': get_default_model(),
1786
  'default_video_model': DEFAULT_VIDEO_MODEL,
1787
  'preload_models': [n for n, _ in PRELOAD_MODELS],
@@ -1791,6 +1782,7 @@ async def health_check():
1791
  'vehicle_res_cap': VEHICLE_RES_CAP,
1792
  'frame_max_dim': FRAME_MAX_DIM,
1793
  'onnx_arena': False,
 
1794
  'alpha_smoothing': _alpha_cache_stats(),
1795
  'frame_batch_endpoint': '/api/process/frames-batch',
1796
  'frame_batch_size_max': 4,
@@ -1818,11 +1810,10 @@ async def gen_exc(request, exc):
1818
  @app.on_event("startup")
1819
  async def startup():
1820
  logger.info("=" * 60)
1821
- logger.info("v32.2.3 ready")
1822
  logger.info("ONNX: arena=OFF, mem_pattern=OFF")
 
1823
  logger.info("Video: Silueta default + temporal alpha smoothing")
1824
- logger.info(f"Smoothing weight: {ALPHA_SMOOTH_WEIGHT}, "
1825
- f"max sessions: {ALPHA_CACHE_MAX_SESSIONS}")
1826
  logger.info(f"Video default model: {DEFAULT_VIDEO_MODEL}")
1827
  logger.info(f"Video max frame dim: {FRAME_MAX_DIM}")
1828
  logger.info(f"Vehicle res cap: {VEHICLE_RES_CAP}")
 
1
  #!/usr/bin/env python3
2
+ # app.py - Background Remover v32.2.4
3
+ # - RLIMIT_AS removed (was causing spurious bad_alloc at 12GB VA)
4
+ # - BiRefNet-lite warmup skipped (was inflating RSS by ~6.8GB)
5
+ # - Silueta default for video; proxy forces it
6
+ # - ONNX arena OFF, VEHICLE_RES_CAP 640, FRAME_MAX_DIM 640
 
7
 
8
  import io
9
  import time
 
18
  import shutil
19
  import zipfile
20
  import json
 
21
  import uuid
22
  import base64
23
  import urllib.parse
 
31
 
32
  # ============================================================
33
  # ONNX RUNTIME
 
 
 
34
  # ============================================================
35
  try:
36
  import onnxruntime as _ort
 
417
  return 'complex'
418
 
419
 
420
+ # RLIMIT_AS removed — see note above.
421
+ logger.info("RLIMIT_AS not set — relying on cgroup memory.max")
 
 
 
 
 
 
 
 
422
 
423
  os.environ["U2NET_HOME"] = "/tmp/u2net_models"
424
  os.environ["OMP_NUM_THREADS"] = "2"
 
847
  try:
848
  test_img = Image.new('RGB', (64, 64), (255, 255, 255))
849
  ImageDraw.Draw(test_img).rectangle([20, 20, 44, 44], fill=(220, 40, 40))
850
+ # BiRefNet-lite warmup forces a 1024x1024 internal inference that
851
+ # reserves ~6 GB of transient allocator state which libc does not
852
+ # return to the OS on CPU-only boxes. Skip it.
853
+ WARMUP_SKIP = {'birefnet-general-lite'}
854
  for name, _ in PRELOAD_MODELS:
855
+ if name in WARMUP_SKIP:
856
+ logger.info(f" {name} skipped (heavy warmup)")
857
+ continue
858
  session = model_manager.models.get(name)
859
  if session is None:
860
  continue
 
873
  logger.warning(f" {name} WRONG (center={ca} corner={corner})")
874
  except Exception as e:
875
  logger.warning(f" {name}: {type(e).__name__}: {e}")
876
+ gc.collect()
877
  except Exception as e:
878
  logger.warning(f"Pre-warm skipped: {e}")
879
 
880
 
881
  logger.info("=" * 60)
882
+ logger.info("Background Remover v32.2.4")
883
  logger.info("=" * 60)
884
  pre_download_models()
885
  initialize_models()
 
1014
  and cc_edge > 0.04
1015
  )
1016
 
 
 
1017
  if is_vehicle_like:
1018
  if has_birefnet:
1019
  return _route(
 
1252
 
1253
 
1254
  # ============================================================
1255
+ # VIDEO FRAME PIPELINE
1256
  # ============================================================
1257
  def _process_frames_sync(raw_frames, resolved_model, transparent,
1258
  session_id: Optional[str] = None,
 
1355
  # ============================================================
1356
  # FASTAPI
1357
  # ============================================================
1358
+ app = FastAPI(title="Background Remover", version="32.2.4")
1359
  app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True,
1360
  allow_methods=["*"], allow_headers=["*"])
1361
 
 
1563
  raise HTTPException(500, str(e)[:200])
1564
 
1565
 
 
 
 
1566
  @app.post("/api/process/frames-batch")
1567
  async def process_frames_batch(
1568
  files: List[UploadFile] = File(...),
 
1724
  'matting_models': sorted(MATTING_MODELS),
1725
  'vehicle_res_cap': VEHICLE_RES_CAP,
1726
  'frame_max_dim': FRAME_MAX_DIM,
1727
+ 'rlimit_as': None,
1728
  'alpha_smoothing': _alpha_cache_stats()}
1729
 
1730
 
 
1735
  smoothing = _alpha_cache_stats()
1736
  return HTMLResponse(f"""
1737
  <!DOCTYPE html><html><head><meta charset="UTF-8">
1738
+ <title>Background Remover v32.2.4</title>
1739
  <style>body{{font-family:system-ui;background:#0A0A0A;
1740
  color:#fff;min-height:100vh;display:flex;align-items:center;justify-content:center;
1741
  margin:0;padding:20px}}.c{{max-width:900px;background:#111;
 
1743
  border:1px solid #222}}.s{{padding:15px;border-radius:12px;
1744
  margin:20px 0;background:#1a1a1a}}a{{color:#7ED957}}</style>
1745
  </head><body><div class="c">
1746
+ <h1>Background Remover v32.2.4</h1>
1747
  <div class="s">AI online. {len(stats['loaded_models'])} models.
1748
  RAM {mem['percent']:.0f}% ({mem['used_mb']}/{mem['total_mb']}MB)</div>
1749
  <p>Default: <strong>ISNet</strong> · Vehicles/F1: <strong>BiRefNet-lite @ {VEHICLE_RES_CAP}px</strong></p>
1750
  <p>Video: <strong>{DEFAULT_VIDEO_MODEL}</strong> @ {FRAME_MAX_DIM}px · alpha smooth {smoothing['smooth_weight']}</p>
1751
  <p>Sessions cached: {smoothing['sessions']}/{smoothing['max_sessions']}</p>
1752
+ <p>ONNX: arena=OFF · RLIMIT_AS: unset</p>
1753
  <p><a href="/docs">API Docs</a></p>
1754
  </div></body></html>
1755
  """)
 
1772
  'pymatting_available': PYMATTING_AVAILABLE,
1773
  'image_formats': ['png', 'jpg', 'jpeg', 'webp', 'bmp'],
1774
  'bulk_limit': 50,
1775
+ 'version': '32.2.4',
1776
  'default_model': get_default_model(),
1777
  'default_video_model': DEFAULT_VIDEO_MODEL,
1778
  'preload_models': [n for n, _ in PRELOAD_MODELS],
 
1782
  'vehicle_res_cap': VEHICLE_RES_CAP,
1783
  'frame_max_dim': FRAME_MAX_DIM,
1784
  'onnx_arena': False,
1785
+ 'rlimit_as': None,
1786
  'alpha_smoothing': _alpha_cache_stats(),
1787
  'frame_batch_endpoint': '/api/process/frames-batch',
1788
  'frame_batch_size_max': 4,
 
1810
  @app.on_event("startup")
1811
  async def startup():
1812
  logger.info("=" * 60)
1813
+ logger.info("v32.2.4 ready")
1814
  logger.info("ONNX: arena=OFF, mem_pattern=OFF")
1815
+ logger.info("RLIMIT_AS: unset (relying on cgroup memory.max)")
1816
  logger.info("Video: Silueta default + temporal alpha smoothing")
 
 
1817
  logger.info(f"Video default model: {DEFAULT_VIDEO_MODEL}")
1818
  logger.info(f"Video max frame dim: {FRAME_MAX_DIM}")
1819
  logger.info(f"Vehicle res cap: {VEHICLE_RES_CAP}")