基于Raspberry Pi 3+Pi Camera+OpenCV的顶视人数统计技术求助
Got it, let's get your Pi Camera working with that people counting code instead of the USB camera. There are two solid approaches here—one using the official modern Picamera2 library (recommended for new Raspberry Pi OS versions) and another that lets you keep using your existing cv2.VideoCapture logic with a quick system tweak.
Option 1: Use Picamera2 (Recommended)
The old picamera library is no longer maintained, so Picamera2 is the official replacement for Python 3.7+. It plays nicely with OpenCV and gives better performance for Pi Camera.
Step 1: Install Dependencies
First, install the required packages:
sudo apt update && sudo apt install -y python3-picamera2 python3-opencv python3-numpy
Step 2: Modify Your Code
Replace the USB camera initialization and frame reading logic with this Picamera2 setup. Here's your full updated code:
import argparse import datetime import imutils import math import cv2 import numpy as np from picamera2 import Picamera2 # Add this import width = 800 textIn = 0 textOut = 0 def testIntersectionIn(x, y): res = -450 * x + 400 * y + 157500 if((res >= -550) and (res < 550)): print (str(res)) return True return False def testIntersectionOut(x, y): res = -450 * x + 400 * y + 180000 if ((res >= -550) and (res <= 550)): print (str(res)) return True return False # Initialize Picamera2 instead of cv2.VideoCapture picam2 = Picamera2() # Configure resolution (match your resize width, keep aspect ratio) picam2.configure(picam2.create_preview_configuration(main={"format": 'RGB888', "size": (width, int(width*0.75))})) picam2.start() firstFrame = None while True: # Capture frame from Pi Camera (returns RGB format) frame = picam2.capture_array() # Convert RGB to BGR (OpenCV's default format) frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) text = "Unoccupied" frame = imutils.resize(frame, width=width) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (21, 21), 0) if firstFrame is None: firstFrame = gray continue frameDelta = cv2.absdiff(firstFrame, gray) thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1] thresh = cv2.dilate(thresh, None, iterations=2) _, cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for c in cnts: if cv2.contourArea(c) < 12000: continue (x, y, w, h) = cv2.boundingRect(c) cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.line(frame, (width // 2, 0), (width, 450), (250, 0, 1), 2) #blue line cv2.line(frame, (width // 2 - 50, 0), (width - 50, 450), (0, 0, 255), 2)#red line rectagleCenterPont = ((x + x + w) //2, (y + y + h) //2) cv2.circle(frame, rectagleCenterPont, 1, (0, 0, 255), 5) if(testIntersectionIn((x + x + w) // 2, (y + y + h) // 2)): textIn += 1 if(testIntersectionOut((x + x + w) // 2, (y + y + h) // 2)): textOut += 1 if cv2.waitKey(1) & 0xFF == ord('q'): break cv2.putText(frame, "In: {}".format(str(textIn)), (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) cv2.putText(frame, "Out: {}".format(str(textOut)), (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) cv2.putText(frame, datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"), (10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1) cv2.imshow("Security Feed", frame) # Cleanup Picamera2 instead of camera.release() picam2.stop() cv2.destroyAllWindows()
Key Notes:
- Make sure you've enabled the Camera interface in
raspi-config(go to Interface Options > Camera and select "Yes"). - The resolution configuration matches your
width=800setting to avoid unnecessary resizing overhead.
Option 2: Emulate Pi Camera as a V4L2 Video Device
If you want to keep using your original cv2.VideoCapture(0) line without major code changes, you can map the Pi Camera to a virtual video device.
Step 1: Load the V4L2 Module
Run this command to load the module temporarily:
sudo modprobe bcm2835-v4l2
Step 2: Make It Permanent (Load on Boot)
Add the module to your system's startup modules:
echo "bcm2835-v4l2" | sudo tee -a /etc/modules
Step 3: Reboot and Test
Restart your Pi, then check if the video device exists:
ls /dev/video*
You should see /dev/video0 listed. Now you can use your original code, but add these lines right after initializing the camera to set the resolution (improves performance):
camera = cv2.VideoCapture(0) # Set resolution to match your resize width camera.set(cv2.CAP_PROP_FRAME_WIDTH, width) camera.set(cv2.CAP_PROP_FRAME_HEIGHT, int(width*0.75))
Key Notes:
- This method works but can have lower performance than Picamera2, especially at higher resolutions.
- If you get permission errors, add your user to the
videogroup:
Log out and back in for the change to take effect.sudo usermod -aG video $USER
Quick Debug Tips
- If the camera doesn't work, double-check
raspi-configto ensure the Camera interface is enabled. - For Picamera2, if you see color issues, confirm you're converting RGB to BGR (OpenCV expects BGR by default).
- Adjust the
cv2.contourArea(c) < 12000threshold if you're getting false detections—tweak it based on your camera's field of view.
内容的提问来源于stack exchange,提问作者Uraforclain

