Skip to content

Tutorials

Simple shape detection – Opencv with Python 3

Access community, courses and source codes
Logo

AI Vision Academy

Access the code of this tutorial, computer vision courses and an exclusive community on AI Vision Academy

  • Access to over 50+ source codes from Pysource.com/blog
  • Dedicated video courses about computer vision
  • Access to an exclusive community of professionals
  • Real-World AI Projects – Get hands-on experience building practical AI Computer Vision solutions with a structured path.
  • Monthly Coaching Calls – get support and any of your questions answered

Subscribe to our newsletter to learn more

We’ll se in this video how to perform a simple shape detection.
Starting from an image with a few shapes, we’ll be able to detect exactly each shape (rectangle, circle, pentagon, etc.) and the position.

As first thing we need to import the libraries, then on line 4 we also define the font that we will use later on to display the text on the image.

import cv2
import numpy as np

font = cv2.FONT_HERSHEY_COMPLEX

We then load the image, we get the threshold of the image to have a black and white image, where the background is white and all the shapes are black.

From the black and white image we find the contours, so the boundaries of all the shapes.

img = cv2.imread("shapes.jpg", cv2.IMREAD_GRAYSCALE)
_, threshold = cv2.threshold(img, 240, 255, cv2.THRESH_BINARY)
_, contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

We loop trough the contours, so we get the coordinates of the contours of each single shape.
On line 10 we approximate the contours to remove the noise.

for cnt in contours:
    approx = cv2.approxPolyDP(cnt, 0.01*cv2.arcLength(cnt, True), True)
    cv2.drawContours(img, [approx], 0, (0), 5)
    x = approx.ravel()[0]
    y = approx.ravel()[1]

    if len(approx) == 3:
        cv2.putText(img, "Triangle", (x, y), font, 1, (0))
    elif len(approx) == 4:
        cv2.putText(img, "Rectangle", (x, y), font, 1, (0))
    elif len(approx) == 5:
        cv2.putText(img, "Pentagon", (x, y), font, 1, (0))
    elif 6 < len(approx) < 15:
        cv2.putText(img, "Ellipse", (x, y), font, 1, (0))
    else:
        cv2.putText(img, "Circle", (x, y), font, 1, (0))

Finally we display everything on the screen:

cv2.imshow("shapes", img)
cv2.imshow("Threshold", threshold)
cv2.waitKey(0)
cv2.destroyAllWindows()

21 comments

  1. C:\Users\Kiran\AppData\Local\Programs\Python\Python37-32\python.exe D:/PythonEx/Libraries/OpenCV/obj_det1.py
    Traceback (most recent call last):
    File “D:/PythonEx/Libraries/OpenCV/obj_det1.py”, line 14, in
    cv2.drawContours(img, cnt, 0, (0), 5)
    cv2.error: OpenCV(4.0.0) C:\projects\opencv-python\opencv\modules\imgproc\src\drawing.cpp:2509: error: (-215:Assertion failed) npoints > 0 in function ‘cv::drawContours’

    I always get this assertion failed error, please help

  2. error: OpenCV(4.0.1) C:\projects\opencv-python\opencv\modules\imgproc\src\contours.cpp:197: error: (-210:Unsupported format or combination of formats) [Start]FindContours supports only CV_8UC1 images when mode != CV_RETR_FLOODFILL otherwise supports CV_32SC1 images only in function ‘cvStartFindContours_Impl’

    i am getting this error on binary image.

  3. img = cv2.imread(“/home/anonymous/Downloads/images/mine.jpg”, cv2.IMREAD_GRAYSCALE)
    _, threshold = cv2.threshold(img, 240, 255, cv2.THRESH_BINARY)
    _, contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    Error :
    ValueError: not enough values to unpack (expected 3, got 2)

    1. write _, contours = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
      instead of _, contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

  4. Hello,

    Just run your script with your image and got an error : 215 Assertion failed .. Many THanks for your inputs !
    ———————-
    error Traceback (most recent call last)
    in
    25 cv2.putText(img, “Circle”, (x, y), font, 1, (0))
    26
    —> 27 cv2.imshow(“shapes”, img)
    28 cv2.imshow(“Threshold”, threshold)
    29 cv2.waitKey(0)

    error: OpenCV(3.4.2) /opt/concourse/worker/volumes/live/9523d527-1b9e-48e0-7ed0-a36adde286f0/volume/opencv-suite_1535558719691/work/modules/highgui/src/window.cpp:356: error: (-215:Assertion failed) size.width>0 && size.height>0 in function ‘imshow’

  5. print(len(approx))
    When I run the code with this command ,its shows numerous values like 4,6,23,2,4,….I also tried by changing its threshold value …Is there anyway to fix it??

  6. Hello i have this erro when i run the code who i can fix it ?
    C:\Users\ASUS\PycharmProjects\vision_project\venv\Scripts\python.exe “C:/Users/ASUS/PycharmProjects/vision_project/simple shape detection.py”
    Traceback (most recent call last):
    File “C:/Users/ASUS/PycharmProjects/vision_project/simple shape detection.py”, line 6, in
    _, contours ,_ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    ValueError: not enough values to unpack (expected 3, got 2)

    Process finished with exit code 1

    1. For Opencv 3.x;
      _, contours ,_ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

      For OpenCV 2.x, 4.x
      contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

  7. For Opencv 3.x;
    _, contours ,_ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    For OpenCV 2.x, 4.x
    contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

Join the discussion