Title: Finding Shapes in Images using Python and OpenCV - PyImageSearch

URL Source: https://pyimagesearch.com/2014/10/20/finding-shapes-images-using-python-opencv/

Published Time: 2014-10-20T14:00:48+00:00

Markdown Content:
[![Image 1: Finding Shapes in Images using Python and OpenCV](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20415'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/10/finding_shapes_example.png)

Before we dive into this post, let’s take a second and talk about Oscar, a dedicated PyImageSearch reader.

He is just getting started in computer vision — and he’s taken the best possible route to mastering the subject: **_creating your own projects and solving them._**

Oscar picked up a copy of my book, _[Practical Python and OpenCV](https://pyimagesearch.com/practical-python-opencv/),_ read through it in a single weekend, and then decided to create a project for himself and solve it.

He is _absolute, 100% proof_ that you can start with very limited (or no) computer vision knowledge and in _**single weekend**_ learn the skills necessary to build and solve computer vision projects.

Today we are going to discuss Oscar’s first project. He emailed me the image at the top of this post and asked for a little guidance on how to:

*   Recognize only figures with the _black background_
*   If _2 or more figures overlap_ they all should be _treated as one object_
*   _Detect and draw contours_ around each of the black shapes
*   _Count_ the number of black shapes

Honestly, this is a great first project.

I replied to Oscar and gave him a few tips on how to solve the problem. I told him what chapters in _Practical Python and OpenCV_ to read, and I suggested a high-level approach to solve the problem.

A day later I found that I had a reply in my inbox — Oscar had solved the problem!

We continued to tweak his code a little more and improve the results.

And today I am going to show the final product.

So let’s give a big hand to Oscar. He’s done a great job. And he’s proof that you can learn computer vision in just a **_single weekend_** using [_Practical Python and OpenCV_](https://pyimagesearch.com/practical-python-opencv/).

![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)

Let’s go ahead and get started.

Open up a new file, name it `find_shapes.py` , and we’ll get to work.

\# import the necessary packages
import numpy as np
import argparse
import imutils
import cv2

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add\_argument("-i", "--image", help = "path to the image file")
args = vars(ap.parse\_args())

# load the image
image = cv2.imread(args\["image"\])

The first thing we’ll do is import the Python packages we’ll need. We’ll use NumPy for numerical processing, `argparse` to parse our command line arguments, and `cv2` for our OpenCV bindings. My [imutils](https://github.com/jrosebr1/imutils) package has a convenience function we’ll utilize.

**Lines 8-10** handle parsing the command line arguments. We need just a single switch, `--image` , which is the path to our image on disk.

Finally, we’ll load our image off disk on **Line 13**.

Now that we have loaded our image off disk, we can move on to detecting the black shapes in the image.

**Our Goal:** Detect the black shapes in the image.

Detecting these black shapes is actually very easy using the `cv2.inRange` function:

\# find all the 'black' shapes in the image
lower = np.array(\[0, 0, 0\])
upper = np.array(\[15, 15, 15\])
shapeMask = cv2.inRange(image, lower, upper)

On **Lines 16 and 17** we define a `lower` and an `upper` boundary points in the BGR color space. Remember, OpenCV stores images in BGR order rather than RGB.

Our `lower` boundary consists of pure black, specifying zeros for each of the Blue, Green, and Red channels, respectively.

And our `upper` boundary consists of a very dark shade of gray, this time specifying 15 for each of the channels.

We then find all pixels within the lower and upper range on **Line 18**.

Our `shapeMask` now looks something like this:

[![Image 3: Figure 1: Finding all the black shapes in the image.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20456'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/10/finding_shapes_mask.png)

**Figure 1:** Finding all the black shapes in the image.

As you can see, all the black shapes in the original image are now _white_ on a _black_ background.

The next step is to detect the contours in the `shapeMask` . This is also very straightforward:

\# find the contours in the mask
cnts = cv2.findContours(shapeMask.copy(), cv2.RETR\_EXTERNAL,
	cv2.CHAIN\_APPROX\_SIMPLE)
cnts = imutils.grab\_contours(cnts)
print("I found {} black shapes".format(len(cnts)))
cv2.imshow("Mask", shapeMask)

# loop over the contours
for c in cnts:
	# draw the contour and show it
	cv2.drawContours(image, \[c\], -1, (0, 255, 0), 2)
	cv2.imshow("Image", image)
	cv2.waitKey(0)

We make a call to `cv2.findContours` on **Lines 21 and 22**, instructing it to find all the _external_ contours of the shapes (i.e. the boundaries).

Due to how various versions of OpenCV handle contours differently we parse the contours on **Line 23**.

From there, we print to the console the number of contours we found.

Then, we start looping over each of the individual contours on **Line 28** and draw the outline of the shapes onto the original image on **Line 30**.

And that’s all there is to it!

To execute the script, fire up a shell, and issue the following command:

$ python find\_shapes.py --image shapes.png 
I found 6 black shapes

If all goes well, you can now cycle through the black shapes, drawing a green outline around each of them:

[![Image 4: Figure 2: We have successfully found the black shapes in the image.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20218'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/10/finding_shapes_found.png)

**Figure 2:** We have successfully found the black shapes in the image.

As you can see, we have clearly found the black shapes in the image!

And all of this was under 30 lines of code, most of which is imports, comments, and parsing command line arguments.

### 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 post we discussed how to find shapes in images using the `cv2.inRange`  and `cv2.findContours`  functions.

This post was largely inspired by Oscar, a dedicated PyImageSearch reader who wrote in and asked how to solve this problem.

You see, Oscar picked up a copy of [_Practical Python and OpenCV_](https://pyimagesearch.com/practical-python-opencv/), read through it, and then decided to develop projects on his own to sharpen and hone his skills.

This is _by far_ the best method to learn — and I highly recommend it to anyone else who is interested in computer vision.

Anyway, if you want to be like Oscar and learn the secrets of computer vision (in a _single weekend_), **[just click here](https://pyimagesearch.com/practical-python-opencv/)** and pickup a copy of _Practical Python and OpenCV._ It worked for Oscar and I know it will work for you too!

Thanks again Oscar! And congrats on your first successful OpenCV project!

![Image 5](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!