Article
Build an AI Security Camera with Raspberry Pi
🕵️
A security camera driven by a plain PIR motion sensor has a classic problem: constant false alarms from wind shaking a branch, moving sunlight, or the neighbor’s cat wandering by. By adding a lightweight object-detection model that runs directly on the Raspberry Pi, the camera can tell “motion happened” apart from “a person is actually there” — only sending an alert when it genuinely matters, with no need to ship footage to the cloud for processing.
How it works
- The camera continuously captures frames; a simple motion filter (comparing consecutive frames) runs first to save resources — only when a meaningful change is detected does the system move on to object detection.
- Frames with motion are passed through a pre-trained MobileNet SSD (Single Shot Detector) model, optimized to run fast enough on the Raspberry Pi’s CPU without a dedicated GPU.
- The model returns a list of detected objects with labels (person, car, dog…) and confidence scores; the system only treats it as a “real alert” when the
personlabel appears above a confidence threshold. - When a person is detected, the system saves a photo/short clip with a timestamp and sends an alert over Telegram with the captured image, so the homeowner can immediately see who’s at the door without opening a separate app.
Parts list
- A Raspberry Pi 4 (4GB or more, for smoother object-detection performance)
- A Raspberry Pi Camera Module or a USB webcam
- A microSD card with enough capacity to store alert clips
- A pre-trained MobileNet SSD model (a publicly available
.caffemodel/.pbfile, run through OpenCV’s DNN module) - (Optional) A weatherproof enclosure for outdoor mounting, and an infrared light if night monitoring is needed
Sample code
import cv2
import numpy as np
import time
import requests
PROTOTXT = "MobileNetSSD_deploy.prototxt"
MODEL = "MobileNetSSD_deploy.caffemodel"
CONFIDENCE_THRESHOLD = 0.5
BOT_TOKEN = "TELEGRAM_BOT_TOKEN"
CHAT_ID = "TELEGRAM_CHAT_ID"
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat", "bottle",
"bus", "car", "cat", "chair", "cow", "diningtable", "dog",
"horse", "motorbike", "person", "pottedplant", "sheep", "sofa",
"train", "tvmonitor"]
net = cv2.dnn.readNetFromCaffe(PROTOTXT, MODEL)
cap = cv2.VideoCapture(0)
prev_gray = None
last_alert = 0
ALERT_COOLDOWN = 60 # seconds, avoids spamming alerts while someone lingers at the door
def send_alert(frame_path):
with open(frame_path, "rb") as photo:
requests.post(
f"https://api.telegram.org/bot{BOT_TOKEN}/sendPhoto",
data={"chat_id": CHAT_ID, "caption": "Person detected at the door!"},
files={"photo": photo},
)
def has_motion(frame):
global prev_gray
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
if prev_gray is None:
prev_gray = gray
return False
diff = cv2.absdiff(prev_gray, gray)
prev_gray = gray
return np.mean(diff) > 5 # simple threshold, tune for your actual environment
def detect_person(frame):
h, w = frame.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 0.007843, (300, 300), 127.5)
net.setInput(blob)
detections = net.forward()
for i in range(detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence < CONFIDENCE_THRESHOLD:
continue
class_id = int(detections[0, 0, i, 1])
if CLASSES[class_id] == "person":
return True
return False
while True:
ret, frame = cap.read()
if not ret:
continue
if has_motion(frame) and detect_person(frame):
now = time.time()
if now - last_alert > ALERT_COOLDOWN:
frame_path = "alert_frame.jpg"
cv2.imwrite(frame_path, frame)
send_alert(frame_path)
last_alert = now
print("Alert sent!")
time.sleep(0.5)
Common pitfalls
- Running the AI model on every single frame overloads the Raspberry Pi and causes it to overheat — always filter for motion first with a simple frame comparison, only running the AI model when something actually changed.
- No anti-spam mechanism (
ALERT_COOLDOWN) floods the phone with dozens of notifications while someone lingers at the door — always enforce a minimum gap between alerts. - A confidence threshold (
CONFIDENCE_THRESHOLD) set too low causes false alarms on shadows or objects that vaguely resemble a person — start at 0.5 and tune it for your specific installation environment. - Poor nighttime lighting makes detection noticeably less accurate than during the day — consider adding an infrared light or a camera with night-vision mode if 24/7 monitoring matters.
Extensions
Add face recognition to distinguish household members from strangers (only alerting on strangers), store full clips on a NAS or private cloud storage instead of just still images, or pair it with the ESP32-CAM smart doorbell project for both monitoring and two-way audio when a visitor arrives.
Tags:#raspberry-pi#opencv#security
Comments