Awhile back I was going through /r/computervision when I stumbled across a question asking how to remove contours from an image using OpenCV.
Intrigued, I posted a reply. The basic algorithm for removing contours from an image goes something like this:
- Step 1: Detect and find contours in your image.
- Step 2: Loop over contours individually.
- Step 3: Determine if the contour is “bad” and should be removed according to some criterion.
- Step 4: Accumulate a mask of “bad” contours to be removed.
- Step 5: Apply the accumulated mask of bad contours to the original image using a bitwise ‘and’.
And that’s it!
The algorithm itself is very straightforward, the main step that you need to pay attention to and consider is Step 3, determining if a contour should be removed.
This step could be very simple — or it also could be quite hard, it really depends on your application. And while it’s impossible for me to guess the criterion as to why you want to remove a contoured region from an image, the remainder of this blog post will demonstrate a toy example that you can use to remove contours from an image. From here, you’ll be able to take this code and modify the contour removal criterion according to your own needs.
Looking for the source code to this post?
Jump Right To The Downloads SectionOpenCV and Python versions:
This example will run on Python 2.7/Python 3.4+ and OpenCV 2.4.X.
Removing contours from an image using Python and OpenCV
In this toy example our goal is to remove the circles/ellipses from the image above while retaining the rectangles. We’ll accomplish this by applying a test to every contour to determine if it should be removed or not.
Anyway, let’s go ahead and get this example started. Open up a new file, name it remove_contours.py
, and let’s get coding:
# import the necessary packages import numpy as np import imutils import cv2 def is_contour_bad(c): # approximate the contour peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.02 * peri, True) # the contour is 'bad' if it is not a rectangle return not len(approx) == 4
The first thing we’ll do is import our necessary packages. We’ll use NumPy for numerical processing and cv2
for our OpenCV bindings.
We then define our is_contour_bad
function on Line 6. This function handles the implementation of Step 3 above and defines the criterion under which a contour should be marked as “bad” and removed from an image.
The is_contour_bad
function requires a single argument, c
, which is the contour we are going to test to determine if it should be removed or not.
Remember, in our toy example image above, our goal is to remove the circles/ellipses, while keeping the rectangles intact.
So let’s take a second to consider if we can exploit the geometry of this problem.
A rectangle has 4 sides. And a circle has no sides.
So if we approximate the contour and then examine the number of points within the approximated contour, we’ll be able to determine if the contour is a square or not!
And that’s exactly what Lines 7-11 do. We first approximate the contour on Lines 8 and 9, while Line 12 returns a boolean, indicating whether the contour should be removed or not. In this case, the contour will be kept if the approximation has 4 points (vertices), indicating that the contour is a rectangle.
Let’s finish implementing the other steps to solve this problem:
# load the shapes image, convert it to grayscale, and edge edges in # the image image = cv2.imread("shapes.png") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edged = cv2.Canny(gray, 50, 100) cv2.imshow("Original", image) # find contours in the image and initialize the mask that will be # used to remove the bad contours cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) mask = np.ones(image.shape[:2], dtype="uint8") * 255 # loop over the contours for c in cnts: # if the contour is bad, draw it on the mask if is_contour_bad(c): cv2.drawContours(mask, [c], -1, 0, -1) # remove the contours from the image and show the resulting images image = cv2.bitwise_and(image, image, mask=mask) cv2.imshow("Mask", mask) cv2.imshow("After", image) cv2.waitKey(0)
In order to find and detect the contours in our image (Step 1), we preprocess our image on Lines 16-19 by loading it from disk, converting it to grayscale and detecting edges.
Finding the actual contours happens on Line 23 by making a call to cv2.findContours
. Subsequently we handle grabbing contours with different versions of OpenCV (Line 24).
We then initialize a mask
on Line 25 to store our accumulated “bad” contours. We’ll be using this mask along with bitwise operations later on in the code to perform the actual removal of the contour.
Now we can move on to Step 2, looping over the individual contours which happens on Line 28.
For each of the contours we make a call to is_contour_bad
on Line 30, and if the contour is indeed “bad”, then we accumulate our contours to be removed on Line 31 by drawing the contour on our mask.
Finally, all we have to do is apply a bitwise ‘and’ to the image using the accumulated mask to remove the contours on Line 34. Lines 35-37 then display our results.
Results
To execute our script, just issue the following command:
$ python remove_contours.py
First, you’ll see our mask of accumulated contours that will be removed:
Notice how the contours appear as black shapes on aĀ white background. This is because the black shapesĀ will be removed from the original image while the white regions will be retained once we apply the cv2.bitwise_and
Ā Ā function.
And here is the output after applying the accumulated mask:
Clearly we have removed the circles/ellipses from the image while retaining the rectangles!
What's next? I recommend PyImageSearch University.
30+ total classes • 39h 44m video • Last updated: 12/2021
★★★★★ 4.84 (128 Ratings) • 3,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:
- ✓ 30+ courses on essential computer vision, deep learning, and OpenCV topics
- ✓ 30+ Certificates of Completion
- ✓ 39h 44m on-demand video
- ✓ Brand new courses released every month, 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 500+ tutorials on PyImageSearch
- ✓ Easy one-click downloads for code, datasets, pre-trained models, etc.
- ✓ Access on mobile, laptop, desktop, etc.
Summary
In this blog post I showed you how to remove contoured regions from an image using Python and OpenCV. Removing contours from an image is extremely straightforward and can be accomplished using the following 5 steps:
- Detecting and finding the contours in an image.
- Looping over each of the contours individually.
- Applying a “test” of some sort to determine if the contour should be removed.
- Accumulating a mask of contours to be removed.
- Applying the mask to the original image.
To apply this algorithm to your own images you’ll need to take a second and considerĀ Step 3 and determine the criterion you are using to remove contours. From there, you can apply the rest of the algorithm as-is.
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!