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, 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.
Looking for the source code to this post?
Jump Right To The Downloads SectionFinding Shapes in Images using Python and OpenCV
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 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:
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:
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.
86 total classes • 115+ hours of on-demand code walkthrough videos • Last updated: October 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:
- ✓ 86 courses on essential computer vision, deep learning, and OpenCV topics
- ✓ 86 Certificates of Completion
- ✓ 115+ 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 540+ tutorials on PyImageSearch
- ✓ Easy one-click downloads for code, datasets, pre-trained models, etc.
- ✓ Access on mobile, laptop, desktop, etc.
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, 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 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!
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!