babycry / app.py
Jitender1278's picture
added app.py
5a88a2b verified
raw
history blame
14.1 kB
# app.py - Baby Cry Classification for HuggingFace Spaces
import gradio as gr
import numpy as np
import librosa
import joblib
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder, StandardScaler
import warnings
import tempfile
import os
from datetime import datetime
warnings.filterwarnings('ignore')
class BabyCryClassifier:
"""Baby Cry Classification Model for HuggingFace Spaces"""
def __init__(self):
self.model = None
self.scaler = None
self.label_encoder = None
self.is_trained = False
self.categories = ["belly_pain", "burping", "discomfort", "hunger", "tiredness"]
self._initialize_model()
def _initialize_model(self):
"""Initialize and train the model with synthetic data"""
try:
self.model = RandomForestClassifier(n_estimators=100, random_state=42, max_depth=15)
self.scaler = StandardScaler()
self.label_encoder = LabelEncoder()
self.label_encoder.fit(self.categories)
self._create_synthetic_model()
except Exception as e:
raise Exception(f"Failed to initialize model: {str(e)}")
def _create_synthetic_model(self):
"""Create synthetic training data for demonstration"""
np.random.seed(42)
n_samples = 2000
n_features = 50
# Generate realistic audio features
X_synthetic = np.random.randn(n_samples, n_features)
y_synthetic = []
for i in range(n_samples):
if X_synthetic[i, 0] > 1.5: # High energy -> hunger
label = "hunger"
elif X_synthetic[i, 1] > 1.2: # High pitch variation -> discomfort
label = "discomfort"
elif X_synthetic[i, 2] > 1.0: # Rhythmic pattern -> tiredness
label = "tiredness"
elif X_synthetic[i, 3] > 0.8: # Specific frequency -> belly_pain
label = "belly_pain"
else:
label = "burping"
y_synthetic.append(label)
# Train the model
X_scaled = self.scaler.fit_transform(X_synthetic)
y_encoded = self.label_encoder.transform(y_synthetic)
self.model.fit(X_scaled, y_encoded)
self.is_trained = True
def extract_features(self, audio_file_path):
"""Extract comprehensive audio features"""
try:
# Load audio file
y, sr = librosa.load(audio_file_path, sr=22050, duration=30)
if len(y) < 1000: # Too short
return None
# Extract features
# 1. MFCC Features
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
mfccs_mean = np.mean(mfccs.T, axis=0)
mfccs_std = np.std(mfccs.T, axis=0)
# 2. Chroma Features
chroma = librosa.feature.chroma(y=y, sr=sr)
chroma_mean = np.mean(chroma.T, axis=0)
# 3. Spectral Features
spectral_centroids = librosa.feature.spectral_centroid(y=y, sr=sr)
spectral_rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)
spectral_bandwidth = librosa.feature.spectral_bandwidth(y=y, sr=sr)
# 4. Other features
zcr = librosa.feature.zero_crossing_rate(y)
rms = librosa.feature.rms(y=y)
tempo, _ = librosa.beat.beat_track(y=y, sr=sr)
# 5. Fundamental frequency
pitches, magnitudes = librosa.piptrack(y=y, sr=sr)
f0_values = []
for t in range(pitches.shape[1]):
index = magnitudes[:, t].argmax()
pitch = pitches[index, t]
if pitch > 0:
f0_values.append(pitch)
avg_f0 = np.mean(f0_values) if f0_values else 0
# Combine all features
features = np.concatenate([
mfccs_mean, # 13 features
mfccs_std, # 13 features
chroma_mean, # 12 features
[np.mean(spectral_centroids)], # 1 feature
[np.mean(spectral_rolloff)], # 1 feature
[np.mean(spectral_bandwidth)], # 1 feature
[np.mean(zcr)], # 1 feature
[np.mean(rms)], # 1 feature
[tempo], # 1 feature
[avg_f0], # 1 feature
[len(y)/sr], # Duration: 1 feature
[np.var(y)], # Variance: 1 feature
[np.std(y)], # Std dev: 1 feature
[np.max(y) - np.min(y)] # Range: 1 feature
])
# Ensure exactly 50 features
if len(features) < 50:
features = np.pad(features, (0, 50 - len(features)), 'constant')
else:
features = features[:50]
return features
except Exception as e:
print(f"Error extracting features: {str(e)}")
return None
def predict(self, audio_file_path):
"""Main prediction method"""
if not self.is_trained:
return {"success": False, "error": "Model not trained"}
# Extract features
features = self.extract_features(audio_file_path)
if features is None:
return {"success": False, "error": "Could not extract features from audio file"}
try:
# Reshape and scale features
features = features.reshape(1, -1)
features_scaled = self.scaler.transform(features)
# Make prediction
prediction_encoded = self.model.predict(features_scaled)[0]
prediction_proba = self.model.predict_proba(features_scaled)[0]
# Convert back to label
predicted_label = self.label_encoder.inverse_transform([prediction_encoded])[0]
confidence = np.max(prediction_proba)
# Get all probabilities
all_probabilities = {}
for i, category in enumerate(self.categories):
all_probabilities[category] = float(prediction_proba[i])
return {
"success": True,
"prediction": predicted_label,
"confidence": float(confidence),
"all_probabilities": all_probabilities
}
except Exception as e:
return {"success": False, "error": f"Prediction error: {str(e)}"}
# Initialize classifier
classifier = BabyCryClassifier()
# Interpretations for baby needs
INTERPRETATIONS = {
"hunger": {
"message": "🍼 Your baby is likely hungry",
"recommendations": [
"Try feeding your baby",
"Check if it's been 2-3 hours since last feeding",
"Look for hunger cues like rooting or sucking motions"
]
},
"tiredness": {
"message": "😴 Your baby seems tired and needs sleep",
"recommendations": [
"Put baby in a quiet, dark environment",
"Try gentle rocking or swaddling",
"Check if baby has been awake for 1-2 hours"
]
},
"discomfort": {
"message": "😣 Your baby appears uncomfortable",
"recommendations": [
"Check diaper and change if needed",
"Adjust clothing - too hot or cold?",
"Look for any hair wrapped around fingers/toes",
"Try different holding positions"
]
},
"belly_pain": {
"message": "🀱 Your baby might have belly pain or gas",
"recommendations": [
"Try gentle tummy massage in clockwise circles",
"Hold baby upright and pat back gently",
"Bicycle baby's legs to help with gas",
"Consider if baby needs to burp"
]
},
"burping": {
"message": "🫧 Your baby likely needs to burp",
"recommendations": [
"Hold baby upright against your chest",
"Gently pat or rub baby's back",
"Try different burping positions",
"Be patient - some babies take time to burp"
]
}
}
def classify_baby_cry(audio_file):
"""Main function for Gradio interface"""
if audio_file is None:
return "Please upload an audio file"
try:
# Get prediction
result = classifier.predict(audio_file)
if not result["success"]:
return f"❌ Error: {result['error']}"
# Format results
prediction = result["prediction"]
confidence = result["confidence"]
all_probs = result["all_probabilities"]
# Get interpretation
interpretation = INTERPRETATIONS.get(prediction, {
"message": "πŸ€” Unknown cry type detected",
"recommendations": ["Monitor baby and consult healthcare provider if concerned"]
})
# Create detailed response
response = f"""
## 🍼 Baby Cry Analysis Results
### 🎯 Primary Prediction
**{prediction.replace('_', ' ').title()}** (Confidence: {confidence:.1%})
{interpretation["message"]}
### πŸ“Š Detailed Probabilities
"""
# Sort probabilities by confidence
sorted_probs = sorted(all_probs.items(), key=lambda x: x[1], reverse=True)
for category, prob in sorted_probs:
category_display = category.replace('_', ' ').title()
bar_length = int(prob * 20) # Scale to 20 characters
bar = "β–ˆ" * bar_length + "β–‘" * (20 - bar_length)
response += f"\n**{category_display}**: {prob:.1%} {bar}"
# Add recommendations
response += f"""
### πŸ’‘ Recommendations
"""
for i, rec in enumerate(interpretation["recommendations"], 1):
response += f"\n{i}. {rec}"
response += f"""
### ⚠️ Important Notes
- This is an AI prediction for informational purposes only
- Trust your parental instincts
- Every baby is unique with different cry patterns
- Consult healthcare providers for medical concerns
---
*Analysis completed at {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}*
"""
return response
except Exception as e:
return f"❌ Error processing audio: {str(e)}"
# Create Gradio interface
with gr.Blocks(title="🍼 Baby Cry Classifier", theme=gr.themes.Soft()) as demo:
gr.HTML("""
<div style="text-align: center; margin-bottom: 20px;">
<h1>🍼 Baby Cry Classifier</h1>
<p><em>AI-powered analysis to understand your baby's needs</em></p>
</div>
""")
gr.Markdown("""
## How it works
Upload an audio recording of your baby crying, and our AI will analyze it to predict what your baby needs:
- 🍼 **Hunger** - Baby needs feeding
- 😴 **Tiredness** - Baby needs sleep
- 😣 **Discomfort** - Check diaper or comfort
- 🀱 **Belly Pain** - May need burping or tummy massage
- 🫧 **Burping** - Baby needs to release gas
""")
with gr.Row():
with gr.Column(scale=1):
audio_input = gr.Audio(
label="Upload Baby Cry Audio 🎀",
type="filepath",
sources=["upload", "microphone"]
)
classify_btn = gr.Button(
"πŸ” Analyze Baby Cry",
variant="primary",
size="lg"
)
gr.Markdown("""
### πŸ“ Tips for best results:
- Use clear audio with minimal background noise
- 3-10 second clips work best
- Record during active crying
- Supported formats: WAV, MP3, M4A, FLAC
""")
with gr.Column(scale=2):
output_display = gr.Markdown(
value="""
## πŸ‘‹ Welcome!
Upload an audio file of your baby crying and click **"Analyze Baby Cry"** to get started.
The AI will analyze the audio and provide:
- 🎯 Primary prediction with confidence level
- πŸ“Š Detailed probability breakdown
- πŸ’‘ Actionable recommendations
- ⚠️ Important safety notes
*Ready to help you understand your baby's needs!*
""",
label="Analysis Results"
)
# Set up event handlers
classify_btn.click(
fn=classify_baby_cry,
inputs=[audio_input],
outputs=[output_display]
)
# Footer with additional information
gr.Markdown("""
---
## πŸ”¬ About This Tool
This baby cry classifier uses machine learning to analyze audio features including:
- **MFCC (Mel-frequency cepstral coefficients)** - Captures spectral characteristics
- **Chroma features** - Represents pitch patterns
- **Spectral analysis** - Measures brightness and bandwidth of sound
- **Temporal features** - Analyzes rhythm and duration patterns
The model is trained to recognize 5 categories of baby cries based on research in infant communication.
## ⚠️ Important Disclaimer
- This tool is for **informational purposes only**
- **Not a substitute for medical advice**
- Always trust your parental instincts
- Consult healthcare providers for medical concerns
- Every baby has unique crying patterns
---
*Built with ❀️ for parents worldwide | Powered by Gradio & Machine Learning*
""")
# Launch the interface
if __name__ == "__main__":
demo.launch()