Installing OpenCV on the Raspberry Pi

Categories OpenCV, Raspberry Pi

Installing OpenCV on Raspberry Pi can be an intermediate challenge, but the rewards can be great! In this video, I show you how to install OpenCV step by step on a Raspberry Pi running the Raspbian operating system. This article is a companion article to the video of the same title on YouTube, which you can watch below.

I recommend you start with a fresh install of the latest version of Raspbian and on boot, update the system.

$ sudo apt update
$ sudo apt upgrade

Install the package debian-goodies and see what large packages that aren’t useful to us are there by running:

$ dpigs -H

This should list packages sorted by their size. You can probably remove a lot of packages on a default Raspbian install and get away with it, but let’s just stick to the usual suspects. Let’s also install various packages that are dependencies to getting OpenCV compiled on the Raspberry Pi.

$ sudo apt purge wolfram-engine libreoffice*
$ sudo apt clean
$ sudo apt autoremove
$ sudo apt install build-essential cmake pkg-config libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libgtk2.0-dev libgtk-3-dev libcanberra-gtk* libatlas-base-dev gfortran python3-dev

If you face problems related to dependencies running the final command, replace “apt” with “aptitude”. That should take care of things better. If “apt” gets the job done, all the better. To make things a bit easier, we install a couple more packages:

$ sudo apt install tmux htop vim

Compiling a package like OpenCV not only requires a lot of available space on your SD card, it also requires quite a bit of RAM. Since the Raspberry Pi 3 comes with only 1GB of RAM, we’ll need to add swap space to the system so that virtual memory available to the system is larger than available RAM. The installation of Raspbian enables 100MB of swap by default, but we should change that to 1024 MB, which is 1GB. 1GB of RAM along with 1GB of swap space should be enough to get OpenCV compiled on the Raspberry Pi.

$ sudo vim /etc/dphys-swapfile

Change CONF_SWAPFILE to 1024


Now restart the swap service for the new swap size to take effect

$ sudo /etc/init.d/dphys-swapfile restart
$ free -m
              total        used        free      shared  buff/cache   available
Mem:            875          87         355          12         432         721
Swap:          1023           0        1023

Let’s install PIP, the Python package installer / manager

$ wget
$ sudo python3

With pip in place, let’s use it to install virtualenvwrapper

$ sudo pip install virtualenv virtualenvwrapper

Add this to ~/.profile to make it easier to use virtualenvwrapper

# For VirtualEnv
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/

Source .profile changes into your current shell:

source ~/.profile

We will create a Python virtual environment named “cv” and install all our dependencies needed to build and use OpenCV into that virtual environment.

mkvirtualenv cv -p python3

You should now notice that your shell prompt has “(cv) ” prefixed to it. This is virtualenv’s way of telling you that your “cv” Python virtual environment is now active. Tip: You can use the “deactivate” command to, well, deactivate the virtual environment. This removes the prefix from your shell prompt.

(cv) shuveb@raspberrypi:~ $

Let’s now install Numpy, OpenCV, OpenCV-contrib and untar them both.

$ pip install numpy
$ mkdir opencv
$ cd opencv
$ wget -O opencv.tar.gz
$ wget -O opencv_contrib.tar.gz
$ tar xvzf opencv.tar.gz
$ tar xvzf opencv_contrib.tar.gz

Make a build directory and configure the build

$ cd opencv-3.4.1
$ mkdir build
$ cd build
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv/opencv_contrib-3.4.1/modules \

Once the build is configured, we can build it with make.

$ make -j4 #this will take several hours
$ sudo make install
$ sudo ldconfig

We need to rename the installed .so file so that we can import it into Python and go about our business

$ sudo mv /usr/local/lib/python3.5/site-packages/ /usr/local/lib/python3.5/site-packages/
$ ln -s /usr/local/lib/python3.5/site-packages/ ~/.virtualenvs/cv/lib/python3.5/site-packages/

Let’s now ensure that we are indeed able to import OpenCV into Python

$ (cv) shuveb@raspberrypi:~ $ python
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170124] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__

While this means that we’ve installed OpenCV successfully on our Raspberry Pi, we could quickly check OpenCV with a simple script which detects human faces. You’ll need to ensure that your “cv” virtual environment is active while you run this script with the “python” command.

# import the necessary packages
from picamera.array import PiRGBArray
from picamera import PiCamera
import imutils
import time
import cv2

# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 32
rawCapture = PiRGBArray(camera, size=(640, 480))

# allow the camera to warmup

# 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
    #image = imutils.rotate(image, 180)
    face_cascade = cv2.CascadeClassifier('/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml')
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.1, 5)
    print("Found "+str(len(faces))+" face(s)")

    #Draw a rectangle around every found face
    for (x,y,w,h) in faces:

    # show the frame
    cv2.imshow("Frame", image)
    key = cv2.waitKey(1) & 0xFF

    # clear the stream in preparation for the next frame

    # if the `q` key was pressed, break from the loop
    if key == ord("q"):

This is what I was able to see