Tragic. Heartbreaking. Unbearable.
These are the three words that I would use to describe my past week.
About a week ago, a close childhood friend of mine passed away in a tragic car accident.
I went to elementary school and middle school with him. We spent our summers skateboarding on my driveway and the winters snowboarding and sledding in my backyard.
Since last week I’ve spent my time traveling and attending his viewing and service. Every moment has been utterly agonizing. I find it extremely hard to focus, my mind always wandering back to memories now over a decade old.
To be honest, it’s a wonder I am even writing this blog post at all.
But if there is anything I believe in, it’s that life should be celebrated. And there is no better form of celebration than the nostalgic memories of a loved one.
Back in middle school, him and I used to go through CCS Catalogs (yes, actual catalogs; they didn’t list all their products online, and even if they did, our internet was dialup and usage was moderated by parents).
We would fantasize about which skateboards we were going to buy next — or rather, which ones we were going to ask our parents to purchase for us as birthday presents.
Little memories like leafing through CCS Catalogs before, during, and after school bring a smile to my face. And they make the days a little easier to get through.
So in this post, I’m going to show how to perform basic image segmentation using Python and OpenCV.
And we’ll give it a little skateboarding theme as well, just to pay homage to a friend whose memory weighs heavy on my mind.
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/OpenCV 3.0+.
The cv2.threshold
Function
Let’s start by taking a look at the cv2.threshold function signature:
(T, threshImage) = cv2.threshold(src, thresh, maxval, type)
The first parameter is our source image, or the image that we want to perform thresholding on. This image should be grayscale.
The second parameter, thresh
, is the threshold value which is used to classify the pixel intensities in the grayscale image.
The third parameter, maxval
, is the pixel value used if any given pixel in the image passes the thresh
test.
Finally, the fourth parameter is the thresholding method to be used. The type
value can be any of:
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
Sound complicated? It’s not — I’ll show you examples for each of these thresholding types.
The cv2.threshold
then returns a tuple of two values. The first value, T
, is the value that was used for the thresholding. In our case, this will be the same value as thresh
that we pass into the cv2.threshold
function.
The second value is our actual thresholded image.
Anyway, let’s go ahead and explore some code.
Thresholding: Simple Image Segmentation using OpenCV
There are many forms of image segmentation.
Clustering. Compression. Edge detection. Region-growing. Graph partitioning. Watershed. The list goes on.
But in the beginning, there was only the most basic type of image segmentation: thresholding.
Let’s discover how to perform simple image segmentation using OpenCV. Open up your favorite editor, create a file named threshold.py
, and let’s get started:
# import the necessary packages import argparse import cv2 # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required = True, help = "Path to the image to be thresholded") ap.add_argument("-t", "--threshold", type = int, default = 128, help = "Threshold value") args = vars(ap.parse_args()) # load the image and convert it to grayscale image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # initialize the list of threshold methods methods = [ ("THRESH_BINARY", cv2.THRESH_BINARY), ("THRESH_BINARY_INV", cv2.THRESH_BINARY_INV), ("THRESH_TRUNC", cv2.THRESH_TRUNC), ("THRESH_TOZERO", cv2.THRESH_TOZERO), ("THRESH_TOZERO_INV", cv2.THRESH_TOZERO_INV)] # loop over the threshold methods for (threshName, threshMethod) in methods: # threshold the image and show it (T, thresh) = cv2.threshold(gray, args["threshold"], 255, threshMethod) cv2.imshow(threshName, thresh) cv2.waitKey(0)
We’ll start by importing the two packages that we’ll need, argparse
and cv2
on Lines 2 and 3.
From there, we’ll parse our command line arguments on Lines 6-11. Here we’ll require two parameters. The first, --image
, is the path to the image that we want to threshold. The second, --threshold
, is the threshold value that will be passed into the cv2.threshold
function.
From there, we’ll load the image from disk and convert it to grayscale on Lines 14 and 15. We convert to grayscale since cv2.threshold
expects a single channel image.
Lines 18-23 defines our list of thresholding methods.
We loop over our thresholding methods starting on Line 26.
From there, we apply the actual threshold method on Line 28. We pass our grayscale image as the first argument, the command line supplied threshold value as the second argument, 255 (white) as our value for when the threshold test passes as our third argument, and finally the threshold method itself as the final parameter.
Finally, the thresholded image is displayed on Lines 29 and 30.
Let’s look at some results. Open up your terminal, navigate to our code directory, and execute the following command:
$ python threshold.py --image images/skateboard_decks.png --threshold 245
In this example we are using a value of 245 for our threshold test. If a pixel in the input image passes the threshold test, it will have the value set to 255.
Now, let’s take a look at the results:
Using cv2.THRESH_BINARY
the skateboards are segmented to be black with a white background.
To invert the colors, just use cv2.THRESH_BINARY_INV
, as seen below:
Not bad. What else can we do?
Using cv2.THRESH_TRUNC
leaves the pixel intensities as they are if the source pixel is not greater than the supplied threshold.
Then we have cv2.THRESH_TOZERO
which sets the source pixel to zero if the source pixel is not greater than the supplied threshold:
Finally, we can invert this behavior as well using cv2.THRESH_TOZERO_INV
:
Nothing to it!
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 blog post I showed you how to perform the most basic form of image segmentation: thresholding.
To perform thresholding we utilized the cv2.threshold
function.
OpenCV provides us with five basic thresholding methods, including: cv2.THRESH_BINARY
, cv2.THRESH_BINARY_INV
, cv2.THRESH_TRUNC
, cv2.THRESH_TOZERO
, cv2.THRESH_TOZERO_INV
.
Most importantly, be sure to play around with the thresh
value as it will give different results depending on what value you supply.
In future posts, I’ll show you how to automatically determine the threshold value, no parameter tuning required!
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!
Juan Diego
This is great content. I’m already waiting for the follow up of the document scanner, specially the preprocessing for OCR to eliminate defects and highlights.
Congrats,
priya
I cannot execute it ! The threshold function has different parameters !
I am using open cv2.4 on py 2.7
Adrian Rosebrock
Hi Priya: This tutorial was designed for OpenCV 2.4 and Python 2.7. Please make sure you download the code at the bottom of this post and give it a try.
karthik
sir can u post leaf colour detection coding
Adrian Rosebrock
Hey Karthik — do you have any examples of leaf datasets that you are working with?
luthfi
Hi Adrian, i have question, how can i get the coordinates of the black pixel after i invert it?
Adrian Rosebrock
Can you elaborate more on what you mean by getting the “coordinates of a black pixel after I invert it”? I’m not sure what you mean.
luthfi
Ok for example i have an image with size (j,i) 256×256 pixel, after convert it to binary, then invert it using cv2.THRESH_TOZERO_INV, i have white background and some black pixels
what i want to know is in which (j,i) is that black pixels?, sorry my bad english…
Adrian Rosebrock
If you want to get the (x, y)-coordinates of the pixels that are black, I would use the
np.where
function. For example:np.where(mask == 0)
. You can then transform this into your coordinates.luthfi
ok adrian, i will try it, thanks
Kavi
Hii Adriyan, this is great can u explain about how to detect the barcode alone in the given image using any image processing..???
Adrian Rosebrock
I actually discuss how to detect barcodes in this blog post.
Kavi
Thanky you for the reply..Let met try this..
prashant kumar
hi sir , could you please list all the pages in the footer so that we can directly to any page without going through the process of clicking next /previous
Adrian Rosebrock
There are way too many blog posts on the PyImageSearch blog to list them out entirely, but I will consider creating curated lists specific to topics.
Zartash
Good Morning Sir,I am working on my thesis “Apple Yield Estimation using UAV” and in this my first is pixel classification. Can you please guide me what i am going to do in this step. please guide me I am doing mscs in computer vision.
caleyjag
Is it fair to call this segmentation? We are doing the thresholding but as far as I can see we aren’t making the jump to separating out and tagging objects associated with the individual skateboards. Am I correct? (Sorry, new to python and OpenCV).
Adrian Rosebrock
Yes, thresholding is a type of image segmentation. We are segmenting objects but we do not know what the objects are. To do this we would need to perform object detection.
If you’re new to the world of computer vision and OpenCV, I would highly suggest you take a look at my book, Practical Python and OpenCV. This book is intended for readers who are eager to learn the fundamentals as quickly as possible.
Sowmya
Hello sir,
But this segmentation code is not as perfect for real time images. For example, super market shelve image which contains products. Can you suggest me any remedy to overcome this problem.
Adrian Rosebrock
If you’re looking for that advanced level of segmentation you should read up on Mask R-CNNs, UNet, and other deep learning-based segmentation algorithms. Simple image processing is not going to solve complex situations like segmenting products on a supermarket shelf.
Mandowara Ankita
Hi everyone!
Can this approach be used for images having different color fields which depict harvested and bare lands..If not, suggest an approach
Adrian Rosebrock
Potentially, but if you’re looking for a more robust approach you may want to consider training your own semantic segmentation network.
tamara
can we apply this threshold technique in aerial images semantic segmentation task for classify each pixel if its belong to road class or non-road class? and in case yes do you have any useful resources to write this kind of code?
thank you in advance
Adrian Rosebrock
No, basic thresholding would not work well here. I would recommend semantic segmentation instead.
Farhan
Hello Adrian,
Brilliant tutorial. I just have a question. How can I save the images after the thresholding?
Thanks
Adrian Rosebrock
You can use the “cv2.imwrite” function to save the image to disk. It sounds like you may be new to OpenCV (which is totally fine!) but I would highly encourage you to work through Practical Python and OpenCV first so you can learn the basics.