"""Gradio demo app for AnomalyMachine-50K dataset anomaly detection.""" import os import tempfile from pathlib import Path import gradio as gr # Fix Gradio 4.35/4.44 API info crash when JSON schema has boolean (e.g. additionalProperties: true) import gradio_client.utils as _client_utils _orig_get_type = _client_utils.get_type def _get_type_handle_bool(schema): if isinstance(schema, bool): return "boolean" return _orig_get_type(schema) _client_utils.get_type = _get_type_handle_bool import librosa import matplotlib matplotlib.use("Agg") # Non-interactive backend import matplotlib.pyplot as plt import numpy as np # Dataset metadata DATASET_INFO = { "total_clips": 50000, "machines": ["fan", "pump", "compressor", "conveyor_belt", "electric_motor", "valve"], "normal_ratio": 0.6, "anomalous_ratio": 0.4, "clip_duration_seconds": 10.0, "sample_rate": 22050, "total_hours": round(50000 * 10.0 / 3600, 2), } # Anomaly subtypes mapping ANOMALY_SUBTYPES = { "fan": ["bearing_fault", "imbalance", "obstruction"], "pump": ["bearing_fault", "cavitation", "overheating"], "compressor": ["bearing_fault", "imbalance", "overheating"], "conveyor_belt": ["obstruction"], "electric_motor": ["bearing_fault", "imbalance", "overheating"], "valve": ["cavitation", "obstruction"], } # Placeholder model - replace with actual trained model MODEL_NAME = "YOUR_HF_USERNAME/AnomalyMachine-Classifier" model = None def load_model(): """Lazy load the audio classification model. Uses placeholder if transformers unavailable.""" global model if model is None: try: from transformers import pipeline model = pipeline( "audio-classification", model=MODEL_NAME, ) except Exception as e: print(f"Using placeholder predictions (no model): {e}") model = "placeholder" return model def create_mel_spectrogram(audio_path: str, title: str = "Mel Spectrogram") -> str: """Create a mel spectrogram visualization from audio file.""" try: y, sr = librosa.load(audio_path, sr=22050, mono=True) mel_spec = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128, fmax=8000) mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max) fig, ax = plt.subplots(figsize=(10, 4)) img = librosa.display.specshow( mel_spec_db, x_axis="time", y_axis="mel", sr=sr, fmax=8000, ax=ax, cmap="viridis", ) ax.set_title(title, fontsize=14, fontweight="bold") plt.colorbar(img, ax=ax, format="%+2.0f dB") plt.tight_layout() # Save to temporary file temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png") plt.savefig(temp_file.name, dpi=100, bbox_inches="tight") plt.close() return temp_file.name except Exception as e: print(f"Error creating spectrogram: {e}") return None def get_reference_audio(machine_type: str) -> str: """Get path to reference normal audio for a machine type.""" examples_dir = Path(__file__).parent / "examples" # Look for a normal example (naming convention: {machine}_normal_*.wav) ref_pattern = f"{machine_type}_*_normal_*.wav" ref_files = list(examples_dir.glob(ref_pattern)) if not ref_files: # Fallback: use any example for this machine ref_files = list(examples_dir.glob(f"{machine_type}_*.wav")) return str(ref_files[0]) if ref_files else None def predict_anomaly(audio_file, machine_type): """Predict if audio contains an anomaly.""" if audio_file is None: return None, None, None, None, None # Load model model_instance = load_model() # Create spectrograms input_spec = create_mel_spectrogram(audio_file, f"Input Audio - {machine_type}") ref_audio = get_reference_audio(machine_type) ref_spec = None if ref_audio: ref_spec = create_mel_spectrogram(ref_audio, f"Reference Normal - {machine_type}") # Make prediction if model_instance == "placeholder": # Placeholder predictions for demo import random is_anomaly = random.random() > 0.5 confidence = random.uniform(0.7, 0.95) if is_anomaly: anomaly_subtype = random.choice(ANOMALY_SUBTYPES.get(machine_type, ["unknown"])) label = "ANOMALY" color = "red" else: anomaly_subtype = "none" label = "NORMAL" color = "green" else: # Real model prediction try: results = model_instance(audio_file) # Assuming model returns list of dicts with 'label' and 'score' top_result = results[0] if isinstance(results, list) else results label_str = top_result.get("label", "").lower() confidence = top_result.get("score", 0.5) is_anomaly = "anomaly" in label_str or "anomalous" in label_str if is_anomaly: label = "ANOMALY" color = "red" # Try to extract anomaly subtype from label anomaly_subtype = "unknown" for subtype in ANOMALY_SUBTYPES.get(machine_type, []): if subtype in label_str: anomaly_subtype = subtype break else: label = "NORMAL" color = "green" anomaly_subtype = "none" except Exception as e: print(f"Prediction error: {e}") label = "ERROR" color = "gray" confidence = 0.0 anomaly_subtype = "none" # Format result HTML result_html = f"""
Anomaly Type: {anomaly_subtype.replace("_", " ").title()}
' if anomaly_subtype != 'none' else ''}Confidence: {confidence:.1%}
Synthetic Industrial Machine Sound Anomaly Detection Dataset
License: CC-BY 4.0 | Dataset: AnomalyMachine-50K | GitHub: mandip42/anomaly-machine-50k
The AnomalyMachine-50K dataset is generated entirely using deterministic signal processing techniques—no neural audio models are used. This ensures reproducibility, lightweight generation, and freedom from copyright concerns.
Each machine type has a dedicated synthesis model:
Conditions (idle, normal_load, high_load) modulate amplitude and harmonic content.
Anomalies are injected via signal transformations:
Factory-floor ambience (pink noise + 60/120 Hz hum) is mixed at configurable SNR levels.
All synthesis is deterministic and reproducible with a fixed random seed.
The AnomalyMachine-50K dataset is generated entirely using deterministic signal processing techniques—no neural audio models are used. This ensures reproducibility, lightweight generation, and freedom from copyright concerns.
Each machine type has a dedicated synthesis model:
Conditions (idle, normal_load, high_load) modulate amplitude and harmonic content.
Anomalies are injected via signal transformations:
Factory-floor ambience (pink noise + 60/120 Hz hum) is mixed at configurable SNR levels.
All synthesis is deterministic and reproducible with a fixed random seed.