Raspberry Pi Motion Detection with Thonny

In this tutorial, you’ll build a motion detection system that:

Detects movement instantly
Draws a box around moving objects
Runs smoothly on a Raspberry Pi
Works directly inside Thonny

This is the starting point for real AI systems like:

Security cameras
Wildlife monitoring
Smart automation

What you will need.

Hardware:
Raspberry Pi (3,4 or 5)
USB Camera
Software:
Python 3 (via Thonny)
OpenCV install

HOW IT WORKS

Instead of using AI, we use a simpler method:

Step-by-step logic:

Capture two frames
Compare them
Detect changes
Highlight motion

If pixels change → something moved.

Plug your USB camera into one of the Raspberry PI USB ports.

Step 1: On your Raspberry Pi:

Open Thonny:

Click Menu (top left)
Go to Programming
Click Thonny Python IDE

Step2: Verify OpenCV is installed.

In the lower Thonny window (Shell), type:

import cv2

Press Enter.

  • If no error appears, OpenCV is installed correctly and you’re ready to continue.
  • If you get an error (like ModuleNotFoundError), follow the Crafty Robotics tutorial on setting up virtual environments in Thonny to install OpenCV properly.

Step 3: Code

import cv2
from matplotlib import pyplot as plt

# Connect to camera
cap = cv2.VideoCapture(0)

# Read initial frames
ret, frame1 = cap.read()
ret, frame2 = cap.read()

# Setup Matplotlib window
plt.ion()
fig, ax = plt.subplots(figsize=(8, 5))
ax.axis('off')
im = None

# Main loop
while cap.isOpened():

    # Find difference between frames
    diff = cv2.absdiff(frame1, frame2)

    # Process image
    gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    _, thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY)
    dilated = cv2.dilate(thresh, None, iterations=3)

    # Find contours
    contours, _ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    # Draw boxes around motion
    for contour in contours:
        if cv2.contourArea(contour) < 1000:
            continue

        x, y, w, h = cv2.boundingRect(contour)
        cv2.rectangle(frame1, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # Convert to RGB for Matplotlib
    frame_rgb = cv2.cvtColor(frame1, cv2.COLOR_BGR2RGB)

    # Display using Matplotlib
    if im is None:
        im = ax.imshow(frame_rgb)
    else:
        im.set_data(frame_rgb)

    plt.pause(0.001)

    # Update frames
    frame1 = frame2
    ret, frame2 = cap.read()

    if not ret:
        break

    # Exit if window is closed
    if plt.get_fignums() == []:
        break

# Cleanup
cap.release()
plt.close()

This section explains exactly what each part of the code is doing.

Import Libraries

import cv2
from matplotlib import pyplot as plt
  • import cv2 → loads OpenCV for camera access and image processing
  • import pyplot → from Matplotlib for displaying the video feed

Connect to Camera

cap = cv2.VideoCapture(0)

Capture Initial Frames

ret, frame1 = cap.read()
ret, frame2 = cap.read()
  • Reads two frames from the camera
  • These will be compared to detect motion

Setup Display Window

plt.ion()
fig, ax = plt.subplots(figsize=(8, 5))
ax.axis('off')
im = None
  • plt.ion() → enables live updating
  • Creates a display window
  • Hides axes for a clean look
  • im stores the image for updating each frame

Main Loop

while cap.isOpened():
  • Runs continuously while the camera is active

Frame Difference

diff = cv2.absdiff(frame1, frame2)
  • Compares two frames
  • Highlights what has changed (motion)

Image Processing

gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
  • Converts image to grayscale (simpler processing)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
  • Smooths the image to reduce noise
thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY)
  • Turns motion areas white, everything else black
dilated = cv2.dilate(thresh, None, iterations=3)
  • Expands white areas to make motion easier to detect

Find Motion Areas

contours, _ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
  • Detects outlines (contours) of moving objects

Filter Small Movements

for contour in contours:
    if cv2.contourArea(contour) < 1000:
        continue
  • Ignores tiny movements (noise, flicker, etc.)

Draw Bounding Boxes

x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(frame1, (x, y), (x + w, y + h), (0, 255, 0), 2)
  • Draws a green rectangle around detected motion

Convert Color for Display

frame_rgb = cv2.cvtColor(frame1, cv2.COLOR_BGR2RGB)
  • Converts OpenCV’s BGR format to RGB for Matplotlib

Display Frame

if im is None:
    im = ax.imshow(frame_rgb)
else:
    im.set_data(frame_rgb)
  • First frame → create image
  • Next frames → update image
plt.pause(0.001)
  • Allows the display to refresh

Update Frames

frame1 = frame2
ret, frame2 = cap.read()
  • Moves to the next frame pair

Stop if Camera Fails

if not ret:
    break
  • Ends the program if frame capture fails

Exit When Window Closes

if plt.get_fignums() == []:
    break
  • Stops the program when the display window is closed

Cleanup

cap.release()
plt.close()
  • Releases the camera
  • Closes the display window

Summary

This program:

  • Captures live video
  • Compares frames to detect motion
  • Processes the image to isolate movement
  • Draws boxes around moving objects
  • Displays everything in real time

Step 4: Paste the Code in Thonny

Open the Thonny editor and follow these steps:

  1. Copy the full motion detection code
  2. In the upper window (editor area), click inside the blank file
  3. Paste it into the editor

Step 5: Save the code.

Use the USB Camera Folder

We’ll reuse the same folder from our previous USB camera tutorial.

  • Click save.
  • Navigate to your existing camera folder (the one you used for the USB camera project)

Save the file as:

camera_motion_detect.py

Click OK. to save the file.

Step 6: Run the program

Click the Run button at the top of Thonny:

What You Should See

  • A live camera window opens
  • The system begins comparing frames
  • When movement happens, green boxes appear around it

What’s Next?

Now that you’ve built a working motion detection system, you’ve already taken your first step into computer vision with Python using OpenCV.

Upgrade this into:

YOLO AI object detection
Smart recording only on motion
Alerts to phone
Robot vision systems

Check back often — there’s a lot more on the way!

Check out the video on YouTube!

Back to Crafty Robotics.com

Craftyrobotics.com/

Raspberry-pi-tutorials/