trixy194t commited on
Commit
191d8ee
·
verified ·
1 Parent(s): cf52eaf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -8
app.py CHANGED
@@ -9,6 +9,7 @@ from fastapi import FastAPI, UploadFile, File, HTTPException
9
  from fastapi.middleware.cors import CORSMiddleware
10
  from typing import Optional, Dict, Any, List
11
  import warnings
 
12
 
13
  warnings.filterwarnings('ignore')
14
 
@@ -208,6 +209,36 @@ except Exception as e:
208
  yamnet_model = None
209
 
210
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  # ========================================
212
  # KAGGLE METHOD - FINE-TUNED MODEL
213
  # ========================================
@@ -587,7 +618,6 @@ def analyze_audio_segments(y, sr, model, segment_duration=10):
587
  def count_precise_apneas(y, sr, segment_results, min_apnea=1, max_apnea=60):
588
  """
589
  ACCURATE APNEA DETECTION
590
-
591
  RULES:
592
  1. Apnea is only valid when a confirmed snoring segment (HIGH or MEDIUM)
593
  exists IMMEDIATELY before AND immediately after the silence gap.
@@ -601,12 +631,10 @@ def count_precise_apneas(y, sr, segment_results, min_apnea=1, max_apnea=60):
601
  b) ML score check: gap audio scored by the fine-tuned model must be
602
  < 0.40 (model must agree it is NOT snoring).
603
  4. If total snoring count = 0, apnea is forced to 0.
604
-
605
  Risk Levels:
606
  - 10-15 seconds: LOW
607
  - 15-20 seconds: MEDIUM
608
  - 20+ seconds: HIGH
609
-
610
  Returns: (apnea_count, apnea_events_for_annotations)
611
  """
612
  print("\n🎯 APNEA DETECTION (Accurate - Immediate snoring before & after required)")
@@ -845,7 +873,6 @@ def validate_sleep_recording(y, sr):
845
  def calculate_apnea_risk(apnea_events: List[Dict[str, Any]]) -> str:
846
  """
847
  Calculate apnea risk based on the longest apnea duration
848
-
849
  Rules:
850
  - NO: No apnea detected
851
  - LOW: Apnea duration 10-15 seconds
@@ -880,7 +907,8 @@ async def root():
880
  "counting_feature": "Enabled - counts individual snores within detected segments" if new_counting_model else "Disabled",
881
  "apnea_detection": "HYBRID (Fast screening + ML validation)",
882
  "model_accuracy": "95.33%",
883
- "threshold_note": "Fine-tuned threshold: 0.55 (NO LOW confidence detection)"
 
884
  }
885
 
886
 
@@ -911,9 +939,9 @@ async def analyze_audio(file: UploadFile = File(...)):
911
  print(f" {'✅ PASS' if is_valid else '⚠️ WARNING'}: {validation_reason}")
912
  validation_warning = None if is_valid else validation_reason
913
 
914
- # 3. SKIP NOISE REDUCTION (REMOVED)
915
- y_clean = y
916
- print("⏭️ Noise reduction skipped (removed from pipeline)")
917
 
918
  # 4. ANALYZE with STRICT DUAL MODELS + NEW COUNTING
919
  print("\n🛡️ Using STRICT detection (HIGH and MEDIUM confidence only)...")
@@ -1011,6 +1039,7 @@ async def analyze_audio(file: UploadFile = File(...)):
1011
  "fine_tuned_threshold": 0.55,
1012
  "validation_approach": "Strict - only detecting HIGH and MEDIUM confidence snores",
1013
  "apnea_detection_method": "Hybrid (Fast screening + ML validation)",
 
1014
  "events": annotations
1015
  }
1016
 
 
9
  from fastapi.middleware.cors import CORSMiddleware
10
  from typing import Optional, Dict, Any, List
11
  import warnings
12
+ import noisereduce as nr
13
 
14
  warnings.filterwarnings('ignore')
15
 
 
209
  yamnet_model = None
210
 
211
 
212
+ # ========================================
213
+ # NOISE REDUCTION AND AUDIO PREPROCESSING
214
+ # ========================================
215
+ def clean_and_prepare_audio(y, sr):
216
+ """
217
+ Step 1: Apply noise reduction to clean the audio
218
+ Step 2: Format audio to proper shape for models
219
+ """
220
+ print(" 🧹 Applying noise reduction...")
221
+ try:
222
+ # Apply noise reduction using spectral gating method
223
+ y_clean = nr.reduce_noise(y=y, sr=sr, stationary=True, prop_decrease=0.8)
224
+ print(" ✅ Noise reduction completed")
225
+ except Exception as e:
226
+ print(f" ⚠️ Noise reduction failed: {e}, using original audio")
227
+ y_clean = y
228
+
229
+ # Normalize audio to proper amplitude range
230
+ print(" 📐 Formatting audio shape for models...")
231
+ y_clean = y_clean.astype(np.float32)
232
+
233
+ # Normalize to [-1, 1] range
234
+ max_val = np.max(np.abs(y_clean))
235
+ if max_val > 0:
236
+ y_clean = y_clean / max_val
237
+
238
+ print(" ✅ Audio prepared and shaped correctly")
239
+ return y_clean
240
+
241
+
242
  # ========================================
243
  # KAGGLE METHOD - FINE-TUNED MODEL
244
  # ========================================
 
618
  def count_precise_apneas(y, sr, segment_results, min_apnea=1, max_apnea=60):
619
  """
620
  ACCURATE APNEA DETECTION
 
621
  RULES:
622
  1. Apnea is only valid when a confirmed snoring segment (HIGH or MEDIUM)
623
  exists IMMEDIATELY before AND immediately after the silence gap.
 
631
  b) ML score check: gap audio scored by the fine-tuned model must be
632
  < 0.40 (model must agree it is NOT snoring).
633
  4. If total snoring count = 0, apnea is forced to 0.
 
634
  Risk Levels:
635
  - 10-15 seconds: LOW
636
  - 15-20 seconds: MEDIUM
637
  - 20+ seconds: HIGH
 
638
  Returns: (apnea_count, apnea_events_for_annotations)
639
  """
640
  print("\n🎯 APNEA DETECTION (Accurate - Immediate snoring before & after required)")
 
873
  def calculate_apnea_risk(apnea_events: List[Dict[str, Any]]) -> str:
874
  """
875
  Calculate apnea risk based on the longest apnea duration
 
876
  Rules:
877
  - NO: No apnea detected
878
  - LOW: Apnea duration 10-15 seconds
 
907
  "counting_feature": "Enabled - counts individual snores within detected segments" if new_counting_model else "Disabled",
908
  "apnea_detection": "HYBRID (Fast screening + ML validation)",
909
  "model_accuracy": "95.33%",
910
+ "threshold_note": "Fine-tuned threshold: 0.55 (NO LOW confidence detection)",
911
+ "noise_reduction": "Enabled - audio cleaned before analysis"
912
  }
913
 
914
 
 
939
  print(f" {'✅ PASS' if is_valid else '⚠️ WARNING'}: {validation_reason}")
940
  validation_warning = None if is_valid else validation_reason
941
 
942
+ # 3. CLEAN AND PREPARE AUDIO (NEW STEP)
943
+ print("\n🧹 Cleaning and preparing audio...")
944
+ y_clean = clean_and_prepare_audio(y, sr)
945
 
946
  # 4. ANALYZE with STRICT DUAL MODELS + NEW COUNTING
947
  print("\n🛡️ Using STRICT detection (HIGH and MEDIUM confidence only)...")
 
1039
  "fine_tuned_threshold": 0.55,
1040
  "validation_approach": "Strict - only detecting HIGH and MEDIUM confidence snores",
1041
  "apnea_detection_method": "Hybrid (Fast screening + ML validation)",
1042
+ "noise_reduction_applied": True,
1043
  "events": annotations
1044
  }
1045