Surface electromyography (sEMG) signals provide a window into muscle activation patterns. In this tutorial, we’ll explore the fundamentals of processing EMG signals using Python, from raw data acquisition to feature extraction.

What is EMG?

Electromyography (EMG) measures the electrical activity produced by skeletal muscles. Surface EMG (sEMG) uses electrodes placed on the skin to detect these signals non-invasively, making it ideal for applications in rehabilitation, prosthetics control, and human-computer interaction.

Setting Up Your Environment

First, let’s install the necessary Python libraries:

pip install numpy scipy matplotlib pandas

For this tutorial, we’ll use NumPy for numerical operations, SciPy for signal processing, and Matplotlib for visualization.

Loading and Visualizing EMG Data

Let’s start by loading a sample EMG signal and visualizing it:

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

# Load your EMG data (example)
# data = np.loadtxt('emg_data.csv')
# For demo, let's create synthetic data
fs = 1000  # Sampling frequency (Hz)
t = np.linspace(0, 2, 2*fs)
emg_signal = np.random.randn(len(t)) * 0.1

# Plot raw signal
plt.figure(figsize=(12, 4))
plt.plot(t, emg_signal)
plt.xlabel('Time (s)')
plt.ylabel('Amplitude (mV)')
plt.title('Raw EMG Signal')
plt.grid(True)
plt.show()

Signal Preprocessing

Raw EMG signals typically contain noise and artifacts. Here’s a standard preprocessing pipeline:

1. Band-pass Filtering

Remove low-frequency motion artifacts and high-frequency noise:

# Design bandpass filter (20-450 Hz)
low_cutoff = 20
high_cutoff = 450
order = 4

# Butterworth bandpass filter
b, a = signal.butter(order, [low_cutoff, high_cutoff],
                     btype='band', fs=fs)
filtered_signal = signal.filtfilt(b, a, emg_signal)

2. Rectification

Take the absolute value to get the signal envelope:

rectified_signal = np.abs(filtered_signal)

3. Envelope Detection

Apply low-pass filter for smooth envelope:

# Low-pass filter at 10 Hz
envelope_cutoff = 10
b_env, a_env = signal.butter(order, envelope_cutoff,
                             btype='low', fs=fs)
envelope = signal.filtfilt(b_env, a_env, rectified_signal)

Onset Detection

Detecting when muscle activation begins is crucial for many applications. A simple threshold-based approach:

def detect_onset(signal, threshold_factor=3, min_duration=0.05):
    """
    Detect muscle activation onset

    Parameters:
    -----------
    signal : array
        Processed EMG signal
    threshold_factor : float
        Multiplier of baseline standard deviation
    min_duration : float
        Minimum duration (seconds) to be considered onset

    Returns:
    --------
    onsets : array
        Indices of detected onsets
    """
    # Calculate baseline (first 10% of signal)
    baseline = signal[:int(len(signal)*0.1)]
    threshold = np.mean(baseline) + threshold_factor * np.std(baseline)

    # Find points above threshold
    above_threshold = signal > threshold

    # Find onset points (transitions from False to True)
    onsets = np.where(np.diff(above_threshold.astype(int)) == 1)[0]

    return onsets, threshold

Feature Extraction

Common features used for EMG analysis:

def extract_features(signal, window_size=200):
    """Extract time-domain EMG features"""

    # Root Mean Square (RMS)
    rms = np.sqrt(np.mean(signal**2))

    # Mean Absolute Value (MAV)
    mav = np.mean(np.abs(signal))

    # Variance
    var = np.var(signal)

    # Zero Crossings
    zc = np.sum(np.diff(np.sign(signal)) != 0)

    return {
        'RMS': rms,
        'MAV': mav,
        'Variance': var,
        'Zero_Crossings': zc
    }

Practical Applications

This basic pipeline forms the foundation for many EMG applications:

  • Prosthetics Control: Pattern recognition for controlling robotic limbs
  • Rehabilitation: Monitoring muscle activation during physical therapy
  • Gesture Recognition: Human-computer interaction through muscle movements
  • Fatigue Assessment: Tracking muscle fatigue in sports or workplace ergonomics

Next Steps

This tutorial covered the basics, but there’s much more to explore:

  • Advanced filtering techniques (adaptive filters, wavelet denoising)
  • Frequency-domain analysis (power spectral density, median frequency)
  • Machine learning for pattern classification
  • Real-time processing considerations

Resources

Check out these resources for deeper learning:

  • Our open-source EMAHA-DB datasets on GitHub
  • SciPy signal processing documentation
  • Research papers on EMG classification techniques