Title: Setting Up a GPU Development Environment Using Docker - PyImageSearch

URL Source: https://pyimagesearch.com/2023/10/16/setting-up-a-gpu-development-environment-using-docker/

Published Time: 2023-10-16T13:00:00+00:00

Markdown Content:
* * *

**Table of Contents**
---------------------

*   [Setting Up a GPU Development Environment Using Docker](#h2BPTitle)

*   [Introduction](#h3Introduction)
*   [A Quick Recap](#h3Recap)
*   [Setting Up Our Virtual Machine Allocation](#h3Setting)
*   [Configuring Our Virtual Machine](#h3Configuring)

*   [Summary](#h2Summary)

*   [Citation Information](#h3Citation)

* * *

In this tutorial, you will learn how to step up a Graphics Processing Unit (GPU) development environment using Docker for machine learning.

[![Image 1](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20603%20500'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2023/10/docker-3-featured-v2.png)

This lesson is the last of a 3-part series on **Docker for Machine Learning**:

1.  [_Getting Started with Docker for Machine Learning_](https://pyimg.co/k3xw6)
2.  [_Getting Used to Docker for Machine Learning_](https://pyimg.co/hf5bk)
3.  [**_Setting Up a GPU Development Environment Using Docker_**](https://pyimg.co/8bf3a) **(this tutorial)**

****To learn how to set up your GPU development environment, _just keep reading._****

* * *

[**Setting Up a GPU Development Environment Using Docker**](#TOC-h2BPTitle)
---------------------------------------------------------------------------

* * *

### [**Introduction**](#TOC-h3Introduction)

Docker is slowly becoming ubiquitous within the modern development ecosystem. It has become the go-to tool for packaging complete environments at once without creating any kind of burden for the developer to check hardware and software compatibility. This has resulted in many open-source repositories as well as large-scale projects adopting it as _the_ solution for environments.

Today, we will look at the following:

*   Starting **_from scratch_** with a plain Virtual Machine on a Cloud Provider
*   Setting up a Docker Container on the Virtual Machine
*   Exposing ports on the container to allow network ingress/egress
*   Connecting from a local machine to the Virtual Machine

By the end of this tutorial, you should be able to spin up and connect to a Docker-backed, fully integrated, GPU-enabled environment setup ready to use for any desired project.

* * *

### [**A Quick Recap**](#TOC-h3Recap)

We have covered quite a lot of ground from where we started. If you missed that, please check them out below!

*   [Getting Started with Docker for Machine Learning](https://pyimg.co/k3xw6): Covers all the basics of containerization and key gotchas
*   [Getting Used to Docker for Machine Learning](https://pyimg.co/hf5bk): Covers how to use Docker and experiment with its Command Line Interface

As a quick walkthrough and summary of them, we looked at the following:

*   Basics of Containers
*   What can Containers do?
*   What makes Containers tick?
*   What is Docker?
*   What are some common utilities of the Docker CLI that we need to manipulate containers?
*   What a sample Dockerfile, Image, and container would look like?
*   How can we push the container to Docker Hub?
*   How can we pull a container from Docker Hub?

Containers are **simple all-in-one packages** that encapsulate everything you need to set up an environment, including files, dependencies, drivers, and more.

You can use Docker to create, handle, manipulate, and run containers on your system locally. It can also be used on **Cloud-based providers** (e.g., [**AWS**](https://aws.amazon.com/)**,** [**GCP**](https://console.cloud.google.com/)**,** [**Azure**](https://azure.microsoft.com/en-in)**,** [**DigitalOcean**](https://www.digitalocean.com/), etc.) to set up containerized workflows.

* * *

### [**Setting Up Our Virtual Machine Allocation**](#TOC-h3Setting)

For this blog, we will use the **Google Cloud Platform (GCP)** to host a GPU-enabled Virtual Machine. To get started, [log onto GCP](https://console.cloud.google.com/).

[![Image 2](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20289'%3E%3C/svg%3E)](https://lh3.googleusercontent.com/LrPJc4j7luJoyOVDSJzlY88by1GiprmqLGp2ESYgZFrdpdwCUzo2rixlpAlz4XEE2isg54s9EIjytqAn9si0ga1XiNZifUUzYH3YtbBaRSsocG2vBdVUkxXVr8ck8331EzQHVa-kB6qKh4UbnVVudEk)

**_Note:_** _This tutorial will require you to have a_ **_Billing-enabled account on GCP_**_. You may incur some charges, but GCP provides a free 90-day credit of USD 300. This tutorial should not utilize over USD 10 at best._

*   Navigate over to the **GCP Compute Engine** service and enter the **VM Instances** section.

[![Image 3](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh4.googleusercontent.com/NYRg6GgZkny9vVbgJNwZdQJ4i6PawYrLZ8cP9VU34nsJJwbIpsumEJnLb9t2eIs96C9aQ1OsKMtQ7e8wJPmoXVjyqAk8POWM7iT64__K5q3beh5P1U5BXj-S3Re5l9VdS3X8LXz6i6SpyyCF4MPonQ4)

*   Click on **CREATE INSTANCE**, give your instance a suitable nickname, and then click on **GPUs** under **Machine configuration**. For our experiment, let’s take an **n1-standard-4** instance.

[![Image 4](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh3.googleusercontent.com/fKjGmqmdhqQGdueHISR74kW96o9wSlPYGc6yGj00Q33ass7A0cmOCaiCe6yGiyq-tXTz4L95D4xSTLJ7Uok6RlksMBmWHPQ7hhRwFxhqkapOYDfLcEhp_AiLHAcnrhm4pemGK0WNnurOWOSQ-jcCCRU)

*   Scroll down to the **Boot disk** option and click on **CHANGE**. You will now get a pop-up with some options.

[![Image 5](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh6.googleusercontent.com/PKDufKYU-G1ut1WiqOmDY4-0_Cvy0fkKS71gS064Dt5wvI47bR-6fN2V2-ofMc0H-6CwMAF5L2p3BfwJbK6YsD4tLR-Wh8wk_YMceANj-YA_eGqyRI7APVQFnA-OvnGSmTRQh3BkYmR44PTiP5xqIGQ)

*   In the pop-up, choose the following options
    *   Choose **Container Optimized OS** within the Operating System
    *   Choose **128 GB** as the size
    *   Choose **SELECT** and continue

[![Image 6](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh6.googleusercontent.com/1AtJeJt5VGVRO72-k8gug4pggH01YRYC1D7X-gIIEFe5n_FxGvSr9Ntn_U3xVJeNZckRtxoOjcCetvz3s-VUInH51E2JYNWgoDsKvt99Vv-yset761Rj9GiRM3hc4gbb3hmMd38C1jvUhPC9qzxuRiw)

*   Within **Firewall**, enable the **Allow HTTP traffic** and **Allow HTTPS traffic** options.

[![Image 7](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh4.googleusercontent.com/E6YtffTtZHgjfJOkAD7LGRFa8YVF97g6hFnR8xJUNJEdDqiDxPrnCsLPGo4_tTYVQGmTYR27Rr8aaCYRfgj0jVAQ-5R14CRhW2d2cM0iOn1XV1z4ZV-w5h4wD7_VfcfJ3Pz_f92kMmMzKDXhlc1lNyo)

*   In summary, our instance will have the following:
    *   An **NVIDIA T4 GPU** (a standard Colaboratory notebook with GPUs enabled has the same accelerator)
    *   4 vCPUs
    *   15 GB Memory/RAM
    *   [ContainerOS](https://cloud.google.com/container-optimized-os/docs/concepts/features-and-benefits) (an OS Image for GCP VMs that is optimized to run Containers)
*   Click the **CREATE** option, which will make the GPU-enabled VM Instance
*   Now, search **Firewall – VPC Network** within the top navigation search bar and click the first option

[![Image 8](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh3.googleusercontent.com/SniCqjb2tZPdeTWoq5zWCWHS7HM4KHHYdcpcVLyO80mrWkKNOWyrPzw1AzLDdsPPDdyL5demIg2Mr7X2UXWpMRcN0ZivX1AppbVr7F3bdiOdP5__5NqZHz2TWkxl0UUhTdugbhi6ctTZXJfj-IUMtlY)

*   Click on **Create a firewall rule** and enter the wizard

[![Image 9](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh4.googleusercontent.com/8TxeFTxaSwEF-o_iLKbhCp9X_Lzax3oyTAthzt_AXuM8gGQ7GQR8CAm_T4qIEBf8hTEoJPBWLI-OuAvcuAKvFZWkOaS7TTwrSG5yvlvVD3sCNTkOhnjQqsaVeE6Lckv52WbxlJjOmqMn8-F9SOEN6JI)

*   Enter the following details within the wizard:
    *   **Name:** Give it a suitable name. We choose **default-allow-jupyter** as our name.
    *   **Targets:** Set **All Instances in the Network** for now. If you have a specific instance, you can enter the name of that instance as well.
    *   **Source IPv4 ranges:** Set **0.0.0.0/0** since this will allow us to accept all source IP Addresses possible. If you are part of an enterprise network and you are sure that your traffic will be routed through that network only, then you can pass the source IP range of that network.
    *   **Protocols and Ports:**
        *   Select the **TCP** option and enter port **8080**. This will expose only port 8080 of all instances on your network, to external traffic. Do the same for **UDP**. While we start our Jupyter server later on, we need to ensure that we only use port 8080 by passing the `--port` flag.

[![Image 10](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh5.googleusercontent.com/5thBZ_t2qrp7tmce2kHplrfrO7jCmsFF9GiLTlpyxriCrUMPzRHBcNxBCZrlIxX61rHJgYAYC7rnK2mfvCUDv5asv0AGsTeuJUR76SJwDKije5249lAsxjOJY0LraoNgq7phlmpSOvfOe0fBdazrnok)

Awesome! We now have our entire system set up. We have an NVIDIA T4 GPU-enabled instance with Container OS installed and port 8080 exposed for external traffic. This is where we will run our Docker containers with full GPU acceleration.

* * *

### [**Configuring Our Virtual Machine**](#TOC-h3Configuring)

To enable GPU acceleration on a system, it is important to have CUDA drivers installed on the system. Fortunately, Google provides helpful utilities to simplify the process for Container OS.

*   Enter the Virtual Machine by SSH-ing into it. Go back to the GCP Compute Engine service and click on the SSH button. This will open a Google Cloud Shell on the browser itself with all GCP utilities present. This Cloud Shell handles all SSH processes, like key transfers internally, thus simplifying the access procedure.
*   Enter the following commands (**Note:** The first two steps need to be run every time the instance is restarted. It is preferable to use a startup script for this which will invoke both commands every time you start the instance.)
    *   `sudo cos-extensions install gpu`: This will execute the utility to run the NVIDIA CUDA Driver installation.

[![Image 11](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20331'%3E%3C/svg%3E)](https://lh6.googleusercontent.com/x64SmPl8hM4UglLA2VnlnLrQduGp_x5QrkxjpSJUJloJayULRaE7Ym4GveG4NpJOl6IGHMf_8JXTYjbt0qzS4Uvab4ejS-rgSrAMz8taM0uJNb8Oj9erPp-LU58BTXVVBWWVFqQsWzRUxQQMs7UZdRM)

\`\`\`
sudo mount --bind /var/lib/nvidia /var/lib/nvidia
sudo mount -o remount,exec /var/lib/nvidia
/var/lib/nvidia/bin/nvidia-smi
\`\`\`

*   This set of commands will verify your installation of driver utilities and mount the GPU device with the right drivers. Below, we can see that the VM can now detect the existence of our T4 GPU.

[![Image 12](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20409'%3E%3C/svg%3E)](https://lh6.googleusercontent.com/s3WBOW8UpEGme3zcNXLTWPa6tY5LuR8P97Dz2MpvTiPmgc8y5f4ViIJXWTq_v1qaQDNE7AtS_k6D23Ydm0O8elZuRIjhvvkhCORkdeveWNtYOLeAcalOyIwqXLPTWbKy1fYXJBJrpRqYsWwLzcrCGv0)

\`\`\`
docker run -it -d -p 8080:8080 --volume /var/lib/nvidia/lib64:/usr/local/nvidia/lib64 \\
--volume /var/lib/nvidia/bin:/usr/local/nvidia/bin \\
--device /dev/nvidia0:/dev/nvidia0 \\
--device /dev/nvidia-uvm:/dev/nvidia-uvm \\
--device /dev/nvidiactl:/dev/nvidiactl \\
--ipc=host \\
--ulimit memlock=-1 \\
--ulimit stack=67108864 \\
nvcr.io/nvidia/pytorch:23.07-py3
\`\`\`

This will execute the Docker command to start and run a GPU-enabled container that can work with PyTorch, while setting up the right drivers.

*   `docker ps`: This will give us the Container ID that we will use to start a shell session with.

[![Image 13](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E)](https://lh3.googleusercontent.com/CenV8lnIylWs0K31vCGVg0LB1LD9ili0ylQRZ2aKT0HP1HWTp2IQmnrAHb5RrS65lHyLKmMwvhlBmyrGcCL5jowEi5iCnDkQzCChBzzZDoMvNjl9FsODU6lA_uJBfuxQrcJK-MwACYw5D20ZNEFuoB0)

*   `docker exec -it a8c bash`: This will enter the Docker container and execute the `bash` command to start a shell inside the container.

[![Image 14](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E)](https://lh3.googleusercontent.com/4Dk20taWmUOY3DyKfKdW-KZYyny_C-mfg8ZlDr65izht2W7hzkgoR60XSztq8Bn1cKXjOHBFDEfjy3wumnofRk6F3JbRd0eNhfPFeOU_V6RrvTasw0ul3PAHWS0yccrWgNoAWEfsHIWqn8SNyRdXrvA)

*   `jupyter notebook --port=8080 --no-browser`: This will start a Jupyter Notebook server on the container, which you can

[![Image 15](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20168'%3E%3C/svg%3E)](https://lh5.googleusercontent.com/XCp3efj0GffRqYN1DnoWSyLKB1F8Jn4XuGATrPYZycEcSdqCGNesWM7uP25YP0dFgIZRDygeWljHfEx0K97A2BE494CXefnNeMHVoyZVU-5yV-1DbynE8NEatsAXKTjsSRluX7IJ7AnHPj4IPyfmJqo)

We have now started the Jupyter Notebook server inside the container that is running on a GCP VM.

*   Go back to the GCP Console. On the instance, you will see an **External IP Address.** Copy the external IP Address and enter it into a new tab while appending **:8080** after it. Hence, the URL will look like **_http://34.67.21.67:8080_**

[![Image 16](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh3.googleusercontent.com/HZqH2UAvpYAN8syPspGQ4IGeq-e9fJ2bYC_yMUvbPPZzVgUWrTrasEwz3r7egRyDWuoSFLg8hYlAIQSDCyyWknKa1RxlMTBkYSgzlPhOJf-zop3pUPLRN4ck-IrPD2IE7fMv-fUwpDFKiXy8BtIVCYU)

*   The new tab will now show a prompt to enter a password or token. Go back to the terminal and copy the token present on the sample URL. Paste it into the password field and log in.

[![Image 17](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20178'%3E%3C/svg%3E)](https://lh4.googleusercontent.com/1nO61itVDoojQsGbPi1rNM-nnNdZpMKGk1yrAc7xW2RrmbTSvetW_jLb8PzhEqCygiuhVTCc8YF5uanu_HVD48QoQMcf_H5vj0X5k12J4ZIk2CzIkpBaRwjXslR24FfA_jb1SmeLqRpL6FubLv2ASEk)

[![Image 18](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh5.googleusercontent.com/Il0D3rKT-jqrh9G0hiO_16frsUORWoRwR0OXe6K_krcOvf68e6jD001o7suNdFiIbiL0V5iGQGcoJIdRkgX1vqQ3af4OzVMGFTWeWJ_UH5ZT3eIbDvFyed33ie21D3CcMw4gRyT7Wqs6iahKjabABAA)

*   You will now see the Jupyter Home page, which is ready for use!

[![Image 19](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20343'%3E%3C/svg%3E)](https://lh5.googleusercontent.com/0Y3FWNzHuBnSpooVhk4UpAhIVQnCehpi8RaiIBAPVacaFx_vCRAS9wVt1ujqvBEG4_xAS0TQsJc6PLNxVp20pvM_wgWtLsQ2by_XVKYLTG7jWO3Q0dUgaKIvxDThAgWXCpyY5QoGFKe8O313I_IGy6g)

Congratulations! You have successfully set up a **PyTorch-NVIDIA container with CUDA 12.1 drivers** set up internally without any hassle. Use this notebook environment to run whatever you like! Here are some fun and interesting notebooks to get started with!

1.  [Stable Diffusion with 🧨diffusers](https://colab.research.google.com/github/huggingface/notebooks/blob/main/diffusers/stable_diffusion.ipynb)
2.  [Meta AI LLaMa Quickstart Notebook](https://github.com/facebookresearch/llama)

* * *

### 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**](#TOC-h2Summary)
-----------------------------

In this blog post, we **culminate the series on Docker for Machine Learning**. We have accomplished the following tasks

*   Set up a Virtual Machine on GCP
*   Set up Firewall Rules to allow Jupyter ports
*   SSH into the Virtual Machine
*   Start a PyTorch-NVIDIA Container on the VM and publish the 8080 port
*   SSH into the container
*   Start a Jupyter Server on the container
*   Log into the server from your local machine’s web browser!

This will now allow you to run any script or notebook within the container, be it something as simple as running an MNIST Training example, training Stable Diffusion models, or hosting a server for inference! Godspeed!

* * *

### [**Citation Information**](#TOC-h3Citation)

**Mukherjee, S.** “Setting Up a GPU Development Environment Using Docker,” _PyImageSearch_, P. Chugh, A. R. Gosthipaty, S. Huot, K. Kidriavsteva, and R. Raha, eds., 2023, [https://pyimg.co/8bf3a](https://pyimg.co/8bf3a)

@incollection{Mukherjee\_2023\_Docker4ML-P3,
  author = {Suvaditya Mukherjee},
  title = {Setting Up a {GPU} Development Environment Using {Docker}},
  booktitle = {PyImageSearch},
  editor = {Puneet Chugh and Aritra Roy Gosthipaty and Susan Huot and Kseniia Kidriavsteva and Ritwik Raha},
  year = {2023},
  url = {https://pyimg.co/8bf3a},
}

* * *

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

### Unleash the potential of computer vision with Roboflow - Free!

*   Step into the realm of the future by [signing up or logging into your Roboflow account](https://roboflow.com/?ref=pyimagesearch). Unlock a wealth of innovative dataset libraries and revolutionize your computer vision operations.
*   Jumpstart your journey by choosing from our broad array of datasets, or benefit from PyimageSearch’s comprehensive library, crafted to cater to a wide range of requirements.
*   Transfer your data to Roboflow in any of the 40+ compatible formats. Leverage cutting-edge model architectures for training, and deploy seamlessly across diverse platforms, including API, NVIDIA, browser, iOS, and beyond. Integrate our platform effortlessly with your applications or your favorite third-party tools.
*   Equip yourself with the ability to train a potent computer vision model in a mere afternoon. With a few images, you can import data from any source via API, annotate images using our superior cloud-hosted tool, kickstart model training with a single click, and deploy the model via a hosted API endpoint. Tailor your process by opting for a code-centric approach, leveraging our intuitive, cloud-based UI, or combining both to fit your unique needs.
*   Embark on your journey today with absolutely no credit card required. Step into the future with Roboflow.

[Join Roboflow Now](https://roboflow.com/?ref=pyimagesearch)

* * *

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

#### Join the PyImageSearch Newsletter and Grab My FREE 17-page Resource Guide PDF

Enter your email address below to **join the PyImageSearch Newsletter** and **download my FREE 17-page Resource Guide PDF** on Computer Vision, OpenCV, and Deep Learning.