Bài viết
Photo booth AI tự chế với Raspberry Pi
📸
Thuê photo booth cho tiệc hoặc sự kiện thường tốn vài triệu đồng mỗi lần, trong khi bản chất chỉ là một webcam, một màn hình cảm ứng nhỏ và phần mềm đếm ngược rồi chụp. Với Raspberry Pi, webcam và thư viện phát hiện khuôn mặt nhẹ (không cần GPU rời), bạn hoàn toàn có thể tự dựng một photo booth “biết” khi nào có người đứng vào khung hình để tự động đếm ngược và chụp — không cần bấm nút.
Nguyên lý hoạt động
- Webcam liên tục chụp khung hình (frame) và đưa qua bộ phát hiện khuôn mặt nhẹ (Haar Cascade của OpenCV hoặc MediaPipe Face Detection) chạy được mượt trên Raspberry Pi mà không cần AI tăng tốc phần cứng.
- Khi phát hiện có ít nhất một khuôn mặt ổn định trong khung hình qua vài frame liên tiếp (tránh chụp nhầm khi người đi ngang qua), hệ thống bắt đầu đếm ngược hiển thị trên màn hình (3, 2, 1…).
- Hết đếm ngược, hệ thống chụp ảnh độ phân giải cao, tự động chèn khung viền/logo sự kiện lên ảnh bằng thư viện xử lý ảnh Pillow.
- Ảnh thành phẩm được lưu vào thẻ nhớ và tùy chọn gửi tới máy in nhiệt (thermal printer) hoặc tải lên thư mục chia sẻ (Google Drive, thư mục mạng nội bộ) để khách lấy ảnh qua QR code.
Linh kiện
- Raspberry Pi 4 (khuyến nghị bản 4GB trở lên để xử lý ảnh mượt)
- Webcam USB độ phân giải tốt (720p trở lên) hoặc Raspberry Pi Camera Module
- Màn hình (HDMI hoặc màn cảm ứng nhỏ) để hiển thị preview và bộ đếm ngược
- (Tùy chọn) Máy in nhiệt USB/Bluetooth nhỏ để in ảnh ngay tại chỗ
- Thẻ nhớ microSD dung lượng đủ lớn để lưu toàn bộ ảnh sự kiện
- Khung/vỏ ngoài để bảo vệ và trang trí, tùy sáng tạo của bạn
Code mẫu
import cv2
import time
from datetime import datetime
from PIL import Image, ImageDraw, ImageFont
FRAME_DIR = "captures"
FACE_STABLE_FRAMES = 15 # so frame lien tiep phai co mat truoc khi dem nguoc
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")
draw = ImageDraw.Draw(img)
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"Da luu anh: {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) # nghi trước khi don frame tiep theo, tranh chup lien tuc
cv2.imshow("Photo Booth", display)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Những lỗi thường gặp
- Chụp quá sớm khi người mới thoáng qua khung hình — luôn yêu cầu khuôn mặt xuất hiện ổn định qua nhiều frame liên tiếp (
FACE_STABLE_FRAMES) trước khi bắt đầu đếm ngược, tránh chụp nhầm người đi ngang. - Ánh sáng yếu làm Haar Cascade phát hiện khuôn mặt kém chính xác — bổ sung đèn LED vòng hoặc đèn nền trắng gần webcam, đặc biệt cho các sự kiện trong nhà thiếu sáng.
- Không có độ trễ (
time.sleep) sau khi chụp khiến hệ thống chụp liên tục nhiều ảnh trùng nhau ngay khi vừa xong một lượt — luôn nghỉ vài giây trước khi quay lại trạng thái chờ. - Chạy phát hiện khuôn mặt ở độ phân giải quá cao làm giảm tốc độ khung hình trên Raspberry Pi — nên xử lý phát hiện khuôn mặt trên ảnh đã thu nhỏ (ví dụ 640x480) rồi mới chụp ảnh gốc độ phân giải cao khi thực sự bấm chụp.
Mở rộng
Thêm bộ lọc/hiệu ứng ảnh theo phong cách sự kiện (đen trắng, cổ điển) bằng OpenCV, tạo mã QR ngay sau khi chụp để khách quét tải ảnh về điện thoại, hoặc ghép chung với dự án gương thông minh Raspberry Pi để biến gương thành photo booth kiêm trợ lý cá nhân.
Thẻ:#raspberry-pi#python#ai
Bình luận