In the development of the Raspberry Pi smart car, I have been working for over a year. Initially, I implemented simple remote control and obstacle avoidance features, and later gradually added functions like line following and voice recognition, as well as object recognition. A while ago, while browsing news headlines, I stumbled upon a foreign expert’s project on a Raspberry Pi target-tracking balance car. This inspired me to add object tracking functionality to my own car. After several days of research, I found that it could be implemented using OpenCV and Python. Today, I will share how to install OpenCV 3.0 and how to use it to enable my car to track objects.
I had previously attempted to install OpenCV several times but failed during the CMake compilation process. However, problems must be solved. After browsing several threads, I finally found a reliable guide. I spent an afternoon and successfully installed it. The installation tutorial is lengthy and might be considered plagiarism by news sites, so I will post it in the comments instead. Then came the question: how to implement object tracking after installing OpenCV? I started searching on GitHub for examples, entering keywords like “track car raspberry”. I found one project that used Raspberry Pi and Arduino. Fortunately, Arduino was only used to control the stepper motor. I began to port the Raspberry Pi GPIO motor control part into this project. After a day of debugging, the modified Raspberry Pi object-tracking car was born. To be honest, this is just a prototype, as the car’s turning is not sensitive enough, and the tracking function needs further optimization. My skills are limited, and I hope everyone can join the research.
Let’s talk about the source code for the object tracking in detect.py. How is object tracking implemented in detect.py? First, it needs to capture a frame and determine an object to track. Once the object to be tracked is identified, the car will maintain tracking of that object. The source code defines actions for moving forward, backward, left, right, and stopping. When the locked object moves, the car responds according to the object’s position, thereby tracking the object.
Source code of detect.py:
# Import necessary packages
from picamera.array import PiRGBArray
from picamera import PiCamera
import cv2
import serial
import syslog
import time
import numpy as np
import RPi.GPIO as GPIO
# Define frame size to capture
width = 320
height = 240
tracking_width = 40
tracking_height = 40
auto_mode = 0
# Define functions for the car’s movements
def t_stop():
GPIO.output(11, False)
GPIO.output(12, False)
GPIO.output(15, False)
GPIO.output(16, False)
def t_up():
GPIO.output(11, True)
GPIO.output(12, False)
GPIO.output(15, True)
GPIO.output(16, False)
time.sleep(0.05)
GPIO.output(11, False)
GPIO.output(12, False)
GPIO.output(15, False)
GPIO.output(16, False)
time.sleep(0.3)
def t_down():
GPIO.output(11, False)
GPIO.output(12, True)
GPIO.output(15, False)
GPIO.output(16, True)
def t_left():
GPIO.output(11, False)
GPIO.output(12, True)
GPIO.output(15, True)
GPIO.output(16, False)
time.sleep(0.05)
GPIO.output(11, False)
GPIO.output(12, False)
GPIO.output(15, False)
GPIO.output(16, False)
time.sleep(0.3)
def t_right():
GPIO.output(11, True)
GPIO.output(12, False)
GPIO.output(15, False)
GPIO.output(16, True)
time.sleep(0.05)
GPIO.output(11, False)
GPIO.output(12, False)
GPIO.output(15, False)
GPIO.output(16, False)
time.sleep(0.3)
def t_open():
GPIO.setup(22,GPIO.OUT)
GPIO.output(22,GPIO.LOW)
def t_close():
GPIO.setup(22,GPIO.IN)
def check_for_direction(position_x):
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(11,GPIO.OUT)
GPIO.setup(12,GPIO.OUT)
GPIO.setup(15,GPIO.OUT)
GPIO.setup(16,GPIO.OUT)
GPIO.setup(38,GPIO.OUT)
if position_x == 0 or position_x == width:
print ‘out of bound’
t_stop()
if position_x <= ((width-tracking_width)/2 – tracking_width):
print ‘move right!’
t_right()
elif position_x >= ((width-tracking_width)/2 + tracking_width):
print ‘move left!’
t_left()
else:
# print ‘move front’
t_up()
# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
The image is not related to the content
camera.resolution = (width, height)
camera.framerate = 32
rawCapture = PiRGBArray(camera, size=(width, height))
rawCapture2 = PiRGBArray(camera, size=(width, height))
# allow the camera to warmup
time.sleep(0.1)
# set the ROI (Region of Interest)
c,r,w,h = (width/2 – tracking_width/2), (height/2 – tracking_height/2), tracking_width, tracking_height
track_window = (c,r,w,h)
# capture single frame of tracking image
camera.capture(rawCapture2, format=’bgr’)
# create mask and normalized histogram
roi = rawCapture2.array[r:r+h, c:c+w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi, np.array([0,30,32]), np.array([180,255,255]))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0,180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 80, 1)
# capture frames from the camera
for frame in camera.capture_continuous(rawCapture, format=’bgr’, use_video_port=True):
# grab the raw NumPy array representing the image, then initialize the timestamp
# and occupied/unoccupied text
image = frame.array
# filtering for tracking algorithm
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
dst = cv2.calcBackProject([hsv], [0], roi_hist, [0,180], 1)
ret, track_window = cv2.meanShift(dst, track_window, term_crit)
x,y,w,h = track_window
cv2.rectangle(image, (x,y), (x+w,y+h), 255, 2)
cv2.putText(image, ‘Tracked’, (x-25, y-10), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
# show the frame
cv2.imshow(“Raspberry Pi RC Car”, image)
key = cv2.waitKey(1) & 0xFF
check_for_direction(x)
time.sleep(0.01)
# clear the stream in preparation for the next frame
rawCapture.truncate(0)