MogensR commited on
Commit
8179154
·
verified ·
1 Parent(s): 3e4b062

Create debug_positioning.py

Browse files
Files changed (1) hide show
  1. debug_positioning.py +237 -0
debug_positioning.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Quick test script to validate positioning fixes before full video processing.
4
+ Run this to verify coordinate calculations are working correctly.
5
+ """
6
+
7
+ import numpy as np
8
+ import cv2
9
+ import os
10
+ from pathlib import Path
11
+
12
+ def test_coordinate_calculations():
13
+ """Test coordinate calculations with various placement scenarios"""
14
+
15
+ print("=== COORDINATE CALCULATION TESTS ===\n")
16
+
17
+ # Simulate video dimensions
18
+ video_dims = [(720, 1280), (1080, 1920), (480, 640)] # (H, W)
19
+
20
+ test_placements = [
21
+ {"name": "Center", "x": 0.5, "y": 0.5, "scale": 1.0},
22
+ {"name": "Bottom Center", "x": 0.5, "y": 0.75, "scale": 1.0},
23
+ {"name": "Top Right", "x": 0.8, "y": 0.2, "scale": 0.7},
24
+ {"name": "Bottom Left Small", "x": 0.2, "y": 0.9, "scale": 0.5},
25
+ {"name": "Large Center", "x": 0.5, "y": 0.5, "scale": 1.5},
26
+ ]
27
+
28
+ for h, w in video_dims:
29
+ print(f"Video Resolution: {w}x{h}")
30
+ print("-" * 40)
31
+
32
+ for test in test_placements:
33
+ px, py, ps = test["x"], test["y"], test["scale"]
34
+
35
+ # Calculate coordinates (same logic as app.py)
36
+ sw = max(1, round(w * ps))
37
+ sh = max(1, round(h * ps))
38
+ cx = round(px * w)
39
+ cy = round(py * h)
40
+ x0 = cx - sw // 2
41
+ y0 = cy - sh // 2
42
+
43
+ # Bounds checking
44
+ xs0 = max(0, x0)
45
+ ys0 = max(0, y0)
46
+ xs1 = min(w, x0 + sw)
47
+ ys1 = min(h, y0 + sh)
48
+
49
+ # Check validity
50
+ valid = xs1 > xs0 and ys1 > ys0
51
+ clipped = x0 < 0 or y0 < 0 or (x0 + sw) > w or (y0 + sh) > h
52
+
53
+ print(f" {test['name']:15} | Center: ({cx:4d}, {cy:4d}) | Size: {sw:4d}x{sh:4d} | Valid: {valid} | Clipped: {clipped}")
54
+
55
+ if not valid:
56
+ print(f" ERROR: Invalid bounds ({xs0}, {ys0}) to ({xs1}, {ys1})")
57
+
58
+ print()
59
+
60
+ def create_test_visualization():
61
+ """Create visual test to verify positioning logic"""
62
+
63
+ print("=== CREATING POSITIONING VISUALIZATION ===\n")
64
+
65
+ # Test canvas
66
+ canvas_w, canvas_h = 800, 600
67
+ canvas = np.zeros((canvas_h, canvas_w, 3), dtype=np.uint8)
68
+ canvas.fill(50) # Dark gray background
69
+
70
+ # Test subject dimensions (simulating scaled subject)
71
+ subject_w, subject_h = 200, 300
72
+
73
+ test_positions = [
74
+ {"x": 0.2, "y": 0.3, "color": (255, 0, 0)}, # Red - top left
75
+ {"x": 0.8, "y": 0.3, "color": (0, 255, 0)}, # Green - top right
76
+ {"x": 0.5, "y": 0.5, "color": (0, 0, 255)}, # Blue - center
77
+ {"x": 0.3, "y": 0.8, "color": (255, 255, 0)}, # Cyan - bottom left
78
+ {"x": 0.7, "y": 0.8, "color": (255, 0, 255)}, # Magenta - bottom right
79
+ ]
80
+
81
+ for i, pos in enumerate(test_positions):
82
+ px, py = pos["x"], pos["y"]
83
+ color = pos["color"]
84
+
85
+ # Calculate placement (same as app.py logic)
86
+ cx = round(px * canvas_w)
87
+ cy = round(py * canvas_h)
88
+ x0 = cx - subject_w // 2
89
+ y0 = cy - subject_h // 2
90
+
91
+ # Bounds
92
+ xs0 = max(0, x0)
93
+ ys0 = max(0, y0)
94
+ xs1 = min(canvas_w, x0 + subject_w)
95
+ ys1 = min(canvas_h, y0 + subject_h)
96
+
97
+ if xs1 > xs0 and ys1 > ys0:
98
+ # Draw subject rectangle
99
+ cv2.rectangle(canvas, (xs0, ys0), (xs1-1, ys1-1), color, 2)
100
+
101
+ # Draw center cross
102
+ cv2.line(canvas, (cx-10, cy), (cx+10, cy), color, 2)
103
+ cv2.line(canvas, (cx, cy-10), (cx, cy+10), color, 2)
104
+
105
+ # Add label
106
+ cv2.putText(canvas, f"({px:.1f}, {py:.1f})", (cx-30, cy-20),
107
+ cv2.FONT_HERSHEY_SIMPLEX, 0.4, color, 1)
108
+
109
+ print(f"Position {i+1}: ({px:.1f}, {py:.1f}) -> Center ({cx}, {cy}) -> Rect ({xs0}, {ys0}) to ({xs1}, {ys1})")
110
+ else:
111
+ print(f"Position {i+1}: ({px:.1f}, {py:.1f}) -> OUT OF BOUNDS")
112
+
113
+ # Save test image
114
+ output_path = "positioning_test_visualization.png"
115
+ cv2.imwrite(output_path, canvas)
116
+ print(f"\nVisualization saved: {output_path}")
117
+
118
+ return output_path
119
+
120
+ def test_ui_parameter_flow():
121
+ """Test that UI slider values correctly flow through to positioning"""
122
+
123
+ print("=== UI PARAMETER FLOW TEST ===\n")
124
+
125
+ # Simulate Gradio slider values
126
+ gradio_values = {
127
+ "place_x": 0.7, # 70% from left
128
+ "place_y": 0.3, # 30% from top
129
+ "place_scale": 1.2, # 120% scale
130
+ "place_feather": 5 # 5px feather
131
+ }
132
+
133
+ # Simulate placement dict creation (from Gradio interface)
134
+ placement = {
135
+ "x": gradio_values["place_x"],
136
+ "y": gradio_values["place_y"],
137
+ "scale": gradio_values["place_scale"],
138
+ "feather": gradio_values["place_feather"]
139
+ }
140
+
141
+ print("Gradio slider values:")
142
+ for key, val in gradio_values.items():
143
+ print(f" {key}: {val}")
144
+
145
+ print(f"\nPlacement dict: {placement}")
146
+
147
+ # Test parameter extraction (same as app.py)
148
+ px = max(0.0, min(1.0, float(placement.get("x", 0.5))))
149
+ py = max(0.0, min(1.0, float(placement.get("y", 0.75))))
150
+ ps = max(0.3, min(2.0, float(placement.get("scale", 1.0))))
151
+ feather_px = max(0, min(50, int(placement.get("feather", 3))))
152
+
153
+ print("\nExtracted and clamped values:")
154
+ print(f" px (x): {px}")
155
+ print(f" py (y): {py}")
156
+ print(f" ps (scale): {ps}")
157
+ print(f" feather_px: {feather_px}")
158
+
159
+ # Verify no unexpected transformations
160
+ expected_x = gradio_values["place_x"]
161
+ expected_y = gradio_values["place_y"]
162
+ expected_scale = gradio_values["place_scale"]
163
+ expected_feather = gradio_values["place_feather"]
164
+
165
+ if abs(px - expected_x) < 0.001 and abs(py - expected_y) < 0.001:
166
+ print("\n✅ Parameter flow is correct!")
167
+ else:
168
+ print(f"\n❌ Parameter flow issue!")
169
+ print(f" Expected x: {expected_x}, got: {px}")
170
+ print(f" Expected y: {expected_y}, got: {py}")
171
+
172
+ return px == expected_x and py == expected_y
173
+
174
+ def test_scaling_calculations():
175
+ """Test scaling calculations for different scenarios"""
176
+
177
+ print("=== SCALING CALCULATION TESTS ===\n")
178
+
179
+ base_dims = [(720, 1280), (1080, 1920)]
180
+ scale_factors = [0.5, 0.75, 1.0, 1.25, 1.5]
181
+
182
+ for h, w in base_dims:
183
+ print(f"Base dimensions: {w}x{h}")
184
+ print("-" * 30)
185
+
186
+ for scale in scale_factors:
187
+ # Test both int() and round() approaches
188
+ sw_int = max(1, int(w * scale))
189
+ sh_int = max(1, int(h * scale))
190
+ sw_round = max(1, round(w * scale))
191
+ sh_round = max(1, round(h * scale))
192
+
193
+ print(f" Scale {scale:4.2f} | int(): {sw_int:4d}x{sh_int:4d} | round(): {sw_round:4d}x{sh_round:4d}")
194
+
195
+ if sw_int != sw_round or sh_int != sh_round:
196
+ print(f" ^ Different results! Using round() is more accurate.")
197
+
198
+ print()
199
+
200
+ def main():
201
+ """Run all positioning tests"""
202
+
203
+ print("🎬 VIDEO BACKGROUND REPLACEMENT - POSITIONING TESTS")
204
+ print("=" * 60)
205
+
206
+ # Test 1: Coordinate calculations
207
+ test_coordinate_calculations()
208
+
209
+ # Test 2: UI parameter flow
210
+ ui_flow_ok = test_ui_parameter_flow()
211
+
212
+ # Test 3: Scaling calculations
213
+ test_scaling_calculations()
214
+
215
+ # Test 4: Visual verification
216
+ viz_path = create_test_visualization()
217
+
218
+ # Summary
219
+ print("=" * 60)
220
+ print("TEST SUMMARY:")
221
+ print(f"✅ Coordinate calculations: Tested")
222
+ print(f"{'✅' if ui_flow_ok else '❌'} UI parameter flow: {'OK' if ui_flow_ok else 'Issues detected'}")
223
+ print(f"✅ Scaling calculations: Tested")
224
+ print(f"✅ Visual verification: {viz_path}")
225
+
226
+ if not ui_flow_ok:
227
+ print("\n⚠️ UI parameter flow issues detected!")
228
+ print(" Check that Gradio slider values are correctly passed to placement dict.")
229
+
230
+ print(f"\n🔧 Next steps:")
231
+ print("1. Review coordinate calculation results above")
232
+ print("2. Check the generated visualization image")
233
+ print("3. Apply the enhanced composite_frame function to your app.py")
234
+ print("4. Test with a small video file first")
235
+
236
+ if __name__ == "__main__":
237
+ main()