Last updated on July 7, 2021.
This tutorial is the second post in our three-part series on shape detection and analysis.
Last week we learned how to compute the center of a contour using OpenCV.
Today, we are going to leverage contour properties to actually label and identify shapes in an image, just like in the figure at the top of this post.
- Update July 2021: Added new sections, including how to utilize feature extraction, machine learning, and deep learning for shape recognition.
Looking for the source code to this post?
Jump Right To The Downloads SectionOpenCV shape detection
Before we get started with this tutorial, let’s quickly review our project structure:
|--- pyimagesearch | |--- __init__.py | |--- shapedetector.py |--- detect_shapes.py |--- shapes_and_colors.png
As you can see, we have defined a pyimagesearch
module. Inside this module we have shapedetector.py
which will store our implementation of the ShapeDetector
class.
Finally, we have the detect_shapes.py
driver script that we’ll use to load an image from disk, analyze it for shapes, and then perform shape detection and identification via the ShapeDetector
class.
Before we get started, make sure you have the imutils package installed on your system, a series of OpenCV convenience functions that we’ll be using later in this tutorial:
$ pip install imutils
Defining our shape detector
The first step in building our shape detector is to write some code to encapsulate the shape identification logic.
Let’s go ahead and define our ShapeDetector
. Open up the shapedetector.py
file and insert the following code:
# import the necessary packages import cv2 class ShapeDetector: def __init__(self): pass def detect(self, c): # initialize the shape name and approximate the contour shape = "unidentified" peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.04 * peri, True)
Line 4 starts the definition of our ShapeDetector
class. We’ll skip the __init__
constructor here since nothing needs to be initialized.
We then have our detect
method on Line 8 which requires only a single argument, c
, the contour (i.e., outline) of the shape we are trying to identify.
In order to perform shape detection, we’ll be using contour approximation.
As the name suggests, contour approximation is an algorithm for reducing the number of points in a curve with a reduced set of points — thus the term approximation.
This algorithm is commonly known as the Ramer-Douglas-Peucker algorithm, or simply the split-and-merge algorithm.
Contour approximation is predicated on the assumption that a curve can be approximated by a series of short line segments. This leads to a resulting approximated curve that consists of a subset of points that were defined by the original curve.
Contour approximation is actually already implemented in OpenCV via the cv2.approxPolyDP
method.
In order to perform contour approximation, we first compute the perimeter of the contour (Line 11), followed by constructing the actual contour approximation (Line 12).
Common values for the second parameter to cv2.approxPolyDP
are normally in the range of 1-5% of the original contour perimeter.
Note: Interested in a more in-depth look at contour approximation? Be sure to check out the PyImageSearch Gurus course where I discuss computer vision and image processing fundamentals such as contours and connected-component analysis in detail.
Given our approximated contour, we can move on to performing shape detection:
# if the shape is a triangle, it will have 3 vertices if len(approx) == 3: shape = "triangle" # if the shape has 4 vertices, it is either a square or # a rectangle elif len(approx) == 4: # compute the bounding box of the contour and use the # bounding box to compute the aspect ratio (x, y, w, h) = cv2.boundingRect(approx) ar = w / float(h) # a square will have an aspect ratio that is approximately # equal to one, otherwise, the shape is a rectangle shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle" # if the shape is a pentagon, it will have 5 vertices elif len(approx) == 5: shape = "pentagon" # otherwise, we assume the shape is a circle else: shape = "circle" # return the name of the shape return shape
It’s important to understand that a contour consists of a list of vertices. We can check the number of entries in this list to determine the shape of an object.
For example, if the approximated contour has three vertices, then it must be a triangle (Lines 15 and 16).
If a contour has four vertices, then it must be either a square or a rectangle (Line 20). To determine which, we compute the aspect ratio of the shape, which is simply the width of the contour bounding box divided by the height (Lines 23 and 24). If the aspect ratio is ~1.0, then we are examining a square (since all sides have approximately equal length). Otherwise, the shape is a rectangle.
If a contour has five vertices, we can label it as a pentagon (Line 31 and 32).
Otherwise, by process of elimination (in context of this example, of course), we can make the assumption that the shape we are examining is a circle (Lines 35 and 36).
Finally, we return the identified shape to the calling method.
Shape detection with OpenCV
Now that our ShapeDetector
class has been defined, let’s create the detect_shapes.py
driver script:
# import the necessary packages from pyimagesearch.shapedetector import ShapeDetector import argparse import imutils import cv2 # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to the input image") args = vars(ap.parse_args())
We start off on Lines 2-5 by importing our required packages. Notice how we’re importing our implementation of the ShapeDetector
class from the shapedetector
sub-module of pyimagesearch
.
Lines 8-11 handle parsing our command line arguments. We only need a single switch here, --image
, which is the path to where the image we want to process resides on disk.
Next up, let’s pre-process our image:
# load the image and resize it to a smaller factor so that # the shapes can be approximated better image = cv2.imread(args["image"]) resized = imutils.resize(image, width=300) ratio = image.shape[0] / float(resized.shape[0]) # convert the resized image to grayscale, blur it slightly, # and threshold it gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1] # find contours in the thresholded image and initialize the # shape detector cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) sd = ShapeDetector()
First, we load our image from disk on Line 15 and resize it on Line 16. We then keep track of the ratio
of the old height to the new resized height on Line 17 — we’ll find out exactly why we do this later in the tutorial.
From there, Lines 21-23 handle converting the resized image to grayscale, smoothing it to reduce high frequency noise, and finally thresholding it to reveal the shapes in the image.
After thresholding, our image should look like this:
Notice how our image has been binarized — the shapes appear as a white foreground against a black background.
Lastly, we find contours in our binary image, handle grabbing the correct tuple value from cv2.findContours
based on our OpenCV version, and finally initialize our ShapeDetector
(Lines 27-30).
The last step is to identify each of the contours:
# loop over the contours for c in cnts: # compute the center of the contour, then detect the name of the # shape using only the contour M = cv2.moments(c) cX = int((M["m10"] / M["m00"]) * ratio) cY = int((M["m01"] / M["m00"]) * ratio) shape = sd.detect(c) # multiply the contour (x, y)-coordinates by the resize ratio, # then draw the contours and the name of the shape on the image c = c.astype("float") c *= ratio c = c.astype("int") cv2.drawContours(image, [c], -1, (0, 255, 0), 2) cv2.putText(image, shape, (cX, cY), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2) # show the output image cv2.imshow("Image", image) cv2.waitKey(0)
On Line 33 we start looping over each of the individual contours. For each of them, we compute the center of the contour, followed by performing shape detection and labeling.
Since we are processing the contours extracted from the resized image (rather than the original image), we need to multiply the contours and center (x, y)-coordinates by our resize ratio
(Lines 43-45). This will give us the correct (x, y)-coordinates for both the contours and centroid of the original image.
Lastly, we draw the contours and the labeled shape on our image (Lines 44-48), followed by displaying our results (Lines 51 and 52).
To see our shape detector in action, just execute the following command:
$ python detect_shapes.py --image shapes_and_colors.png
As you can see from the animation above, our script loops over each of the shapes individually, performs shape detection on each one, and then draws the name of the shape on the object.
Determining object shape using feature extraction and machine learning
This post demonstrated how simple contour properties, including contour detection, contour approximation, and examining the number of points in a contour, can be used to recognize shapes in an image.
However, there are more advanced shape detection techniques. These methods utilize feature extraction/image descriptors and are used to quantify the shape in an image using a list of numbers (i.e., a “feature vector”).
The first method you should look into is the classic Hu moments shape descriptor. Hu moments are built into the OpenCV library via the cv2.HuMoments
function. The result of applying cv2.HuMoments
is a list of seven numbers used to quantify the shape in an image.
We then have Zernike moments which build on the research and work from Hu moments. The result of applying Zernike moments is a list of 25 numbers used to quantify the shape in the image. Zernike moments tend to be a bit more powerful than Hu moments but may require some manual parameter tuning (in particular, the radius of the moments).
Can we use deep learning for shape recognition?
In short, yes, absolutely. Deep learning-based models excel and object and shape recognition. And if you’re working with simple shapes, then even a shallow CNN will likely outperform Hu moments, Zernike moments, and contour-based shape recognition methods — provided you have enough data to train the CNN, of course!
If you’re interested in learning how to train your own custom deep learning shape recognition algorithms, be sure you go through my deep learning courses inside PyImageSearch University.
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 today’s post blog, we learned how to perform shape detection with OpenCV and Python.
To accomplish this, we leveraged contour approximation, the process of reducing the number of points on a curve to a more simple approximated version.
Then, based on this contour approximation, we examined the number of vertices each shape has. Given the vertex count, we were able to accurately label each of the shapes.
This lesson is part of a three part series on shape detection and analysis. Last week we covered how to compute the center of a contour. Today we covered shape detection with OpenCV. And next week we’ll discuss how to label the actual color of a shape using color channel statistics.
Be sure to enter your email address in the form below to be notified when the next post goes live — you won’t want to miss it!
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!
leena
Why it is scanning and labeling from bottom to top?
How to to scan and label top to bottom?
Adrian Rosebrock
That is how the
cv2.findContours
method is implemented. If you would like to sort contours, see this post.leena
Thanks Adrian. It worked and I am able to scan from top to bottom.
Please help me in identifying lines connected with two shapes like in a flowchart, 2 boxes are connected with line/arrow
with regards.
leena
I have done the same with
shape factor= area / (peri * peri)
if shapefactor >= 0.06 and shapefactor = 0.0484 and shapefactor = 0.050 and shapefactor = 0.032 and shapefactor = 0.95 and ar <= 1.05 else "rectangle"
Adrian Rosebrock
Is there a particular reason you are taking the ratio of the area to the perimeter squared? It seems to make the rule more complicated.
leena
Actually I do not know the reason, just it got solved my problem, so I took it. You or somebody can help me understanding this and the better solution .
Thanks
bitflip
Given you have following triangle:
The bounding rect of it would have aspect-ratio about 1:1.
So, better take the area() of the contour and compare it to width*height of the bounding rect. when the error is too hight –> rectangle.
Vincent
Hi Adrian,
First and foremost, thank you for this excellent tutorial. Very useful and informative.
I have used the logic here to detect red triangles in a webcam feed. I have also tweaked the shapedetector class to identify only triangles. I am able to successfully identify a red triangle.
http://imgur.com/6Z9CnBA
I’ve noticed that sometimes a very messy contour will be classified incorrectly as a triangle.
http://imgur.com/4a06psM
What would be a good way to tweak this?
http://pastie.org/10727912
http://pastie.org/10727915
Adrian Rosebrock
Keep in mind that the code is only as good as the images that you put into it. The code detailed in this post assumes simple shapes that can be recognized utilizing contour properties. For more advanced shapes, or shapes that have substantial variances in how they appear (such as noisy contours), you might need to train your own custom object detector.
Anyway, the reason sometimes even messy contours get classified differently is due to the contour approximation. Play around with the percentage used in
cv2.approxPolyDP
and you’ll be able to see the differences.Alfarabi
Hi vincent, your shapedetector class to identify triangles is very usefull for me. Can you show me the source of code?
Peng
Hi Adrian,
Thank you for making this. A little feedback on the image file.
I notice that if using a .jpg file as the source, the moment(cnt) will not get a correct value.
It report an error :
cntX = int(M[“m10”] / M[“m00”])
ZeroDivisionError: float division by zero
Any ideas on this?
Thanks
Adrian Rosebrock
Version version of OpenCV and Python are you using?
In either case, you can resolve the issue by doing:
This
if
statement will take care of the divide by zero error.Alternatively, you can add a tiny value to the moment to ensure there is no divide by zero problem:
cX = (M["c10"] / (M["m00"] + 1e-7))
saurabh
can you please elaborate this .. i didn’t get it..
====================================
cX = int((M[“m10”] / M[“m00”] + 1e-7) * ratio)
ZeroDivisionError: float division by zero
====================================
showing this error
Adrian Rosebrock
My original comment is missing a parenthesis:
M["c10"] / (M["m00"] + 1e-7)
Notice how the addition is done before the divide.
Euan
Hi Adrian,
Firstly thanks for a great tutorial and site. I’m a mechanical engineer and noob to openCV, python and linux and have managed to get openCV 3.0 and python2.7 setup thanks to your tutorial here…. https://www.pyimagesearch.com/2015/06/22/install-opencv-3-0-and-python-2-7-on-ubuntu/
In order to get this code running on my setup, I needed to modify “float” on line 17 to “int” as it was causing cast problems on line 43 “c *=ratio”. I believe this is probably due to an update of how python works from how it worked when you wrote this tutorial. Is this the case?
Adrian Rosebrock
Interesting, Brandon mentioned this issue in a comment above. Which version of OpenCV and NumPy are you using?
brandon
Adrian, great stuff. I’ve learned a lot from your blog, and plan on purchasing the book soon. I was working through this post for now, and I’m getting the following traceback error:
Adrian Rosebrock
I personally haven’t seen this error message before. Can you let me know which OpenCV and NumPy versions you are using?
Brandon
numpy is 1.10.4, and it happens with both OpenCV 2.4.12 and 3.1.0 (in a virtualenv, thanks to another of your tutorials) under Python 2.7 on OS X 10.11.3
The workaround was simply to adjust data types pre and post multiplication:
c=c.astype(np.float_)
c *= ratio
c=c.astype(np.int32)
It works now.
Adrian Rosebrock
Thanks for the tip Brandon! I’ll be sure to dive into this more. I’m using NumPy 1.9.3, so perhaps this is an issue with NumPy 1.10.X.
Ahmed Abdeldaim
Great work Mr. Adrian
but is there a way to make the selection more softer, for example by reduce point size ??
or this is the best result??
Adrian Rosebrock
Absolutely, you just need to apply contour approximation first. I detail contour approximation in a few blog posts, but I would start with this one.
Ahmed Abdeldaim
Thanks for your help.
darshan
how to install imutils module
I used pip install imutils I’m getting error
Adrian Rosebrock
Please see the “OpenCV shape detection” section of this blog post. You just need to use
pip
$ pip install imutils
firoz khan
hi adrian it is only detcting one pentagon and nothing else
Adrian Rosebrock
Make sure you click on the window and press any key on your keyboard — this will advance the script. Right now a keypress is required after each detection.
Diego Fernando Barrios
Good afthernoon!
Thanks very much for this tutotrial, you´re doing a great and util work.
Friend, I have a problem with contour detection, when I change the image, the project don’t work (I’m using a black background, I take the image from USB camera). I not have problem with the image path.
The python scripts should recognize (9 “nine” rectangles”) but just one is recognized
Sorry for the writing, my english is not so good.
I would like that you can help me. I’m working in my work grade.
Thanks very much!
Adrian Rosebrock
Depending on your image, this could be an issue with segmentation and/or the contours. Make sure that after thresholding your 9 rectangles have been clearly segmented. From there, move on to the contour approximation and see how many points are returned by the approximation. You might need to tweak the
cv2.approxPolyDP
parameters.itai
Hey Adrian,
I was wondering why did you use the Ramer-Douglas-Peucker algorithm to reduce the set of points, instead of using the convex hull ?
Thanks
Adrian Rosebrock
The contour approximation algorithm and Convex Hull algorithm are used for two separate purposes. As the name implies, contour approximation is used to reduce the number of points along a contour by “simplifying” the contour based on a percentage of the perimeter. Your resulting contour approximation is this a simplification of the shape by utilizing points that are already part of the shape.
The convex hull on the other hand is the smallest convex set that contains all points along the contour — it is, by definition, not a simplification of the contour shape and the resulting convex hull actually contains points that are not part of the original shape.
In this case, I used contour approximation because I wanted to reduce the number of (x, y)-coordinates that comprise the contour, while ensuring that all points in the resulting approximation were also part of the original shape.
Armin
Hello Adrian
thanks for tutorial
I want to show detected shapes in seperate windows( each shape on each window), what should I do?
also tried cropping them (using ROI) but I didn’t able to work it out.
tnx
Adrian Rosebrock
Hey Armin — you’re on the right track. You should be applying array slicing to extract the ROI, then using the
cv2.imshow
function on each ROI. An example of ROI slicing can be found in this blog post as well as Practical Python and OpenCV.Alex Hopper
Hello,
I’m new openCV-Python user.. I have a question about it:
I have a database containing pre-processed images by kinect, and I need use Deep Learning to analyse these images. Is there a best way to start?
https://www.pyimagesearch.com/2016/02/08/opencv-shape-detection/
Can I use it to start?
Thanks.
Adrian Rosebrock
What type of images are you working with? You mentioned they were pre-processed by the Kinect. Are they depth images? RGB images?
Neal
hi
I’m looking for advice in shape detection. I want to use a camera to detect different kinds of shapes on a microcontroller. What would be the best method to approach this?
Your help will be much appreciated.
Thanks
Adrian Rosebrock
Hey Neal — to start, you need to segment each of the components of the microcontroller. Do you have any example images that you’re working with?
Neal
well i’m going to be using different shape cut outs of wooden blocks as my different objects.
Adrian Rosebrock
I would use a similar approach as detailed in this blog post. Cut out your wooden blocks and place the camera such that its “looking down” on the blocks. Apply thresholding or edge detection to find the blocks. And from there, you can use the contour approximation technique to label the shapes.
Anupam
Can you please help me out with detecting overlapping shapes ?
Adrian Rosebrock
For overlapping shapes, I would suggest the watershed algorithm.
Leena
How can we use the shapedetector to classify polygon as rectangle/diamond(decision box)/ parallelogram….
please help
Poehe
Hi Adrian, thank you so much for the tutorial, it’s a great starting point for me to dive into OpenCV.
I noticed when processing images using your code that in pictures with a white background the engine also shows the contours/edges of the whole input picture as being a shape, while in images with a black background (as in your example) the engine ignores the outside contours of the whole input pic and only shows the contours of the objects within the input pic itself (which is the way it should work, I suppose).
Could you think of a solution that makes the engine not classify the picture edges as contours?
Your help will be much appreciated!
Cheers
Adrian Rosebrock
So if I understand your question correctly, you are using a background that is lighter than the shapes themselves? And after thresholding your shapes appear as “black” on a “white” background? Am I understanding that correctly? If so, simply invert the threshold step to make the shapes “white” on a “black” background.
Adam Graham
how exactly would one do that?
Adrian Rosebrock
You can use the
cv2.bitwise_not
function.ARUN YUVARAJ
Hi Adrian,
Thanks for the tutorial.
I understand that using cv2.bitwise_not can solve the problem.
But if we have 10 images and all the images have different colour settings, it is a tedious task to change the threshold every time. Do we have a workaround for that
Adrian Rosebrock
You would need to look into more advanced thresholding methods. Deep learning-based segmentation methods may work well if you have complex backgrounds and/or an image dataset of example objects you want to detect (and can therefore train such a model on).
Megha Maheshwari
Hi Adrian
How can we differentiate between rectangle and trapezoid. I have detected that the polygon contains 4 corners and hence is either a square, rectangle or trapezoid as per my image. However, for square can easily check the width and height, but how do i differentiate between rectangle and trapezoid.
Adrian Rosebrock
There are many ways to do this. I would consider computing the extent (contour area / bounding box area). A perfect rectangle will have an extent of near 1.0 while trapezoid will have an extent much less than 1.0. You can also compute the angle between each corner of the shape. A rectangle would have near perfect 90 degree angles. Either one will work.
Mohamad
Hi Great Man. Mr. Adrian
I guess your offer in this tutorial use the webcam for raspberry pi. its Ok? other question is that for detect other shapes such as (H) similar or (L) similar or … How doing it? Is this method work with edge or point detection?
Adrian Rosebrock
You can certainly use a webcam or Raspberry Pi camera module to perform shape detection. You would just need to read the frame from the camera and process it. I provide tutorials on how to access webcams here.
As for detecting an “H” or “L” you can do that using contour properties (extent, solidity, etc.), template matching, or image descriptors such as Histogram of Oriented Gradients. I would suggest taking a look at Practical Python and OpenCV along with the PyImageSearch Gurus for more advanced demonstrates of recognizing objects in images.
Luís Serrador
Hi Adrian,
I tried two of your tutorials (this one and ‘OpenCV center of contour’) and when I execute the command to run the .py file my result is not the same as you show at the end of the tutorials. My final image only recognize the first shape/center, and doesn’t recognize more shapes. Is there anything that could be wrong?
Adrian Rosebrock
Hi Luís — what versions of OpenCV and Python are you using?
Luís Serrador
Hi Adrian! I’m using OpenCV 3.0 and Python 2.7. Any mistake of mine?
Adrian Rosebrock
Nope, the Python and OpenCV version shouldn’t be an issue. I was just curious about the setup to confirm it wasn’t an outlier situation. I personally haven’t ran into this problem when executing the code. I assume you downloaded the code using the “Downloads” section of this post rather than copying and pasting the code? Sometimes that causes problems with reader’s code as well.
Thomas
Hi Luis,
you should make an empty file of __init__.py , to solve you issue for not detect all the shape from the *.png file.
Jan
Hi Adrian,
Thanks for the tutorial,
I did the same, but for certain cicrles the vertices were shown as 4 and hence were displayed as squares , can you suggest a way to increase the number of detected vertices in the picture.
Thanks
Adrian Rosebrock
You’ll want to play with the following line:
approx = cv2.approxPolyDP(c, 0.04 * peri, True)
The smaller the value passed in for
peri
, the more vertices you’ll obtain.Preethi
Hi Adrian,
From Shape detection i should detect circle alone. even though rectangle,square and etc present. In your Same example i need this modification
Adrian Rosebrock
For circle detection, take a look at this blog post. Otherwise, you can use this code to determine a circle as well. A circle will have many more approximated contour vertices than all other shapes. You basically need to create an
if
statement for this.Niel
Hi, Adrian i’m mechatronic students and now i build an obstacle avoidance robot i like to ask how can i create a detection square box in OpenCV for detect colour so it will give feedback to th robot to move or to stop
Adrian Rosebrock
Hey Niel — can you elaborate on what you mean by a “detection square box”? I’m not sure what you mean.
Chandu
Hi Adrian
i’m getting an error
Traceback (most recent call last):
File “”, line 2, in
from pyimagesearch.shapedetector import ShapeDetector
ImportError: No module named pyimagesearch.shapedetector
Adrian Rosebrock
Hey Chandu — make sure you download the source code to this blog post using the “Downloads” section. It’s likely that your project directory structure does not match mine (perhaps missing a
__init__.py
file. Please download my code and compare it to yours.Arturo
Hi, i´m having a problem with the code, Sorry for my ignorance but where do I have to put the path of the image?
I can´t understand the lines 9-12 where you say that we have to place the path, the (– image) part
Adrian Rosebrock
Hey Arturo, I suggest you read up on command line arguments before continuing. You don’t need to modify the code at all.
tal
Hi, i´m having a problem with the code, i have insert the path into the
ap.add_argument(“-i”, “–image”, required=True, help=”rec.jpg”)
and i’m getting this error.
usage: detect_shapes.py [-h] -i IMAGE
detect_shapes.py: error: argument -i/–image is required.
thanks alot
Adrian Rosebrock
You do not have to modify the code at all. You just need to supply the
--image
switch to the Python script via command line argument:$ python detect_shapes.py --image shapes_and_colors.png
Please read up on command line arguments before continuing.
BKumar
Hey Adrian,
I was wondering about how to find out the number of different shapes in such an example. Like if there are 4 squares, 2 rectangles etc., how can you label them in the image as Square #1, Square #2 or something. Or display the number of instances of each shape in the image.
Thanks in advance.
Adrian Rosebrock
I would use a Python built-in dictionary type and simply count the number of shapes as you loop over them. Your pseudocode might look something like:
This would give you a dictionary of shape counts.
Milán Vincze
Hello!
A get an error when I run the program:
ImportError: No module named ‘imutils’
I installed imutils before. Could you please help?
Adrian Rosebrock
The first part of this blog post discusses exactly how to solve this error message:
$ pip install imutils
Milán Vincze
Yes I know I ran that before I start the program. Maybe the problam is that the raspberry want to run it in python3. How can I run in python2 if I installed python2 and python 3 too?
I thought that is the problem because the installation put the imutils in python2.7 library.
Milán Vincze
I also copied the imutils folder to python3.1 folder
Milán Vincze
Sorry, I copied the imutils to the shape detector folder and it worked, sorry to bother you.
Adrian Rosebrock
For what it’s worth, you could also just install imutils for your Python 3 as well:
$ pip3 install imutils
Milán Vincze
Hello! Adrian
First thank you for the exellent tutorial! I am interesting in a real-time shape detector with the picamera. Maybe there is a tutorial for it that you made?
Adrian Rosebrock
I would suggest using the
cv2.VideoCapture
class or theVideoStream
class covered in this blog post. My book, Practical Python and OpenCV also covers the basics of working with video streams and video files — this would help you port the code over to a video stream rather than a single image.Tyler
Adrian can u suggest what changes to make in this so that we can detect shapes in real time using laptop camera feed ,I would be very greatful
Adrian Rosebrock
The comment you replied to has a link to a blog post + book that I recommend that you read so you can access your laptop webcam. Take the time to study the basics of OpenCV first, then it will be easy to implement this method for real-time applications.
PANJI
Sir i have problem error
usage: detect_shapes.py [-h] -i IMAGE
detect_shapes.py: error: argument -i/–image is required
anyone help me?
Adrian Rosebrock
Please read the comments before you submit your own. I answered your question in reply to “Arturo” above.
Open The CV
Hi, how can I find the angle between a triangle and the horizontal axe ?
Adrian Rosebrock
I’m not sure what you mean. Do you have an example image of what you’re working with?
Open The CV
Problem solved with some trigonometry formulas. Thanks
sandra
Hello, how can i detect certain rectangle which is the border of some text area in an image ?
Adrian Rosebrock
Hi Sandra — I’m not sure I understand your question. It would be helpful if you had an example image of what you’re working with.
Abu
Hello Adrain,
Awesome tutorial, thank you.
I was wondering if there is a way to detect rectangles or squares to exact approximately. Basically, I have an image, and it has shapes and text in it. I only want to detect the shapes and ignore all the text in the image. This tutorial really helped me. But, I am still detecting squares and rectangles in the text of the image. is there a way, I can completely ignore that?.
Thanks.
Adrian Rosebrock
I would compute the solidity of the shape which is the area of the contour divided by the convex hull area. Text will have a lower solidity than a rectangle which should be equal to one.
Laura
Hello Adrian,
Thanks a lot for the awesome tutorial.
I am using the shape detection to get the coordinates from where rectangular elements are located in an image that I am getting from my phone camera. For some specific layouts the code works perfectly, but when I start to place elements in the same row, the coordinates of an specific element are organised in a different order.
However, when I try the same layout from an image I am building in photoshop (not a picture) it works correctly. When I compared both shape detection processes, I realised that the order in which the shapes are sorted is also changing. I tried altering the lightning and contrast of the pictures, but somehow there is something that is altering the order of how the elements are detected and the order of how the coordinates are organised.
Image from camera: http://imgur.com/a/xHaGn
Digital image: http://imgur.com/a/NNsv5
Do you have any idea of what could be the problem?
Adrian Rosebrock
The
cv2.findContours
function will not return contours in a specific order. You should sort your contours if you expect them to be in a given order.Martin
Hi Laura,
I am working on the same topic –> finding squares on picture taken by my phone camera.
Could you share your project with us?
Thanks
jandi
Thanks for this tutorial …
I have a question. In my image, I have a square and lozenge shape and I want to distinguish between them, how can I do that?
Adrian Rosebrock
I would suggest using either:
1. Contour properties, such as extent, solidity, and aspect ratio.
2. Features, such Hu Moments or Zernike Moments.
Thailynn
Hi Adrian,
Is there a way to save the results of the image classification into a new image? For example, identifying all the squares and saving a new image with just the squares. I am trying to do some feature extraction of satellite imagery.
Thank you very much for any insight you can offer!
Adrian Rosebrock
Hi Thailynn — if you are trying to extract each individual square, I would compute the bounding box and extract it using array slicing. You can then write the region to disk using the
cv2.imwrite
function. I cover this in more detail inside Practical Python and OpenCV.Cuningan
Hello Adrian, i ahve bought you curse and now i am seeking this tutorial.
I am using RPI with with OpenCV3.2 compiled like you described on you post.
My problem is that also, python2 and 3 can not find imutils, i have tryed to install it with pip but failed with a large crash…
Any idea about??
Adrian Rosebrock
Which tutorial did you use to install OpenCV? Also, what is the error you are getting when trying to install imutils? Without knowing the error, I cannot provide any suggestions.
disheet
Hello Sir,
I am getting below error.Please give me the solution
File “/usr/local/lib/python2.7/dist-packages/imutils/convenience.py”, line 69, in resize
(h, w) = image.shape[:2]
AttributeError: ‘NoneType’ object has no attribute ‘shape’
disheet
And i am using logitech c170 webcamera.
Adrian Rosebrock
It sounds like OpenCV cannot access your webcam. I discuss NoneType errors (and how to resolve them) in detail inside this post.
disheet
Hello Sir,
How can i do shape detection using webcam?
Adrian Rosebrock
You apply the exact same algorithm detailed in this post, only to every frame of a video. You can access the frames of a video using this post or reading through Practical Python and OpenCV.
morejump
Hi Adrian,
the rectange is shape which has 4 vertices, and also has three of them is 90 degree. cause your algorithm dose not work every time
Doson
I don’t think it is strict to recognize the sharp just by the number of the ‘approx’.For example, a rhomboid have for ‘approx’ but it is neither a square or rectangle.I suggest that more judgement such as checking the degree in each ‘approx’ .If more than three degree was close to 90,maybe 91 or 89,we can believe it is a square or rectangle.
David
Just wanted to say that these tutorials have been amazing! Thanks for publishing these
Adrian Rosebrock
Thanks David, I really appreciate that 🙂
KansaiRobot
Very nice Blog, I have just discovered it. I am going to be browsing through it tomorrow but let me ask you a question. In this post you covered shape detection when the objects are quite separated from each other- therefore you can find the true center.
How about detecting shapes when one shape is touching another or even slightly overlapping it?
Adrian Rosebrock
Take a look at the Watershed algorithm.
Enko
Hi Adrian,
Thank’s for your excellent tutorial, I want to detect circle accurately. I have tried to use HoughCircles in circle detection part:
else:
# shape = “circle”
img = np.zeros(image.shape, image.dtype)
cv2.drawContours(img, [c], -1, (255, 255, 255), -1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1.2, 100)
if circles is not None:
shape = “circle”
but the “circles” is always None. Can you help me?
Adrian Rosebrock
Hi Enko — see this blog post: Detecting Circles in Images using OpenCV and Hough Circles.
KansaiRobot
Part 1) I would like to ask if watershed can be effectively used for adjacent objects that are not circles. In particular tablet-like. (I tried the method and it does not work)
Adrian Rosebrock
In general, yes, the watershed algorithm can be used for these types of objects provided you can obtain a reasonable segmentation.
KansaiRobot
Yes, segmentation is not a problem. I used a discriminant analysis method for segmentation. I can send you the original (non segmented) images or the binarized ones (just purely black and white)
KansaiRobot
An example of my problems can be found here
https://stackoverflow.com/questions/46107628/problems-with-segmenting-pills
I would like to hear your advice on how to tackle this problem. Thanks in advance
Adrian Rosebrock
Do you have the original example image(s)? I would consider writing a blog post on this topic.
KansaiRobot
Thanks. I have some sample images obtained with backward ilumination. (Therefore basically dark shapes on white background). I can send some to you for the post you are considering.
Adrian Rosebrock
Sure, that would be cool to take a look at. Send me a note here or if you already know my email address you can send the images and reference this blog post.
KansaiRobot
Part2) You seem to be using scikit watershed not opencv. Any reason for that?
Adrian Rosebrock
At the time the watershed blog post was published the watershed + connected-component analysis functions in OpenCV were not as easy to use in OpenCV versus scikit-image. That has changed now and I would recommend using whichever one you are more comfortable with.
Kanwal
Hello Sir,
Can you help how to solve the problem of occlusion.
Sameer
Hi Adrian,
When I run the program, only single object is being contoured. What is wrong?
Adrian Rosebrock
Make sure you click the active window and press any key on your keyboard. This will advance the detection.
Yadnyesh
Hello Adrian,
I have slight problem
The code works fine with images which have a black background it detects all the shapes
the problem comes when an image has a white background.
It recognizes the frame of image as a rectangle and none of the shapes within it.
Can you help me with this?
Thank you in advance
Yadnyesh
Sorry for this I read your reply for a comment
So all I have to do this
replace
thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]
with
thresh = cv2.threshold(blurred, 255, 60, cv2.THRESH_BINARY)[1]
Priyam Vora
Hi Ardrian,
How can we detect a cricket bat in a image? Please provide me a detailed idea.
Thank You
Caner Yagci
Hi Adrian, What should I do if I want to detect only the circles ?
Thank you
Adrian Rosebrock
If you want to detect only the circles you should take a look at this blog post where I filter contours or apply the Hough Circles method.
james
hello can you help me to detect an custom object like “H” key word real time ???? how we can do that with countours or somthing else
Adrian Rosebrock
Hey James — do you have any example images of what you’re working with?
Emre uysal
hi adrian
how can i detect resistor shape or undefined shape?
thanks
Adrian Rosebrock
I’m not sure what you mean by “undefined shape”, but I would suggest training a custom object detector. The Histogram of Oriented Gradients method would be a great starting point.
Oshada
How to apply this technique for unfilled shapes?
Adrian Rosebrock
By “unfilled” do you mean just the outline of a shape?
Oshada
Yeah. It works now. But, the problem is I have to change the threshold when a different image is used. I want to convert a hand-drawn flow chart into a stored procedure. How do I solve this issue?
Adrian Rosebrock
Take a look at “adaptive thresholding”. Adaptive thresholding works by thresholding on local areas. It might work well for you in this situation. Also take a look at Otsu’s thresholding. I cover both inside Practical Python and OpenCV.
Mustafa Ismail
Hello, thank you for the awesome tutorial man!
I’m tryna detect a shape like this https://drive.google.com/open?id=11D4SiYQ84TYDA0aZxaEDm5MDlY6lWWaW
and as you can see the shape on the right is perfectly detected by following your tutorial and tuning some parameters. However i’m having a problem on detecting half colored shapes like the shape on the left, as you can see the thresholding technique classifies the blue part as black.
So any ideas on how to solve this? I need to detect the whole object as a triangle
Adrian Rosebrock
You will need to play with the thresholding parameters (or try adaptive thresholding) or try Canny edge detection instead. Secondly, make sure there is sufficient contrast between the foreground (the shape you want to detect) and the background. If there is not enough contrast, thresholding and edge detection methods will not work.
Oshada
Hi Adrian, I tried to identify shapes in hand-drawn flowcharts like this.
https://ibb.co/d10sEG
The case is sometimes because these are hand-drawn diagrams, there can be unclosed shapes(specially in corners) which mess up the detection. So I used closing operation and it resolved the problem. But, when gap between shapes and arrows and text is less, everything tends to linked and it create messed up contours. Is there are way to get rid of this problem without putting condition like users have to put at least this much of gap between items. Also, I can’t get rid of the closing operation.
Adrian Rosebrock
There are a few ways to approach this problem, but have you considered training an object detector to recognize each of these shapes? HOG + Linear SVM would be a good starting point. This would alleviate the new to rely on image processing operations and make your algorithm more extendible.
Oshada
The problem is my supervisor has highly recommended me not to use any ML or DL approaches first. That is why I have been trying to use contour analysis, mathematical relationships among different shapes and etc. I have done detection parts and everything putting that restriction I mentioned. And I want to get rid of it. Can you give me some tips to do that without going for ML.
Adrian Rosebrock
You’ll need to continue to fiddle with the parameters to your morphological operations if you want to continue using non-ML solutions. That’s perfectly fine from a education standpoint but keep in mind that your method won’t be as robust.
bhuvan
Hi Adrian,could you mention other ways to approach this problem?
Juhi
ModuleNotFoundError: No module named ‘pyimagesearch’
Please help.
Adrian Rosebrock
You need to use the “Downloads” section of the blog post to download the code. Unzip the .zip archive. Change directory to where the code is stored. Then execute it via the command line.
Darshan kumar
Hi Adrian! I am looking for a code which has the same properties for a real time video and also to find the co ordinates on a plane. And may be midpoints as well.
Andrew R
Hi Adrian
Thanks for posting this – and your other examples – really clear and super helpful.
Adrian Rosebrock
Thanks Andrew, I’m glad you enjoyed the post! 🙂
Tom S
Hi Adrian,
Thanks for this and all the other awesome posts!
I’m really new to OpenCV and have been trying recently to implement it into my capstone project for undergrad. I’m using a number of your tutorials for help in this. The problem I’m running into with this one is identifying shapes that are really close together. I need to get the shapes of each individual Lego in an image so I can translate it to code using a syntax my team created. A sample of the code can be seen here:
https://imgur.com/a/OjwE5
So far it’s only detecting the entire block structure like so:
https://imgur.com/a/8cvRP
Any help you could offer in finding shapes that are closer together would be greatly appreciated. Thank you in advance!
Best,
Tom
Adrian Rosebrock
Keep in mind that you’ll only be able to find individual contours for each lego piece if you can cleanly segment each piece via thresholding, edge detection, etc. In this case you’re detecting all of the legos at once. It’s impossible for the cv2.findContours function to know that you’re trying to extract each individual lego. Instead, I would recommend you use color thresholding methods to help you segment each set of legos.
Tom S
Ignore the previous comment, I did end up trying the color detection first and then using shape detection. It worked like a charm, thanks!
Adrian Rosebrock
Awesome! Congrats, Tom 🙂
Tom S
I decided to detect the shapes after each color had been detected and that worked well!
Kay
Hi Adrian,
I have two rectangular to be detected but it only detect one and from the previous reply of yours, I need to pressed any key on the keyboard but it closed the program and does not advance the detection. How to make them show all the detect shape in one go?
Adrian Rosebrock
It sounds like the second rectangle is:
1. Not being detected by the threshold process
2. If it is being detected, the contour approximation is not returning 4 coordinates
You will need to debug both of these. I would suggest starting with the “thresh” map (you can debug it using cv2.imshow).
Additionally, if you are new to working with OpenCV and Python I would recommend reading through Practical Python and OpenCV to help you get up to speed. I hope that helps point you in the right direction!
kasun
i used this approch to identify the er digram shpes.up to now i identify the few shapes but i need to identify the double rectangle (Week entity)double elipse(multi value attribute) dotted elipse(derived attribute )can you dive mee tip for identiy those shapes
kasun
those er digrams are hand drawn ones so up to now i didn’t use any ml or dl methos.but tell me can do this easyly using ml or dl .plese tell me easyest way to so this?
Adrian Rosebrock
Do you have any example images of the hand drawn diagrams you are working with?
kasun
ya i have .this is link for that
https://drive.google.com/open?id=1JEJ_RySZ04FYIVYl3Zf1jjryAR5OmYPU
only threre you can see double rectangle and double diamond also have double elipse and doted elipse too.
Adrian Rosebrock
There are a few things you can do for this. You either extract the contour hierarchy for the double rectangle/double diamond or you can extract the outer shape and then do another series of contour detections to detect any inner shapes.
Manuel
works great ! but with 200×150 resolution not working. I have camera 1 meter above the floor. What can i do ? Thank you !
Adrian Rosebrock
Can you increase the resolution of your input images?
Mitch
Thanks for the great tutorials. Can you explain why you initially resize the image (“load the image and resize it to a smaller factor so that the shapes can be approximated better”) and its implication about improved performance? Thank you.
Adrian Rosebrock
While high resolution images are appealing to the human eye, they can be a problem to computer vision algorithms. The larger an image is, the more data there is to process, and therefore the algorithm will run slower. Secondly, reducing an image size reduces the amount of detail in an image, which can be seen as a “noise reduction”, allowing us to focus on the objects/components in an image that actually matter.
I hope that helps and if you’re interested in learning more about the fundamentals of image processing and computer vision be sure to refer to Practical Python and OpenCV. I’m confident the book will help you get up to speed quickly.
ali
Hi Adrian
i have a image with green bounding box, i want to get coordinates of bounding box. please guide me.
Adrian Rosebrock
I’m a little confused here. Typically we create computer vision algorithms to detect the (x, y)-coordinates of an object in an image and then draw a bounding box surrounding it. It sounds like you have the opposite workflow — you have a green bounding box already in an image and you want to detect the location of it?
ali
Yes, precisely, I want to get the position of the bounding box, and then I draw it in another image in the same place.
Adrian Rosebrock
Got it, I understand now. There are two options here.
1. Apply color thresholding to find green regions. Then process the contours to filter out only the box itself.
2. Train an object detector to find only squares.
The second option would be more accurate but would require significantly more work.
Yadira
Hi Adrian,
When I try to run the code I keep getting “the following arguments are required: -i/–image”
it may have the simplest solution in the world, but I’m not sure what to change
Adrian Rosebrock
Reading this post on command line arguments will help you resolve the issue.
Dan
Dear Adrian,
Awesome work! It is quite useful.
I have a question regarding the edge effect.
The contour approximation goes wrong when I tested on some shapes with jagged edges.
Does this mean that the method works perfectly, assuming the edge is smooth?
I wonder whether you have published a paper about this?
I’m not a computer vision newbie and many thanks in advance for your explanation.
cheers,
Dan
I mean I am a newbie in computer vision ….. ahh
Adrian Rosebrock
Yes, this method does assume that you can cleanly segment the foreground from the background. If you cannot obtain a clean segmentation than this method will likely fail.
Additionally, if you are new to OpenCV/computer vision I would definitely recommend working through my book, Practical Python and OpenCV. I wrote this book for readers new to computer vision as you are. Give it a try, I’m confident that once you go through it you’ll be able to more easily understand the concepts discussed on this blog.
Dan
Hi Adrian,
Can this method detect other shapes such as an octagon, hexagon, etc?
Many thanks!
Adrian Rosebrock
Yes, you would just need to check the number of vertices in the approximated contour (as we have done in this example).
Geetanjali Sahoo
hi Adrian,
how to know the connector between two shape ? like an arrow between rectangle and square?
Adrian Rosebrock
There are a few ways to do this, some easier than others. For an arrow you could use the contour approximation technique discussed here or you could compute the solidity and extent of the contour and use them to help determine if a particular shape is an arrow.
Henrique
Hi Adrian !
I’m working on computer vision applied to drones, and I need to calculate the area of a shape on the ground, seen from a camera on the copter. I’ve seen this tutorial and “Measuring size of objects in an image” also. Is there any implementation in which both could return the area of the shape ? Thank you, appreciate your work a lot !
Adrian Rosebrock
Hey Henrique — your project is a very specific and you’ll need more advanced techniques here. I would suggest first calibrating the camera via an intrinsic/extrinsic calibration computation. From there you’ll be able to compute a more accurate measurement of the area.
Andrea
Adrian, please could you tell us where we can see how the function imutils.resize() is defined? Thanks
Adrian Rosebrock
The “imutils.resize” function is defined inside the imutils library.
Adnan KHan
Hi,
I want to extract the text (in order) from an image using Pytesseract. For the reason I want to detect rectangles in the image first then split the image based on those rectangles and then feed those sub-images to Pytesseract.
So how would I detect the rectangles in this image? https://imgur.com/8sfUyXe
Adrian Rosebrock
I would first perform a perspective transform like we do in this tutorial to obtain a top-down view of your paper. From there, a Hough lines transform would help you detect the rectangles.
Josh Doran
When running the code, only the pentagon is recognized, none of the other shapes are looped through. Can’t figure out why this happens.
Adrian Rosebrock
You need to click on the active window opened by OpenCV and press any key on your keyboard to advance execution of the script.
pavan varyani
hello Adrian, thanks for the lovely tutorials.
i have an issue, the green contours are not being drawn at the right location , they are being drawn at random locations,rest (centre detection,shape detection seemd to be perfect).
Adrian Rosebrock
That’s quite odd. Are you using the code and images from this blog post? Or your own custom images?
pavan varyani
Hey the code works fine now, i just had to play and tinker a little around with the resizing amount of the width 🙂
pavan varyani
Hello Adrian thanks for posting such extraordinary helpful content over the internet.
i have a very fundamental doubt, could you please enlighten me why are we exactly resizing the image before we begin with the manipulations.
Adrian Rosebrock
1. The less data we have to process, the faster our algorithms run.
2. While higher resolution images may look aesthetically pleasing to us they actually hurt CV algorithm performance. We reduce image size as a form of “noise reduction”.
pavan varyani
thanks 🙂 ,could you please brief me on the approach to the picture containing shapes (drawn on paint tool) ? the same code when tried on a customised picture containing shapes (made on paint tool), detects only the shape of the canvas part of the picture.
Nirmal Mandal
Hello, can u tell me how can detect hologram from national id card.
Adrian Rosebrock
Sorry, I do not have any experience with hologram detection.
Arya
Sir please help me install open CV in my laptop to start doing my project.
My system is operating in windows.
Please reply me
Adrian Rosebrock
Hi Arya — I have a number of OpenCV install tutorials; however, please keep in mind that I only support macOS and Linux here on the PyImageSearch blog (I do not support Windows). I recommend you use macOS or Linux for computer vision.
boba
Adrian,I am working on my school project where i want to to identify shapes from images.
I would like to store the location and co-ordinates of these shapes.What methods can be used from OpenCV (python)?
Adrian Rosebrock
What specific coordinates? The bounding box coordinates? The (x, y)-coordinates of the outline/contour of the shape? Just the center (x, y)-coordinates of the shape?
boba
Adrian,
Automatically detect/identify different possible shapes (coordinates of the outline/contour of those shapes) from any given image (things/people/objects).
Adrian Rosebrock
You would need to train your own custom object detector. Be sure to refer to this guide for more information.
Amvoxite
Adrien,
What do you make of this problem finding imutils.grab_contours(…)?
When I run this script I get:
AttributeError: ‘module’ object has no attribute ‘grab_contours’
Adrian Rosebrock
You need to upgrade your imutils install:
$ pip install --upgrade imutils
John Kent
Long thin rectangle (14:1) being detected as a circle.
Tried every combination of modes & methods.
Happy to send code and test image.
Dheeraj Bansal
Is it possible to count people using shape detection by detecting the shape of forehead?
Adrian Rosebrock
No, you would be better off using an object detector that is trained to detect people. See this tutorial as an example of people counting.
Adam
How would I change the program so that it counts the total amount of each shape and outputs the data somewhere? Like the total number of squares different from the total number of triangles or circles.
Adrian Rosebrock
You would use a Python dictionary or Counter object to increment a count each time an object is identified. From there you can log the output anywhere you wish using basic file I/O.
Adam
thank you for your help. I was able to figure it out!
Adrian Rosebrock
Congrats! 🙂
Eva
Adrian, is there any chance to detect shapes that are empty, I mean that we only have the contour?
Thanks!
Adrian Rosebrock
How are you defining “empty” in this case? What is an “empty shape”?
Jenny
I think what Eva means is, like you drawing a shape onto a white paper, but not colored “inside” the shape. Only the frame (so inside the shape is still white, or “empty”). Would that be possible that could detect the shape as well?
Adrian Rosebrock
If I’m understanding the question correctly (and I’m still not convinced that I am), but yes, provided you have the outline of the shape, regardless of whether it’s colored in, you can still detect it.
HM
Hi
any one can tell if i can use this codes to detect shape in image that had been taken by a cheap camera? the image will contain a specific number of regular shapes with almost known coordinate. Actually, it will be a scan for Rubik’s cube that its small faces in each side will be covered with the same shape, but of course the photo will be taken after the cube scrambled
Michael
I am getting an error saying “module ‘imutils’ has no attribute ‘grab_contours'” what do i do?
Adrian Rosebrock
You need to upgrade your install of “imutils”:
$ pip install imutils
Gabo
Hello! Hey how can I do this with a rapsberry camera?
Adrian Rosebrock
Yes, you can learn how to access your Raspberry Pi camera module in this tutorial.
PRAJWAL
How to download PYIMAGE LIBRARY ??
Adrian Rosebrock
You can use the “Downloads” section of the tutorial to download the “pyimagesearch” library.
PRAJWAL
Sir .how to download pyimage.shapedetector library
Adrian Rosebrock
You can use the “Downloads” section of the tutorial to download the “pyimagesearch” module.
Laura
Hi Adrian,
Thank you so much for this!
It detects only the shell not any of the shapes, when I try the key press to advance the script it just cancels the script. Any thoughts on this?
Thank you!
L
Adrian Rosebrock
I’m not sure what you mean by “cancels” the script. Click on the window opened by OpenCV and press a key on your keyboard to advance execution.
Davood
Hi Dear Adrian
1- If we have many rectangles (or squares, circles,…), then the code works?
2- If the shapes somehow covered each other, then the code works?
Adrian Rosebrock
1. Yes.
2. No, you would need to use the Watershed algorithm.
George
hi. I am very thankful for your explanation tutorial. While following, I found some polygons with round corners have incorrect result because of the wrong detection of corner, even though change the epsilon value. In this case, any advice for analyzing polygon? I’m considering Hough Transform to detect polygon line. thank you very much!
Adrian Rosebrock
I would suggest using a more advanced object detector. See this tutorial.
Ramesh
Hi adrian. Really a very great job done by you. It is very useful one to lot of students.
Here I am getting a problem in identifying the shapes the remaining part of the program run well along with contours also drawn on images. But the problem is it doesn’t showing labels.
Please helm me regarding this issue.
james
hi adrian I search alot about how to detect “H” sign of helipad in any orientation with contour.
how can I detect that?
I tried ocr and tempte matching and sift and surf
but many of them have problem in rotation
and scales.
Adrian Rosebrock
One method would be to train a custom object detector. How many example images do you have of the “H” on the helipad?
russom
can we find the area of the shapes now
Adrian Rosebrock
You can use the “cv2.contourArea” function to compute the contour.
Pragash
Hi Adrian,
Thanks for the Tutorial. How can I detect a “X mark” on a image, in specific a “Cross shaped” fiducial marker on a PCB board?
Adrian Rosebrock
There are a few ways to try it. Consider performing template matching or training your own HOG + Linear SVM detector.
Pragash
Thanks for giving me a head start. I will try it.
pk
did you figured it out?
corentin
Hello Adrian,
This is incredible ! I have an ideas but I don’t know if it’s possible…
I’m printing on leather, and I would like to detect the shape of leather (not a simple square or circle),
When image was create, launch a script to open photoshop and create a stencil.
Do you think it is possible ?
Thank you !
Alex
Hi,
Thank you for this tutorial.
I think there is a speeling error : “This leads[..] the original cruve.” I guess “cruve” means “curve” 🙂
Alex
Adrian Rosebrock
You are correct, thank you for pointing out the spelling error. It’s now been fixed.
Askar Shah
Can you help me in making/training my own Image Classifier ?
PAID
Adrian Rosebrock
Take a look at the PyImageSearch Gurus course which includes information on how to train your own custom image classifiers.
Pranav Chaturvedi
Hi, Adrian.
Very much appreciate the tutorials.
I have been attempting to draw contours on the object using the same code above but the green color is not coming, although I did use (0, 255, 0). Instead it’s coming in black. Would you know why this is happening?
Adrian Rosebrock
Perhaps you’re trying to draw on a grayscale image versus a RGB one?
Samantha Cruz
Hi Adrian! Thanks for this. I was wondering if you have anything similar for real-time shape detection?
Rob
Hey great tutorial,
Small question:
thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]
what does the [1] do for the thresholding here? is this something python specific?
Adrian Rosebrock
The “cv2.threshold” function returns a 2-tuple of:
1. The threshold value used (very useful if performing automatic thresholding using Otsu’s method)
2. The thresholded image itself
As next steps, I would suggest you read Practical Python and OpenCV so you can learn the fundamentals of the OpenCV library.