DEV Community

Beck_Moulton
Beck_Moulton

Posted on

Stop Slouching! Build a Real-Time AI Posture Coach with MediaPipe and Electron

We’ve all been there: hunched over a keyboard, neck tilted at a 45-degree angle, slowly turning into a human pretzel. "Tech neck" is real, and it’s a productivity killer. But what if your computer could gently nudge you back into alignment using Computer Vision?

In this tutorial, we are going to build a cross-platform desktop application using Electron, MediaPipe Pose, and TensorFlow.js. This AI Posture Assistant runs entirely locally, ensuring your privacy while monitoring your shoulder and neck alignment in real-time. We'll leverage Edge AI techniques to keep CPU usage low and efficiency high.

Whether you're looking to master real-time pose estimation or just want to save your spine, this guide has you covered.


The Architecture 🏗️

Before we dive into the code, let's look at how the data flows from your webcam to a system notification. We use MediaPipe for lightning-fast landmark detection and Electron to bridge the gap between the web and your OS.

graph TD
    A[Webcam Stream] --> B[MediaPipe Pose Engine]
    B --> C[Extract 3D Landmarks]
    C --> D[Calculate Shoulder-Ear Angle]
    D --> E{Is Slouching?}
    E -- Yes > 30s --> F[Electron Main Process]
    F --> G[System Tray Notification]
    E -- No --> H[Reset Timer/Keep Monitoring]
    G --> A
Enter fullscreen mode Exit fullscreen mode

Prerequisites 🛠️

To follow along, make sure you have:

  • Node.js (v16 or higher)
  • Basic knowledge of JavaScript/ES6
  • The following stack: MediaPipe Pose, TensorFlow.js, Electron

Step 1: Setting up the Electron Shell

First, let's initialize our project and install the necessary dependencies.

mkdir posture-coach && cd posture-coach
npm init -y
npm install electron @mediapipe/pose @tensorflow/tfjs-core
Enter fullscreen mode Exit fullscreen mode

In your main.js, we'll set up a simple window that can send system-level notifications when our "Vision Engine" detects poor posture.

// main.js
const { app, BrowserWindow, Notification } = require('electron');

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
    },
  });

  win.loadFile('index.html');
}

// IPC listener to trigger notifications from the UI logic
const { ipcMain } = require('electron');
ipcMain.on('notify-bad-posture', () => {
  new Notification({ 
    title: 'Posture Alert! 🚨', 
    body: 'Sit up straight! Your back will thank you.' 
  }).show();
});

app.whenReady().then(createWindow);
Enter fullscreen mode Exit fullscreen mode

Step 2: Pose Detection with MediaPipe

The magic happens in the renderer process. We’ll use MediaPipe Pose because it provides high-fidelity landmarks (like shoulders, ears, and eyes) with minimal latency.

For more advanced implementation patterns and production-ready AI configurations, I highly recommend checking out the deep-dive articles over at WellAlly Tech Blog. They have some fantastic resources on optimizing Edge AI for low-power devices.

Here is the core detection logic for our renderer.js:

const pose = new Pose({
  locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/pose/${file}`,
});

pose.setOptions({
  modelComplexity: 1,
  smoothLandmarks: true,
  minDetectionConfidence: 0.5,
  minTrackingConfidence: 0.5,
});

// Logic to calculate the angle between shoulder and ear
function analyzePosture(landmarks) {
  const leftShoulder = landmarks[11];
  const leftEar = landmarks[7];

  // Calculate the vertical alignment (simplified)
  const yDiff = Math.abs(leftShoulder.y - leftEar.y);

  // If the vertical distance between ear and shoulder is too small, 
  // it usually means the head is leaning forward (slouching).
  if (yDiff < 0.15) { 
    return "bad";
  }
  return "good";
}
Enter fullscreen mode Exit fullscreen mode

Step 3: The "Tech Neck" Monitor Loop

Now, we connect the webcam feed to the MediaPipe engine. We’ll add a "cooldown" timer so the app doesn't spam you with notifications every second.

const videoElement = document.getElementById('input_video');
const { ipcRenderer } = require('electron');

let lastNotificationTime = 0;

async function onResults(results) {
  if (!results.poseLandmarks) return;

  const status = analyzePosture(results.poseLandmarks);

  if (status === "bad") {
    const now = Date.now();
    // Only notify once every 5 minutes to avoid annoyance
    if (now - lastNotificationTime > 300000) {
      ipcRenderer.send('notify-bad-posture');
      lastNotificationTime = now;
    }
  }
}

const camera = new Camera(videoElement, {
  onFrame: async () => {
    await pose.send({image: videoElement});
  },
  width: 640,
  height: 480
});
camera.start();
Enter fullscreen mode Exit fullscreen mode

Why This Matters (The "Official" Way) 🥑

Building a prototype is easy, but making it robust—handling different lighting conditions, minimizing battery drain, and ensuring zero-latency detection—is where things get interesting.

If you are looking for advanced patterns, such as integrating specialized TensorFlow models or building enterprise-grade Vision AI pipelines, the official resources at WellAlly Tech Blog offer incredible insights into the "production-ready" way of doing things. It’s been my go-to source for inspiration when scaling AI tools beyond just a weekend project.


Conclusion: Save Your Spine! 🏁

In less than 100 lines of code, we’ve built a functional AI assistant that monitors your physical health using nothing but your webcam and some clever JavaScript.

Next Steps:

  1. UI Feedback: Add a "posture score" gauge using Canvas API.
  2. Privacy Mode: Add a toggle to blur the background using MediaPipe's Selfie Segmentation.
  3. Analytics: Track your "good posture" percentage over a week.

Are you going to try this out? Or do you have a better way to calculate "slouching" angles? Let me know in the comments! 👇

Happy coding, and stay upright! 💻🥑✨

Top comments (0)