Title: Accessing RPi.GPIO and GPIO Zero with OpenCV + Python - PyImageSearch

URL Source: https://pyimagesearch.com/2016/05/02/accessing-rpi-gpio-and-gpio-zero-with-opencv-python/

Published Time: 2016-05-02T14:00:15+00:00

Markdown Content:
![Image 1: Figure 5: A second example of using OpenCV to display an image and then utilizing GPIO to illuminate an LED.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20533'%3E%3C/svg%3E)

I can’t believe this is the first time I am writing a blog post on GPIO and the Raspberry Pi. It’s a pretty big mistake on my part. I should have written this post much earlier.

**You see, on average, I receive 1-3 emails per week along the lines of:**

> When I use the ‘cv’ virtual environment, I can access my OpenCV bindings. But then I can’t import RPi.GPIO. When I switch out of the virtual environment (and use the system Python), I can use RPi.GPIO, but I can’t import OpenCV. What gives?

The reason for this problem is that RPi.GPIO/GPIO Zero _were not_ installed into your Python virtual environment! To fix this issue, all you need to do is use `pip` to install them into your virtual environment — from there, you’ll be good to go.

But to be honest with you, _I don’t think that’s the real issue here!_

The _real problem_ is not having a sufficient understanding of _what_ Python virtual environments are and _why_ we use them. Utilizing Python virtual environments is a _best practice_ that you _need_ to become comfortable with.

In the remainder of this blog post, I’ll _gently introduce the concept of Python virtual environments_. And from there, we’ll learn how to install RPi.GPIO and GPIO Zero into the same Python virtual environment as our OpenCV bindings, allowing us to access both OpenCV and RPi.GPIO/GPIO Zero _at the same time!_

**Keep reading to find out how…**

![Image 2](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20128%20128'%3E%3C/svg%3E)

#### Looking for the source code to this post?

[Jump Right To The Downloads Section](#download-the-code)

Before we learn how to (correctly) install RPi.GPIO and GPIO Zero on our Raspberry Pi, we first need to review the concept of Python virtual environments.

If you’ve ever followed one of the [Raspberry Pi + OpenCV install tutorials on the PyImageSearch blog](https://pyimagesearch.com/opencv-tutorials-resources-guides/), you’ll know that I’m a _huge fan_ of Python virtual environments and recommend them for nearly _every_ project.

However, it seems that I haven’t done a good enough job explaining **_what_** Python virtual environments are and **_why_** we use them. The following section should help clear up any questions.

### What are Python virtual environments?

At the very core, Python virtual environments allow us to create _isolated, independent_ environments for _each_ of our Python projects. This implies that **each project can have its own set of dependencies**, _regardless_ of which dependencies another project has.

**So why in the world would we want to create a virtual environment for each of our projects?**

**Consider this:** Suppose we are software contractors and are hired by a company to develop _ProjectA_. But before we have completed _ProjectA_, a second company hires us to develop _ProjectB_. We notice that both _ProjectA_ and _ProjectB_ have a dependency on _LibraryA_…_**but the problem is that**_ **ProjectA** _**requires v1.0.0 of**_ **LibraryA** _**while**_ **ProjectB** _**requires v2.0.0!**_

This is a real issue for Python because we _cannot_ install _two different versions_ of the _same library_ into the same `site-packages` directory (i.e., where Python stores 3rd party libraries, such as the ones you download and install from `pip` , GitHub, etc.).

**So, what do we do?**

Do we run out to the nearest Apple Store and buy a new MacBook Pro so we can use one laptop to develop _ProjectA_ and the other to develop _ProjectB_? **I really hope not.** That would get expensive quick.

Do use a web host like Linode, Digital Ocean, or Amazon EC2 and spin-up a new instance for each project? **This is a better solution, and is highly applicable in some cases, but in our _specific instance_, it’s overkill.**

_Or do we use Python virtual environments?_

You guessed it — **we go with Python virtual environments.**

In this case, all we need to do is create a virtual environment for _each_ project, that way there is a separate, isolated, and independent environment for all projects:

![Image 3: Figure 1: Each Python environment we create is separate and independent from the others.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20254'%3E%3C/svg%3E)

**Figure 1:** Each Python environment we create is separate and independent from the others.

This allows us to install completely different dependencies for _ProjectA_ and _ProjectB_, ensuring we can finish development of both projects on the same computer.

Pretty neat, right?

Of course, there are many more benefits to using Python virtual environments, but instead of listing them all out, _**[please refer to this excellent Python virtual environments primer on the RealPython blog](https://realpython.com/blog/python/python-virtual-environments-a-primer/)**._

### But Adrian, I’m already using Python virtual environments!

If you followed any of the [OpenCV install tutorials on the PyImageSearch blog](https://pyimagesearch.com/opencv-tutorials-resources-guides/), then you’re already using Python virtual environments.

So how can you find out for sure?

If you need to execute `workon <virtual environment name>` _before_ executing your Python script to import OpenCV, then guess what, you’re using Python virtual environments.

_But here is the real problem…_

### You _probably_ installed RPi.GPIO and GPIO Zero incorrectly

“Incorrect” is the wrong word to use here — but I needed to get your attention. When you went to install RPi.GPIO or GPIO Zero, I’m willing to bet you used `apt-get` . Your command probably looked (something) like this:

$ sudo apt-get install python-rpi.gpio python-gpiozero

This command will download RPi.GPIO and GPIO Zero from the official Raspbian package repository and install them on your system.

The _problem_ is that `apt-get` will install packages into the _system install_ of Python and _not_ your Python virtual environments.

**And this is _exactly why_ you run into problems like:**

> I can import OpenCV in the ‘cv’ virtual environment, but I can’t import RPi.GPIO. On the other hand, I can import RPi.GPIO outside of the ‘cv’ environment, but then I can’t import cv2.

How do you resolve this issue?

You just need to install your libraries into your _virtual environment_ rather than the system version of Python, which can easily be accomplished by `workon` and `pip` .

This brings me to my next point:

**I _do not_ recommend using `apt-get` to install Python libraries.**

You’re probably thinking, _“But Adrian, using `apt-get` is so easy! It’s just one command and then I’m done!”_

I’ve got news for you — using `pip` is also one command. **And it’s just as easy.**

To get back to my point, not only will `apt-get` install these libraries into the system Python (rather than your virtual environment), there is also the issue that `apt-get` packages are normally a bit out of date.

And guess what happens when you want to install the newest version of a given library?

**Hint:** You run into the exact problem detailed above — you’ll be trying to install two different versions of the _same library_ into the _same `site-packages`_ directory, which simply cannot happen (due to how Python works).

Instead, you should be using the Python package manager, [pip](https://pip.pypa.io/en/stable/), to install your Python packages into virtual environments. For more information on `pip` , how it works, and why we use it, **[please refer to this article](https://www.dabapps.com/blog/introduction-to-pip-and-virtualenv-python/)**.

### Installing RPi.GPIO and GPIO Zero “correctly”

Let’s go ahead and get RPi.GPIO and GPIO zero installed into our Python virtual environment. To start, first use the `workon` command to enter your Python virtual environment:

$ workon <virtual environment name>

_**Note:** You may need to execute `source ~/.profile` prior to running the `workon` command so that the virtual environment startup scripts are loaded._

You can tell you are in a Python virtual environment if the name of the environment appears in parenthesis before your prompt:

![Image 4: Figure 2: I can tell I am in the "cv" virtual environment because I can see the text "(cv)" before my prompt.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20370'%3E%3C/svg%3E)

**Figure 2:** I can tell I am in the “cv” virtual environment because I can see the text “(cv)” before my prompt.

In this case, I have entered the `cv` virtual environment and I can verify this because I see the text _“(cv)”_ before my prompt.

From there, we can let `pip` install RPi.GPIO and GPIO Zero for us:

$ pip install RPi.GPIO
$ pip install gpiozero

Lastly, let’s test the install and ensure we can import RPi.GPIO, GPIO Zero, and OpenCV together:

$ python
>>> import RPi.GPIO
>>> import gpiozero
>>> import cv2
>>>

_**Note:** I’ve made the assumption that the virtual environment you are using_ already _has OpenCV installed in it. My `cv` virtual environment has OpenCV already installed, so by using `pip` to install the `RPi.GPIO` and `gpiozero` to install the respective GPIO packages, I’m able to access all three libraries from within the same environment._

Once you can import these libraries in the same environment, we’re ready to move on.

### Hardware

For this blog post, I used my **[Raspberry Pi 3](http://amzn.to/1Nz3AaP)** and the **TrafficHAT** board, a really cool module for the Raspberry Pi that allows you to get started quickly and easily with GPIO programming:

![Image 5: Figure 3: The TrafficHAT module for the Raspberry Pi, which includes 3 LED lights, a buzzer, and push button, all of which are programmable via GPIO.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20556%20600'%3E%3C/svg%3E)

**Figure 3:** The TrafficHAT module for the Raspberry Pi, which includes 3 LED lights, a buzzer, and push button, all of which are programmable via GPIO.

As you can see, the TrafficHAT includes 3 big LED lights, a push-button, and a buzzer.

_**Note:** It’s called a “hat” because we simply need to set it on top of the GPIO pins — no breakout board, extra cables, or soldering is required._

Once we have the TrafficHAT installed on the Raspberry Pi, we can program it using nearly any programming language (provided the language can access the GPIO pins), but for the purposes of this blog post, we’ll be using Python + [RPi.GPIO](https://pypi.python.org/pypi/RPi.GPIO) and [GPIO Zero](https://gpiozero.readthedocs.org/en/v1.2.0/).

### Using RPi.GPIO + OpenCV

Let’s go ahead and write some code to access the TrafficHAT board using the RPi.GPIO library. We’ll also utilize OpenCV to load an image from file and display it to our screen.

Open up a new file, name it `gpio_demo.py` , and insert the following code:

\# import the necessary packages
import RPi.GPIO as GPIO
import time
import cv2

# load the input image and display it to our screen
print("click on the image and press any key to continue...")
image = cv2.imread("hoover\_dam.jpg")
cv2.imshow("Image", image)
cv2.waitKey(0)
print("moving on...")

# set the GPIO mode
GPIO.setmode(GPIO.BCM)

# loop over the LEDs on the TrafficHat and light each one
# individually
for i in (22, 23, 24):
	GPIO.setup(i, GPIO.OUT)
	GPIO.output(i, GPIO.HIGH)
	time.sleep(3.0)
	GPIO.output(i, GPIO.LOW)

# perform a bit of cleanup
GPIO.cleanup()

**Lines 2-4** handle importing our required Python packages. We then load the input image from disk and display it to our screen on **Lines 8-10**. Our script will pause execution until we click on the active image window and press any key on our keyboard.

From there, we loop over each of the LEDs on the TrafficHAT (**Line 18**). For each of these lights, we:

1.  Turn the LED light on.
2.  Wait 3 seconds.
3.  Turn the light off and continue looping.

To execute `gpio_demo.py` , make sure you are in the `cv` virtual environment (or whatever virtual environment you are using to store your OpenCV bindings + GPIO libraries) by using the `workon` command:

$ workon cv

We can then run the `gpio_demo.py` script:

$ python gpio\_demo.py

As the output image demonstrates, we can see that our `hoover_dam.jpg` image is displayed to the screen _and_ the green LED lights is shining brightly on the TrafficHAT:

![Image 6: Figure 4: Loading an image to my screen using OpenCV and then lighting up the green LED using GPIO.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20450'%3E%3C/svg%3E)

**Figure 4:** Loading an image to my screen using OpenCV and then lighting up the green LED using GPIO.

### What about root?

But what if we wanted to execute `gpio_demo.py` as the root user? What do we do then?

We have two options here.

The first option is to use the `sudo` command _inside_ our Python virtual environment, like this:

$ sudo python gpio\_demo.py

_**Note:** Make sure you are in your Python virtual environment_ before _executing your script with `sudo` ; otherwise, you will not have access to the libraries installed in your virtual environment._

The second option is to launch a root shell, access our Python virtual environment, and then execute the script:

$ sudo /bin/bash
$ source /home/pi/.profile
$ workon cv
$ python gpio\_demo.py

Which one is best?

To be honest, it doesn’t really matter.

There are some cases where using `sudo` is easier. And there are others where it’s nice to simply have a root shell pulled up. Use whichever option you’re more comfortable with — **just be careful when executing commands as root!**

### Using RPI Zero + OpenCV

Now that we’ve explored RPi.GPIO, let’s re-create the same Python script, but this time using the GPIO Zero library. Open up a different file, name it `gpiozero_demo.py` , and insert the following code:

\# import the necessary packages
from gpiozero import TrafficHat
import time
import cv2

# load the input image and display it to our screen
print("click on the image and press any key to continue...")
image = cv2.imread("hoover\_dam.jpg")
cv2.imshow("Image", image)
cv2.waitKey(0)
print("moving on...")

# initialize the TrafficHAT, then create the list of lights
th = TrafficHat()
lights = (th.lights.green, th.lights.amber, th.lights.red)

# loop over the lights and turn them on one-by-one
for light in lights:
	light.on()
	time.sleep(3.0)
	light.off()

**Lines 2-4** again handle importing our required packages. What’s really interesting here is that the `gpiozero` library has a `TrafficHat` class, which enables us to easily interface with the TrafficHAT module.

**Lines 8-10** handle loading and displaying our input image to sour screen.

We can then initialize the `TrafficHat` object and construct the list of `lights` on **Lines 14 and 15**.

Finally, **Lines 18-21** handle looping over each of the `lights` , turning each on individually, waiting 3 seconds, and then turning the `light` off before moving to the next one.

Just like the RPi.GPIO example, we first need to access our Python virtual environment and then execute our script:

$ workon cv
$ python gpiozero\_demo.py

As the script executes, we can see an image displayed to our screen and the LEDs lighting up:

![Image 7: Figure 5: A second example of using OpenCV to display an image and then utilizing GPIO to illuminate an LED.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20550%20733'%3E%3C/svg%3E)

**Figure 5:** A second example of using OpenCV to display an image and then utilizing GPIO to illuminate an LED.

_**Note:** To execute this script as root, follow the instructions detailed in the previous section._

### What's next? We recommend [PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend).

**Course information:**  
84 total classes • 114+ hours of on-demand code walkthrough videos • Last updated: February 2024  
★★★★★ 4.84 (128 Ratings) • 16,000+ Students Enrolled

**I strongly believe that if you had the right teacher you could _master_ computer vision and deep learning.**

Do you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?

That’s _not_ the case.

All you need to master computer vision and deep learning is for someone to explain things to you in _simple, intuitive_ terms. _And that’s exactly what I do_. My mission is to change education and how complex Artificial Intelligence topics are taught.

If you're serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to _successfully_ and _confidently_ apply computer vision to your work, research, and projects. Join me in computer vision mastery.

**Inside PyImageSearch University you'll find:**

*   ✓ **84 courses** on essential computer vision, deep learning, and OpenCV topics
*   ✓ **84 Certificates** of Completion
*   ✓ **114+ hours** of on-demand video
*   ✓ **Brand new courses released _regularly_**, ensuring you can keep up with state-of-the-art techniques
*   ✓ **Pre-configured Jupyter Notebooks in Google Colab**
*   ✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)
*   ✓ Access to **centralized code repos for _all_ 536+ tutorials** on PyImageSearch
*   ✓ **Easy one-click downloads** for code, datasets, pre-trained models, etc.
*   ✓ **Access** on mobile, laptop, desktop, etc.

[Click here to join PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend)

Summary
-------

In this blog post, I started by reviewing _what_ Python virtual environments are and _why_ we use them. Simply put, Python virtual environments allow us to create independent, isolated development environments for _each_ project we work on, ensuring we don’t run into version dependency issues. Furthermore, virtual environments allow us to keep our system install of Python clean and tidy.

Once we understood the basics of Python virtual environments, I detailed how to (correctly) install RPi.GPIO and GPIO Zero such that we can access _both_ GPIO libraries _and_ OpenCV at the same time.

We then developed a simple Python script that loads an image from disk using OpenCV, displays it to our screen, and then lights up various LEDs on the [TrafficHAT](https://ryanteck.uk/hats/1-traffichat-0635648607122.html).

In the next blog post, we’ll create a more advanced GPIO + OpenCV script, this time lighting up LEDs and buzzing the buzzer whenever a _pre-defined visual action_ takes place.

**Be sure to enter your email address in the form below to be notified when the next blog post goes live, _you won’t want to miss it!_**

![Image 8](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20410%20567'%3E%3C/svg%3E)

#### Download the Source Code and FREE 17-page Resource Guide

Enter your email address below to get a .zip of the code and a **FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning.** Inside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!