iljung1106 commited on
Commit
5d8deba
·
1 Parent(s): 0f961a6

Removed lock

Browse files
Files changed (1) hide show
  1. inference_utils.py +33 -25
inference_utils.py CHANGED
@@ -2,7 +2,6 @@
2
  Three-View-Style-Embedder - Inference Utilities
3
  Lazy loading for Hugging Face Spaces compatibility
4
  """
5
- import threading
6
  from pathlib import Path
7
  from typing import List, Optional, Tuple
8
  import numpy as np
@@ -66,7 +65,7 @@ class FaceEyeExtractor:
66
  self.neighbors = neighbors
67
  self.eye_fallback_to_face = eye_fallback_to_face
68
 
69
- self._lock = threading.RLock()
70
  self._yolo_model = None
71
  self._yolo_device = None
72
  self._stride = 32
@@ -88,9 +87,9 @@ class FaceEyeExtractor:
88
  if self._yolo_model is not None and self._cascade is not None:
89
  return
90
 
91
- with self._lock:
92
- if self._yolo_model is not None and self._cascade is not None:
93
- return
94
 
95
  # Lazy import so app can still run if OpenCV/YOLO deps are missing.
96
  import sys
@@ -315,8 +314,7 @@ class FaceEyeExtractor:
315
 
316
  def extract_face(self, full_image: Image.Image) -> Optional[Image.Image]:
317
  rgb = np.array(full_image.convert('RGB'))
318
- with self._lock:
319
- boxes = self._detect_faces(rgb)
320
  if not boxes:
321
  return None
322
 
@@ -337,9 +335,8 @@ class FaceEyeExtractor:
337
  return Image.fromarray(face)
338
 
339
  def extract_eye_region(self, face_image: Image.Image) -> Optional[Image.Image]:
340
- # CascadeClassifier is not guaranteed to be thread-safe.
341
- with self._lock:
342
- self._ensure_ready()
343
 
344
  rgb_face = np.array(face_image.convert('RGB'))
345
  H, W = rgb_face.shape[:2]
@@ -445,7 +442,7 @@ class StyleEmbedderApp:
445
 
446
  # Model will be loaded lazily in @spaces.GPU decorated function
447
  self._model = None
448
- self._model_lock = threading.RLock()
449
  self._embeddings_loaded = False
450
  self._artist_names = None
451
  self._embeddings = None
@@ -470,10 +467,19 @@ class StyleEmbedderApp:
470
  if self._model is not None:
471
  return
472
 
473
- with self._model_lock:
474
- if self._model is not None:
475
- return
476
-
 
 
 
 
 
 
 
 
 
477
  print("Loading model (lazy)...")
478
  # Load checkpoint on CPU first
479
  checkpoint = torch.load(self.checkpoint_path, map_location='cpu')
@@ -500,22 +506,24 @@ class StyleEmbedderApp:
500
  self.embedding_dim = config.model.embedding_dim
501
 
502
  print("Model loaded successfully")
 
 
503
 
504
  def _ensure_embeddings_loaded(self):
505
  """Lazy load embeddings - no CUDA needed"""
506
  if self._embeddings_loaded:
507
  return
508
 
509
- with self._model_lock:
510
- if self._embeddings_loaded:
511
- return
512
-
513
- print("Loading embeddings...")
514
- data = np.load(self.embeddings_path)
515
- self._artist_names = data['artist_names'].tolist()
516
- self._embeddings = data['embeddings']
517
- self._embeddings_loaded = True
518
- print(f"Loaded {len(self._artist_names)} artist embeddings")
519
 
520
  def preprocess_image(self, image: Optional[Image.Image]) -> Optional[torch.Tensor]:
521
  """이미지 전처리"""
 
2
  Three-View-Style-Embedder - Inference Utilities
3
  Lazy loading for Hugging Face Spaces compatibility
4
  """
 
5
  from pathlib import Path
6
  from typing import List, Optional, Tuple
7
  import numpy as np
 
65
  self.neighbors = neighbors
66
  self.eye_fallback_to_face = eye_fallback_to_face
67
 
68
+ # No lock needed - Gradio runs synchronously
69
  self._yolo_model = None
70
  self._yolo_device = None
71
  self._stride = 32
 
87
  if self._yolo_model is not None and self._cascade is not None:
88
  return
89
 
90
+ # Double-check pattern (Gradio runs synchronously)
91
+ if self._yolo_model is not None and self._cascade is not None:
92
+ return
93
 
94
  # Lazy import so app can still run if OpenCV/YOLO deps are missing.
95
  import sys
 
314
 
315
  def extract_face(self, full_image: Image.Image) -> Optional[Image.Image]:
316
  rgb = np.array(full_image.convert('RGB'))
317
+ boxes = self._detect_faces(rgb)
 
318
  if not boxes:
319
  return None
320
 
 
335
  return Image.fromarray(face)
336
 
337
  def extract_eye_region(self, face_image: Image.Image) -> Optional[Image.Image]:
338
+ # Ensure ready (Gradio runs synchronously, so thread-safety not critical)
339
+ self._ensure_ready()
 
340
 
341
  rgb_face = np.array(face_image.convert('RGB'))
342
  H, W = rgb_face.shape[:2]
 
442
 
443
  # Model will be loaded lazily in @spaces.GPU decorated function
444
  self._model = None
445
+ self._model_loading = False # Flag to prevent concurrent loading
446
  self._embeddings_loaded = False
447
  self._artist_names = None
448
  self._embeddings = None
 
467
  if self._model is not None:
468
  return
469
 
470
+ # Simple double-check pattern (Gradio runs synchronously, so race condition unlikely)
471
+ if self._model_loading:
472
+ # Wait for loading to complete
473
+ import time
474
+ while self._model_loading and self._model is None:
475
+ time.sleep(0.01)
476
+ return
477
+
478
+ if self._model is not None:
479
+ return
480
+
481
+ self._model_loading = True
482
+ try:
483
  print("Loading model (lazy)...")
484
  # Load checkpoint on CPU first
485
  checkpoint = torch.load(self.checkpoint_path, map_location='cpu')
 
506
  self.embedding_dim = config.model.embedding_dim
507
 
508
  print("Model loaded successfully")
509
+ finally:
510
+ self._model_loading = False
511
 
512
  def _ensure_embeddings_loaded(self):
513
  """Lazy load embeddings - no CUDA needed"""
514
  if self._embeddings_loaded:
515
  return
516
 
517
+ # Simple check (Gradio runs synchronously)
518
+ if self._embeddings_loaded:
519
+ return
520
+
521
+ print("Loading embeddings...")
522
+ data = np.load(self.embeddings_path)
523
+ self._artist_names = data['artist_names'].tolist()
524
+ self._embeddings = data['embeddings']
525
+ self._embeddings_loaded = True
526
+ print(f"Loaded {len(self._artist_names)} artist embeddings")
527
 
528
  def preprocess_image(self, image: Optional[Image.Image]) -> Optional[torch.Tensor]:
529
  """이미지 전처리"""