Article
Build a DIY AI Photo Booth with Raspberry Pi
📸
Renting a photo booth for a party or event usually costs a few hundred dollars a pop, even though under the hood it’s just a webcam, a small touchscreen, and software that counts down and snaps a photo. With a Raspberry Pi, a webcam, and a lightweight face-detection library (no dedicated GPU needed), you can build your own photo booth that “knows” when someone’s standing in frame and auto-counts down to capture — no button required.
How it works
- The webcam continuously captures frames, feeding each one through a lightweight face detector (OpenCV’s Haar Cascade or MediaPipe Face Detection) that runs smoothly on a Raspberry Pi without hardware AI acceleration.
- Once at least one face is detected consistently across several consecutive frames (to avoid triggering on someone just walking past), the system starts a countdown shown on screen (3, 2, 1…).
- When the countdown ends, the system captures a high-resolution photo and automatically overlays an event frame/logo using the Pillow image library.
- The finished photo is saved to the memory card and optionally sent to a thermal printer or uploaded to a shared folder (Google Drive, a local network share) so guests can grab it via a QR code.
Parts list
- A Raspberry Pi 4 (4GB or more recommended for smooth image processing)
- A decent USB webcam (720p or higher) or a Raspberry Pi Camera Module
- A display (HDMI monitor or a small touchscreen) to show the preview and countdown
- (Optional) A small USB/Bluetooth thermal printer to print photos on the spot
- A microSD card with enough capacity to store the whole event’s photos
- An enclosure/frame to protect and decorate it, up to your creativity
Sample code
import cv2
import time
from datetime import datetime
from PIL import Image, ImageDraw, ImageFont
FRAME_DIR = "captures"
FACE_STABLE_FRAMES = 15 # consecutive frames a face must be present before counting down
COUNTDOWN_SECONDS = 3
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
stable_count = 0
def add_frame_overlay(photo_path, output_path):
img = Image.open(photo_path).convert("RGB")
border = 40
framed = Image.new("RGB", (img.width + border * 2, img.height + border * 2), "white")
framed.paste(img, (border, border))
draw = ImageDraw.Draw(framed)
draw.text((border, framed.height - border + 5), "CoderDIY Photo Booth", fill="black")
framed.save(output_path)
def capture_photo():
ret, frame = cap.read()
if not ret:
return
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
raw_path = f"{FRAME_DIR}/raw_{timestamp}.jpg"
final_path = f"{FRAME_DIR}/photo_{timestamp}.jpg"
cv2.imwrite(raw_path, frame)
add_frame_overlay(raw_path, final_path)
print(f"Saved photo: {final_path}")
while True:
ret, frame = cap.read()
if not ret:
continue
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
if len(faces) > 0:
stable_count += 1
else:
stable_count = 0
display = frame.copy()
for (x, y, w, h) in faces:
cv2.rectangle(display, (x, y), (x + w, y + h), (0, 255, 0), 2)
if stable_count >= FACE_STABLE_FRAMES:
for i in range(COUNTDOWN_SECONDS, 0, -1):
ret, frame = cap.read()
preview = frame.copy()
cv2.putText(preview, str(i), (frame.shape[1] // 2 - 30, frame.shape[0] // 2),
cv2.FONT_HERSHEY_SIMPLEX, 4, (0, 0, 255), 6)
cv2.imshow("Photo Booth", preview)
cv2.waitKey(1000)
capture_photo()
stable_count = 0
time.sleep(2) # pause before the next frame check, avoids back-to-back captures
cv2.imshow("Photo Booth", display)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Common pitfalls
- Capturing too early when someone briefly passes through frame — always require a face to stay present across several consecutive frames (
FACE_STABLE_FRAMES) before starting the countdown, to avoid triggering on passersby. - Low light makes Haar Cascade detection unreliable — add a ring light or a white backlight near the webcam, especially for indoor events with dim lighting.
- No delay (
time.sleep) after capturing causes the system to fire off several duplicate captures right after finishing one — always pause a few seconds before returning to the waiting state. - Running face detection at full resolution slows down the frame rate on a Raspberry Pi — detect faces on a downscaled frame (e.g. 640x480), and only capture the full-resolution original when the shutter actually fires.
Extensions
Add event-themed photo filters (black-and-white, vintage) using OpenCV, generate a QR code right after capture so guests can scan and download the photo to their phone, or pair it with the DIY smart mirror with Raspberry Pi project to turn a mirror into a photo booth and personal assistant in one.
Tags:#raspberry-pi#python#ai
Comments