Object Detection using Raspberry Pi:
Why?
- Object detection is a kind of eye for AI or Machines of Future. Just Imagine a Humanoid Robot can not visualize like human hence it needs to detect what it is watching or where it is?
- Detection is always a curious case, Deep Learning covers a major area on this.
- Here we use a camera, to be precise pixels to find the object and also classify them.4
How?
- Installation of TensorFlow in raspberry pi,
This can be done in two ways, either using Docker and compile tensorflow inside it or installing with a compiled file.
Here we go for Compiled file from github repository,
Open terminal and make directory tf
mkdir tf
cd tf
Download the wheel file using wget
wget https://github.com/lhelontra/tensorflow-on-arm/releases/download/v1.13.1/tensorflow-1.13.1-cp35-none-linux_armv7l.whl
This downloads the tensorflow file and ready to install
sudo pip3 install tensorflow-1.13.1-cp35-none-linux_armv7l.whl
This is tensorflow 1.13 version for raspberry pi, if you see any update find here,
Tensorflow needs additional package of LibAtlas,lets install that too
sudo apt-get install libatlas-base-dev
Camera object detection is made through openCV hence we need other dependencies with respect to tensorflow and OpenCV,
sudo pip3 install pillow lxml jupyter matplotlib cython
sudo apt-get install python-tk
Sometimes you may get error on this installation, if you get error then try installing one by one like,
sudo pip3 install matplotlib
sudo pip3 install cpython
- OpenCV installation
Image plotting is done through matplotlib and OpenCV is core in image processing and tensorflow uses pixel analysis for producing the results.
Hence, OpenCV installation is must one,For installing it in raspberry pi there are few dependecies,
sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
sudo apt-get install libxvidcore-dev libx264-dev
sudo apt-get install qt4-dev-tools
Now, lets start OpenCV install command,
sudo pip3 install opencv-python
if you really interested in learning more on OpenCV, find pyimagesearch.com provides valuable information.
- Protobuf installation
Protobuf, a package that implements Google’s Protocol Buffer data format is used by Tensorflow for object detection.
First, get the packages needed to compile Protobuf from source.
sudo apt-get install autoconf automake libtool curl
Then download the protobuf release from its GitHub repository by issuing:
wget https://github.com/google/protobuf/releases/download/v3.5.1/protobuf-all-3.5.1.tar.gz
Unpack the file and cd into the folder:
tar -zxvf protobuf-all-3.5.1.tar.gz
cd protobuf-3.5.1
Configure the build by issuing the following command (it takes about 2 minutes):
./configure
Build the package
make
The build process took 1 hr 10 minutes on my Raspberry Pi. When it’s finished,
make check
This process takes even longer, clocking in at 1.5 hrs on my Pi. If you see errors, you can ignore them for now. Now that it’s built, install it by issuing:
sudo make install
Then move into the python directory and export the library path:
cd python
export LD_LIBRARY_PATH=../src/.libs
Next,
python3 setup.py build --cpp_implementation
python3 setup.py test --cpp_implementation
sudo python3 setup.py install --cpp_implementation
Then enter the following path commands:
export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=3
Finally, finish with the command
sudo ldconfig
Now Protobuf is installed on the Pi. Verify it’s installed correctly by issuing the command below and making sure it puts out the default help text.
protoc
then, Raspberry Pi needs to be restarted after this process, or TensorFlow will not work.
sudo reboot now
- Tensorflow Config
Now, back to tensorflow,
let start with directory structure,
mkdir tensorflow
cd tensorflow
Get the tensorflow repostiory ready by downloading it with wget
git clone --recurse-submodules https://github.com/tensorflow/models.git
Since we didn't have docker here, we need to configure path for python to enable tensorflow working structure,
for which edit the following file,
sudo nano ~/.bashrc
In the file, enter the last line and add the following text,
export PYTHONPATH=$PYTHONPATH:/home/pi/tensorflow/models/research:/home/pi/tensorflow/models/research/slim
press ctrl+x and save it by providing 'yes'
We need to use Protoc to compile the Protocol Buffer (.proto) files used by the Object Detection API. The .proto files are located in /research/object_detection/protos, but we need to execute the command from the /research directory. Issue:
cd /home/pi/tensorflow/models/research
protoc object_detection/protos/*.proto --python_out=.
Now, move into object detection folder,
cd /home/pi/tensorflow/models/research/object_detection
Download the Tensorflow detection model with wget,
wget http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz
extract the file,
tar -xzvf ssdlite_mobilenet_v2_coco_2018_05_09.tar.g
Here comes the end of sequencial order,
Final Step of Running Detection model,
Enter into the directory,
cd /home/pi/tensorflow/models/research/object_detection
Create a empty file named, objectdetection.py
Copy the below content into the file and run from terminal using python3 objectdetection.py
######## Picamera Object Detection Using Tensorflow Classifier #########
# This program uses a TensorFlow classifier to perform object detection.
# It loads the classifier uses it to perform object detection on a Picamera feed.
# It draws boxes and scores around the objects of interest in each frame from
# the Picamera. It also can be used with a webcam by adding "--usbcam"
# when executing this script from the terminal.
## Some of the code is copied from Google's example at
## https://github.com/tensorflow/models/blob/master/research/object_detection/object_detection_tutorial.ipynb
## and some is copied from Dat Tran's example at
## https://github.com/datitran/object_detector_app/blob/master/object_detection_app.py
## but I changed it to make it more understandable to me.
# Import packages
import os
import cv2
import numpy as np
from picamera.array import PiRGBArray
from picamera import PiCamera
import tensorflow as tf
import argparse
import sys
# Set up camera constants
IM_WIDTH = 1280
IM_HEIGHT = 720
#IM_WIDTH = 640 Use smaller resolution for
#IM_HEIGHT = 480 slightly faster framerate
# Select camera type (if user enters --usbcam when calling this script,
# a USB webcam will be used)
camera_type = 'picamera'
parser = argparse.ArgumentParser()
parser.add_argument('--usbcam', help='Use a USB webcam instead of picamera',
action='store_true')
args = parser.parse_args()
if args.usbcam:
camera_type = 'usb'
# This is needed since the working directory is the object_detection folder.
sys.path.append('..')
# Import utilites
from utils import label_map_util
from utils import visualization_utils as vis_util
# Name of the directory containing the object detection module we're using
MODEL_NAME = 'ssdlite_mobilenet_v2_coco_2018_05_09'
# Grab path to current working directory
CWD_PATH = os.getcwd()
# Path to frozen detection graph .pb file, which contains the model that is used
# for object detection.
PATH_TO_CKPT = os.path.join(CWD_PATH,MODEL_NAME,'frozen_inference_graph.pb')
# Path to label map file
PATH_TO_LABELS = os.path.join(CWD_PATH,'data','mscoco_label_map.pbtxt')
# Number of classes the object detector can identify
NUM_CLASSES = 90
## Load the label map.
# Label maps map indices to category names, so that when the convolution
# network predicts `5`, we know that this corresponds to `airplane`.
# Here we use internal utility functions, but anything that returns a
# dictionary mapping integers to appropriate string labels would be fine
label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)
category_index = label_map_util.create_category_index(categories)
# Load the Tensorflow model into memory.
detection_graph = tf.Graph()
with detection_graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)
tf.import_graph_def(od_graph_def, name='')
sess = tf.Session(graph=detection_graph)
# Define input and output tensors (i.e. data) for the object detection classifier
# Input tensor is the image
image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
# Output tensors are the detection boxes, scores, and classes
# Each box represents a part of the image where a particular object was detected
detection_boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
# Each score represents level of confidence for each of the objects.
# The score is shown on the result image, together with the class label.
detection_scores = detection_graph.get_tensor_by_name('detection_scores:0')
detection_classes = detection_graph.get_tensor_by_name('detection_classes:0')
# Number of objects detected
num_detections = detection_graph.get_tensor_by_name('num_detections:0')
# Initialize frame rate calculation
frame_rate_calc = 1
freq = cv2.getTickFrequency()
font = cv2.FONT_HERSHEY_SIMPLEX
# Initialize camera and perform object detection.
# The camera has to be set up and used differently depending on if it's a
# Picamera or USB webcam.
# I know this is ugly, but I basically copy+pasted the code for the object
# detection loop twice, and made one work for Picamera and the other work
# for USB.
### Picamera ###
if camera_type == 'picamera':
# Initialize Picamera and grab reference to the raw capture
camera = PiCamera()
camera.resolution = (IM_WIDTH,IM_HEIGHT)
camera.framerate = 10
rawCapture = PiRGBArray(camera, size=(IM_WIDTH,IM_HEIGHT))
rawCapture.truncate(0)
for frame1 in camera.capture_continuous(rawCapture, format="bgr",use_video_port=True):
t1 = cv2.getTickCount()
# Acquire frame and expand frame dimensions to have shape: [1, None, None, 3]
# i.e. a single-column array, where each item in the column has the pixel RGB value
frame = np.copy(frame1.array)
frame.setflags(write=1)
frame_expanded = np.expand_dims(frame, axis=0)
# Perform the actual detection by running the model with the image as input
(boxes, scores, classes, num) = sess.run(
[detection_boxes, detection_scores, detection_classes, num_detections],
feed_dict={image_tensor: frame_expanded})
# Draw the results of the detection (aka 'visulaize the results')
vis_util.visualize_boxes_and_labels_on_image_array(
frame,
np.squeeze(boxes),
np.squeeze(classes).astype(np.int32),
np.squeeze(scores),
category_index,
use_normalized_coordinates=True,
line_thickness=8,
min_score_thresh=0.40)
cv2.putText(frame,"FPS: {0:.2f}".format(frame_rate_calc),(30,50),font,1,(255,255,0),2,cv2.LINE_AA)
# All the results have been drawn on the frame, so it's time to display it.
cv2.imshow('Object detector', frame)
t2 = cv2.getTickCount()
time1 = (t2-t1)/freq
frame_rate_calc = 1/time1
# Press 'q' to quit
if cv2.waitKey(1) == ord('q'):
break
rawCapture.truncate(0)
camera.close()
### USB webcam ###
elif camera_type == 'usb':
# Initialize USB webcam feed
camera = cv2.VideoCapture(0)
ret = camera.set(3,IM_WIDTH)
ret = camera.set(4,IM_HEIGHT)
while(True):
t1 = cv2.getTickCount()
# Acquire frame and expand frame dimensions to have shape: [1, None, None, 3]
# i.e. a single-column array, where each item in the column has the pixel RGB value
ret, frame = camera.read()
frame_expanded = np.expand_dims(frame, axis=0)
# Perform the actual detection by running the model with the image as input
(boxes, scores, classes, num) = sess.run(
[detection_boxes, detection_scores, detection_classes, num_detections],
feed_dict={image_tensor: frame_expanded})
# Draw the results of the detection (aka 'visulaize the results')
vis_util.visualize_boxes_and_labels_on_image_array(
frame,
np.squeeze(boxes),
np.squeeze(classes).astype(np.int32),
np.squeeze(scores),
category_index,
use_normalized_coordinates=True,
line_thickness=8,
min_score_thresh=0.85)
cv2.putText(frame,"FPS: {0:.2f}".format(frame_rate_calc),(30,50),font,1,(255,255,0),2,cv2.LINE_AA)
# All the results have been drawn on the frame, so it's time to display it.
cv2.imshow('Object detector', frame)
t2 = cv2.getTickCount()
time1 = (t2-t1)/freq
frame_rate_calc = 1/time1
# Press 'q' to quit
if cv2.waitKey(1) == ord('q'):
break
camera.release()
cv2.destroyAllWindows()
######## Picamera Object Detection Using Tensorflow Classifier #########
# This program uses a TensorFlow classifier to perform object detection.
# It loads the classifier uses it to perform object detection on a Picamera feed.
# It draws boxes and scores around the objects of interest in each frame from
# the Picamera. It also can be used with a webcam by adding "--usbcam"
# when executing this script from the terminal.
## Some of the code is copied from Google's example at
## https://github.com/tensorflow/models/blob/master/research/object_detection/object_detection_tutorial.ipynb
## and some is copied from Dat Tran's example at
## https://github.com/datitran/object_detector_app/blob/master/object_detection_app.py
## but I changed it to make it more understandable to me.
# Import packages
import os
import cv2
import numpy as np
from picamera.array import PiRGBArray
from picamera import PiCamera
import tensorflow as tf
import argparse
import sys
# Set up camera constants
IM_WIDTH = 1280
IM_HEIGHT = 720
#IM_WIDTH = 640 Use smaller resolution for
#IM_HEIGHT = 480 slightly faster framerate
# Select camera type (if user enters --usbcam when calling this script,
# a USB webcam will be used)
camera_type = 'picamera'
parser = argparse.ArgumentParser()
parser.add_argument('--usbcam', help='Use a USB webcam instead of picamera',
action='store_true')
args = parser.parse_args()
if args.usbcam:
camera_type = 'usb'
# This is needed since the working directory is the object_detection folder.
sys.path.append('..')
# Import utilites
from utils import label_map_util
from utils import visualization_utils as vis_util
# Name of the directory containing the object detection module we're using
MODEL_NAME = 'ssdlite_mobilenet_v2_coco_2018_05_09'
# Grab path to current working directory
CWD_PATH = os.getcwd()
# Path to frozen detection graph .pb file, which contains the model that is used
# for object detection.
PATH_TO_CKPT = os.path.join(CWD_PATH,MODEL_NAME,'frozen_inference_graph.pb')
# Path to label map file
PATH_TO_LABELS = os.path.join(CWD_PATH,'data','mscoco_label_map.pbtxt')
# Number of classes the object detector can identify
NUM_CLASSES = 90
## Load the label map.
# Label maps map indices to category names, so that when the convolution
# network predicts `5`, we know that this corresponds to `airplane`.
# Here we use internal utility functions, but anything that returns a
# dictionary mapping integers to appropriate string labels would be fine
label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)
category_index = label_map_util.create_category_index(categories)
# Load the Tensorflow model into memory.
detection_graph = tf.Graph()
with detection_graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)
tf.import_graph_def(od_graph_def, name='')
sess = tf.Session(graph=detection_graph)
# Define input and output tensors (i.e. data) for the object detection classifier
# Input tensor is the image
image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
# Output tensors are the detection boxes, scores, and classes
# Each box represents a part of the image where a particular object was detected
detection_boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
# Each score represents level of confidence for each of the objects.
# The score is shown on the result image, together with the class label.
detection_scores = detection_graph.get_tensor_by_name('detection_scores:0')
detection_classes = detection_graph.get_tensor_by_name('detection_classes:0')
# Number of objects detected
num_detections = detection_graph.get_tensor_by_name('num_detections:0')
# Initialize frame rate calculation
frame_rate_calc = 1
freq = cv2.getTickFrequency()
font = cv2.FONT_HERSHEY_SIMPLEX
# Initialize camera and perform object detection.
# The camera has to be set up and used differently depending on if it's a
# Picamera or USB webcam.
# I know this is ugly, but I basically copy+pasted the code for the object
# detection loop twice, and made one work for Picamera and the other work
# for USB.
### Picamera ###
if camera_type == 'picamera':
# Initialize Picamera and grab reference to the raw capture
camera = PiCamera()
camera.resolution = (IM_WIDTH,IM_HEIGHT)
camera.framerate = 10
rawCapture = PiRGBArray(camera, size=(IM_WIDTH,IM_HEIGHT))
rawCapture.truncate(0)
for frame1 in camera.capture_continuous(rawCapture, format="bgr",use_video_port=True):
t1 = cv2.getTickCount()
# Acquire frame and expand frame dimensions to have shape: [1, None, None, 3]
# i.e. a single-column array, where each item in the column has the pixel RGB value
frame = np.copy(frame1.array)
frame.setflags(write=1)
frame_expanded = np.expand_dims(frame, axis=0)
# Perform the actual detection by running the model with the image as input
(boxes, scores, classes, num) = sess.run(
[detection_boxes, detection_scores, detection_classes, num_detections],
feed_dict={image_tensor: frame_expanded})
# Draw the results of the detection (aka 'visulaize the results')
vis_util.visualize_boxes_and_labels_on_image_array(
frame,
np.squeeze(boxes),
np.squeeze(classes).astype(np.int32),
np.squeeze(scores),
category_index,
use_normalized_coordinates=True,
line_thickness=8,
min_score_thresh=0.40)
cv2.putText(frame,"FPS: {0:.2f}".format(frame_rate_calc),(30,50),font,1,(255,255,0),2,cv2.LINE_AA)
# All the results have been drawn on the frame, so it's time to display it.
cv2.imshow('Object detector', frame)
t2 = cv2.getTickCount()
time1 = (t2-t1)/freq
frame_rate_calc = 1/time1
# Press 'q' to quit
if cv2.waitKey(1) == ord('q'):
break
rawCapture.truncate(0)
camera.close()
### USB webcam ###
elif camera_type == 'usb':
# Initialize USB webcam feed
camera = cv2.VideoCapture(0)
ret = camera.set(3,IM_WIDTH)
ret = camera.set(4,IM_HEIGHT)
while(True):
t1 = cv2.getTickCount()
# Acquire frame and expand frame dimensions to have shape: [1, None, None, 3]
# i.e. a single-column array, where each item in the column has the pixel RGB value
ret, frame = camera.read()
frame_expanded = np.expand_dims(frame, axis=0)
# Perform the actual detection by running the model with the image as input
(boxes, scores, classes, num) = sess.run(
[detection_boxes, detection_scores, detection_classes, num_detections],
feed_dict={image_tensor: frame_expanded})
# Draw the results of the detection (aka 'visulaize the results')
vis_util.visualize_boxes_and_labels_on_image_array(
frame,
np.squeeze(boxes),
np.squeeze(classes).astype(np.int32),
np.squeeze(scores),
category_index,
use_normalized_coordinates=True,
line_thickness=8,
min_score_thresh=0.85)
cv2.putText(frame,"FPS: {0:.2f}".format(frame_rate_calc),(30,50),font,1,(255,255,0),2,cv2.LINE_AA)
# All the results have been drawn on the frame, so it's time to display it.
cv2.imshow('Object detector', frame)
t2 = cv2.getTickCount()
time1 = (t2-t1)/freq
frame_rate_calc = 1/time1
# Press 'q' to quit
if cv2.waitKey(1) == ord('q'):
break
camera.release()
cv2.destroyAllWindows()
Thank you so much for providing these updated instructions.
ReplyDeleteThere is one minor error: "cd /home/pi/tensorflow1/models/research" should read "cd /home/pi/tensorflow/models/research" since this example uses the directory tensorflow and not tensorflow1.
Thank you...updated the errors
DeleteThis comment has been removed by the author.
ReplyDeleteprovide clear information of what step and process you are trying
DeleteIt works for me. From my limited experience: Make sure you get no errors in the various installs for libatlas-base-dev, pillow, lxml, jupyter, matplotlib, cython and python-tk
DeleteI had to do a bunch up "sudo apt-get update" and "sudo apt-get upgrade"s even in-between the installs and retry afterwards to be error free. In one case I had to do a "-force reinstall", forgot which one.
Thanks a lot I resolved it 😃
DeleteWhen I try running the code from the file objectdetection.py, in the last step I get the following error: " python3 objectdetection.py
ReplyDeleteTraceback (most recent call last):
File "objectdetection.py", line 46, in
from utils import label_map_util
File "/home/pi/tensorflow/models/research/object_detection/utils/label_map_util.py", line 21, in
from object_detection.protos import string_int_label_map_pb2
ImportError: cannot import name 'string_int_label_map_pb2'
"
Please help.
Are you trying in raspberry pi or windows or linux
Deletehttps://github.com/tensorflow/models/issues/2322
DeleteTry the last command on this issue it might be of protos installation
python3 protoc object_detection/protos/*.proto --python_out=.
DeleteTry this command
I am using a Raspberry Pi 3 Model B
DeleteI tried it, but the error is "python3: can't open file 'protoc': [Errno 2] No such file or directory
Delete". I can clearly recall literally zero issues during any of the steps.
This comment has been removed by the author.
DeleteI was able to run the command without "python3" in the /research directory but not object_detection one. BUT the issue now is that when I run the file with --usbcam because I have a webcam, Logitech C270, its' led lights up for about 7 seconds, there is now window outputting the object detection stuff and then the whole pi reboots. Please help.
DeleteCan u run usb cam outside of tensorflow...? Is it working without any problem.in such case may be u need to change power adapter which is having rating of 2.1A minimum
DeleteYes I am able to do that. Also, my adapter is rated 2.5A. The guesses I have is varying the gpu memory, overclocking or buffer size or something. What would you suggest?
DeleteTry to over clock or else remove extra softwares(try with raspberry lite)
DeleteThe overclocking option seems to be locked out, also I don't want to damage the Pi. I'll try with raspberry lite although I have stripped most of my pre-installed packages. Can Memory Card size be a factor as well? What equipment did you use for this project?
DeleteRpi cam,16gb mem card(class10),raspbian stretch
DeleteIn the object_detection_tutorial.: %Run object_detection_tutorial.ipynb
ReplyDeleteTraceback (most recent call last):
File "/home/pi/tensorflow/models/research/object_detection/object_detection_tutorial.ipynb", line 23
%matplotlib inline
^
SyntaxError: invalid syntaxpynb fle I am getting an error on line 23 where it says %matplotlib inline.
PLease help.
pip install matplotlib
Delete(R u trying inside jypyter notebook)
As robots can have huge memory banks, they continue planning their area with the assistance of SLAM innovation. Along these lines, recording its excursions, it graphs maps. This is extremely useful when the robot needs to diagram a comparative course later on.
ReplyDelete