MogensR commited on
Commit
d5540c9
·
verified ·
1 Parent(s): 390b954

Update processing/two_stage/quality_manager.py

Browse files
processing/two_stage/quality_manager.py CHANGED
@@ -1,6 +1,6 @@
1
  """
2
- Enhanced Quality Profile Manager for Two-Stage Processing
3
- THIS IS A NEW FILE - Create this to separate quality management logic
4
  """
5
  import os
6
  import logging
@@ -11,27 +11,27 @@
11
 
12
  @dataclass
13
  class QualityProfile:
14
- """Quality profile with all tunable parameters"""
15
  # MatAnyone refinement
16
  refine_enabled: bool = True
17
  refine_cadence: int = 3 # Process every N frames (1=every frame)
18
  refine_start_frame: int = 0 # Start refinement from this frame
19
 
20
- # Mask processing
21
  mask_dilate: int = 5 # Morphological dilation radius
22
  mask_blur: int = 3 # Gaussian blur for feathering
23
  mask_threshold: float = 0.5 # Binary threshold
24
 
25
- # Chroma keying
26
  chroma_tolerance: float = 30.0 # Color distance tolerance
27
  chroma_softness: float = 10.0 # Edge softness
28
  spill_suppression: float = 0.3 # Green/blue spill removal strength
29
 
30
- # Hybrid mixing
31
  hybrid_mix: float = 0.7 # 0=pure chroma, 1=pure segmentation
32
  temporal_smooth: float = 0.2 # Temporal consistency weight
33
 
34
- # Edge refinement
35
  edge_feather: int = 5 # Edge feathering radius
36
  edge_contrast: float = 1.2 # Edge contrast enhancement
37
 
@@ -42,19 +42,19 @@ class QualityProfile:
42
  max_resolution: int = 1080 # Max processing resolution
43
  batch_size: int = 1 # Frames to process in parallel
44
 
45
- # Define quality presets with VISIBLE differentiation
46
  QUALITY_PRESETS = {
47
  "speed": QualityProfile(
48
  refine_enabled=True,
49
  refine_cadence=10, # Refine every 10th frame only
50
  refine_start_frame=0,
51
- mask_dilate=3,
52
  mask_blur=1,
53
  mask_threshold=0.5,
54
- chroma_tolerance=40.0, # Less precise
55
  chroma_softness=15.0,
56
  spill_suppression=0.1, # Minimal spill work
57
- hybrid_mix=0.5, # Balanced mix
58
  temporal_smooth=0.1,
59
  edge_feather=2,
60
  edge_contrast=1.0,
@@ -69,9 +69,9 @@ class QualityProfile:
69
  mask_dilate=5,
70
  mask_blur=3,
71
  mask_threshold=0.5,
72
- chroma_tolerance=30.0,
73
- chroma_softness=10.0,
74
- spill_suppression=0.3,
75
  hybrid_mix=0.7, # Favor segmentation
76
  temporal_smooth=0.2,
77
  edge_feather=5,
@@ -82,41 +82,41 @@ class QualityProfile:
82
  ),
83
  "max": QualityProfile(
84
  refine_enabled=True,
85
- refine_cadence=1, # Refine EVERY frame
86
  refine_start_frame=0,
87
- mask_dilate=7, # Stronger hole filling
88
- mask_blur=5, # Smoother edges
89
- mask_threshold=0.45,
90
- chroma_tolerance=20.0, # More precise
91
- chroma_softness=5.0, # Sharper edges
92
- spill_suppression=0.6, # Strong spill removal
93
- hybrid_mix=0.85, # Heavy favor to segmentation
94
- temporal_smooth=0.3, # More temporal consistency
95
- edge_feather=7,
96
- edge_contrast=1.5, # Stronger edge enhancement
97
- bg_blur_sigma=2.0, # More background blur
98
- max_resolution=1920, # Full HD+
99
- batch_size=1
100
  )
101
  }
102
 
103
  class QualityManager:
104
- """Manages quality profiles and settings"""
105
 
106
  def __init__(self):
107
  self.current_profile: Optional[QualityProfile] = None
108
- self.profile_name: str = "balanced"
109
 
110
  def load_profile(self, profile_name: Optional[str] = None) -> QualityProfile:
111
  """Load quality profile from environment or parameter"""
112
- # Check environment variable first
113
  if profile_name is None:
114
- profile_name = os.environ.get("BFX_QUALITY", "balanced").lower()
115
 
116
  # Validate and load profile
117
  if profile_name not in QUALITY_PRESETS:
118
- logger.warning(f"Unknown quality profile '{profile_name}', using 'balanced'")
119
- profile_name = "balanced"
120
 
121
  self.profile_name = profile_name
122
  self.current_profile = QUALITY_PRESETS[profile_name]
@@ -134,6 +134,8 @@ def _profile_summary(self) -> str:
134
  p = self.current_profile
135
  return (
136
  f"refine_every={p.refine_cadence} frames, "
 
 
137
  f"spill={p.spill_suppression:.1f}, "
138
  f"hybrid_mix={p.hybrid_mix:.1f}, "
139
  f"edge_feather={p.edge_feather}, "
@@ -152,7 +154,7 @@ def should_refine_frame(self, frame_idx: int) -> bool:
152
  if frame_idx == 0:
153
  return True
154
 
155
- # Check cadence
156
  return (frame_idx % self.current_profile.refine_cadence) == 0
157
 
158
  def get_params(self) -> Dict[str, Any]:
@@ -173,8 +175,36 @@ def log_quality_impact(self, frame_idx: int, processing_time: float):
173
  f"Frame {frame_idx}: Skipped refinement (quality={self.profile_name}, "
174
  f"time={processing_time:.3f}s)"
175
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
- # Global instance
178
  quality_manager = QualityManager()
179
 
180
  def get_quality_profile(profile_name: Optional[str] = None) -> QualityProfile:
@@ -183,4 +213,15 @@ def get_quality_profile(profile_name: Optional[str] = None) -> QualityProfile:
183
 
184
  def should_refine_frame(frame_idx: int) -> bool:
185
  """Check if frame should be refined (convenience function)"""
186
- return quality_manager.should_refine_frame(frame_idx)
 
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
+ Enhanced Quality Profile Manager for Two-Stage Processing - MAXIMUM QUALITY VERSION
3
+ Updated to align with maximum quality SAM2 settings and aggressive mask cleaning
4
  """
5
  import os
6
  import logging
 
11
 
12
  @dataclass
13
  class QualityProfile:
14
+ """Quality profile with all tunable parameters - optimized for maximum quality"""
15
  # MatAnyone refinement
16
  refine_enabled: bool = True
17
  refine_cadence: int = 3 # Process every N frames (1=every frame)
18
  refine_start_frame: int = 0 # Start refinement from this frame
19
 
20
+ # Mask processing - enhanced for maximum quality
21
  mask_dilate: int = 5 # Morphological dilation radius
22
  mask_blur: int = 3 # Gaussian blur for feathering
23
  mask_threshold: float = 0.5 # Binary threshold
24
 
25
+ # Chroma keying - tightened for better precision
26
  chroma_tolerance: float = 30.0 # Color distance tolerance
27
  chroma_softness: float = 10.0 # Edge softness
28
  spill_suppression: float = 0.3 # Green/blue spill removal strength
29
 
30
+ # Hybrid mixing - favor segmentation for better quality
31
  hybrid_mix: float = 0.7 # 0=pure chroma, 1=pure segmentation
32
  temporal_smooth: float = 0.2 # Temporal consistency weight
33
 
34
+ # Edge refinement - enhanced for smoother results
35
  edge_feather: int = 5 # Edge feathering radius
36
  edge_contrast: float = 1.2 # Edge contrast enhancement
37
 
 
42
  max_resolution: int = 1080 # Max processing resolution
43
  batch_size: int = 1 # Frames to process in parallel
44
 
45
+ # Define quality presets with MAXIMUM QUALITY optimizations
46
  QUALITY_PRESETS = {
47
  "speed": QualityProfile(
48
  refine_enabled=True,
49
  refine_cadence=10, # Refine every 10th frame only
50
  refine_start_frame=0,
51
+ mask_dilate=2,
52
  mask_blur=1,
53
  mask_threshold=0.5,
54
+ chroma_tolerance=50.0, # Less precise for speed
55
  chroma_softness=15.0,
56
  spill_suppression=0.1, # Minimal spill work
57
+ hybrid_mix=0.4, # Favor chroma for speed
58
  temporal_smooth=0.1,
59
  edge_feather=2,
60
  edge_contrast=1.0,
 
69
  mask_dilate=5,
70
  mask_blur=3,
71
  mask_threshold=0.5,
72
+ chroma_tolerance=35.0,
73
+ chroma_softness=8.0,
74
+ spill_suppression=0.35,
75
  hybrid_mix=0.7, # Favor segmentation
76
  temporal_smooth=0.2,
77
  edge_feather=5,
 
82
  ),
83
  "max": QualityProfile(
84
  refine_enabled=True,
85
+ refine_cadence=1, # Refine EVERY frame for maximum quality
86
  refine_start_frame=0,
87
+ mask_dilate=8, # MAXIMUM: Aggressive hole filling to eliminate gaps
88
+ mask_blur=6, # MAXIMUM: Heavy smoothing for seamless edges
89
+ mask_threshold=0.4, # MAXIMUM: Lower threshold to keep more detail
90
+ chroma_tolerance=25.0, # MAXIMUM: Tighter tolerance for precision
91
+ chroma_softness=3.0, # MAXIMUM: Minimal softness for crisp edges
92
+ spill_suppression=0.6, # MAXIMUM: Strong spill removal
93
+ hybrid_mix=0.9, # MAXIMUM: Heavy favor to segmentation over chroma
94
+ temporal_smooth=0.4, # MAXIMUM: Strong temporal consistency
95
+ edge_feather=8, # MAXIMUM: Heavy edge feathering
96
+ edge_contrast=1.8, # MAXIMUM: Strong edge enhancement
97
+ bg_blur_sigma=2.5, # MAXIMUM: More background blur for seamless blend
98
+ max_resolution=1920, # MAXIMUM: Full HD+ processing
99
+ batch_size=1 # Single frame processing for stability
100
  )
101
  }
102
 
103
  class QualityManager:
104
+ """Manages quality profiles and settings with maximum quality optimizations"""
105
 
106
  def __init__(self):
107
  self.current_profile: Optional[QualityProfile] = None
108
+ self.profile_name: str = "max" # Default to maximum quality
109
 
110
  def load_profile(self, profile_name: Optional[str] = None) -> QualityProfile:
111
  """Load quality profile from environment or parameter"""
112
+ # Check environment variable first, default to max quality
113
  if profile_name is None:
114
+ profile_name = os.environ.get("BFX_QUALITY", "max").lower()
115
 
116
  # Validate and load profile
117
  if profile_name not in QUALITY_PRESETS:
118
+ logger.warning(f"Unknown quality profile '{profile_name}', using 'max' for best results")
119
+ profile_name = "max"
120
 
121
  self.profile_name = profile_name
122
  self.current_profile = QUALITY_PRESETS[profile_name]
 
134
  p = self.current_profile
135
  return (
136
  f"refine_every={p.refine_cadence} frames, "
137
+ f"mask_dilate={p.mask_dilate}, "
138
+ f"mask_blur={p.mask_blur}, "
139
  f"spill={p.spill_suppression:.1f}, "
140
  f"hybrid_mix={p.hybrid_mix:.1f}, "
141
  f"edge_feather={p.edge_feather}, "
 
154
  if frame_idx == 0:
155
  return True
156
 
157
+ # Check cadence - for max quality, refine every frame
158
  return (frame_idx % self.current_profile.refine_cadence) == 0
159
 
160
  def get_params(self) -> Dict[str, Any]:
 
175
  f"Frame {frame_idx}: Skipped refinement (quality={self.profile_name}, "
176
  f"time={processing_time:.3f}s)"
177
  )
178
+
179
+ def get_max_quality_params(self) -> Dict[str, Any]:
180
+ """Get parameters specifically optimized for maximum quality gap elimination"""
181
+ max_profile = QUALITY_PRESETS["max"]
182
+ params = asdict(max_profile)
183
+
184
+ # Add specific maximum quality enhancements
185
+ params.update({
186
+ # Aggressive morphological operations
187
+ "morph_close_kernel": 9, # Large closing kernel for gap filling
188
+ "morph_connect_kernel": 7, # Connect nearby regions
189
+ "gaussian_heavy_sigma": 2.0, # Heavy boundary smoothing
190
+ "gaussian_final_sigma": 1.0, # Final edge smoothing
191
+ "dilate_final_kernel": 3, # Final dilation for coverage
192
+
193
+ # Enhanced SAM2 integration
194
+ "sam2_points_per_side": 64, # Double density sampling
195
+ "sam2_confidence_threshold": 0.05, # Accept almost everything
196
+ "sam2_bbox_padding": 0.3, # 30% padding for full coverage
197
+ "sam2_refine_iterations": 5, # Maximum refinement iterations
198
+
199
+ # Quality flags
200
+ "enable_aggressive_cleaning": True,
201
+ "enable_heavy_smoothing": True,
202
+ "enable_gap_elimination": True,
203
+ })
204
+
205
+ return params
206
 
207
+ # Global instance with maximum quality default
208
  quality_manager = QualityManager()
209
 
210
  def get_quality_profile(profile_name: Optional[str] = None) -> QualityProfile:
 
213
 
214
  def should_refine_frame(frame_idx: int) -> bool:
215
  """Check if frame should be refined (convenience function)"""
216
+ return quality_manager.should_refine_frame(frame_idx)
217
+
218
+ def get_max_quality_settings() -> Dict[str, Any]:
219
+ """Get maximum quality settings for gap elimination"""
220
+ return quality_manager.get_max_quality_params()
221
+
222
+ def is_max_quality_enabled() -> bool:
223
+ """Check if maximum quality mode is active"""
224
+ return quality_manager.profile_name == "max"
225
+
226
+ # Initialize with maximum quality by default
227
+ quality_manager.load_profile("max")