Skip to content

Beginners Opencv · Tutorials

Find and Draw Contours – OpenCV 3.4 with python 3 Tutorial 19

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’re going to see in this tutorial how to find and draw the contours.
Contours are simply the boundaries of an object.

We first import the libraries and we load the Camera.

import cv2
import numpy as np

cap = cv2.VideoCapture(0)

We start the while loop to work with a video, so we loop trough frame after frame.
On line 7 we blur the frame to remove the noise for the contorus detection, otherwise we would many false contours, or not so clean boundaries.
On line 8 we convert the frame from BGR to HSV format. We need to do this so that later we can create a mask.

while True:
    _, frame = cap.read()
    blurred_frame = cv2.GaussianBlur(frame, (5, 5), 0)
    hsv = cv2.cvtColor(blurred_frame, cv2.COLOR_BGR2HSV)

We define the HSV ranges lower and upper of a specific color, in our case we choosed the blue.

    lower_blue = np.array([38, 86, 0])
    upper_blue = np.array([121, 255, 255])
    mask = cv2.inRange(hsv, lower_blue, upper_blue)

We can at this point find the contours using the opencv built in function findContours.
The value contours contains an array with the coordinates of all the contours of the object.

    _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

We loop trough the countours and we draw each single one.

    for contour in contours:
        cv2.drawContours(frame, contour, -1, (0, 255, 0), 3)

Finally we display everything.

    cv2.imshow("Frame", frame)
    cv2.imshow("Mask", mask)
    key = cv2.waitKey(1)
    if key == 27:
        break
        
cap.release()
cv2.destroyAllWindows()

 

 

21 comments

  1. _ , cnts , _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    ValueError: not enough values to unpack (expected 3, got 2)

    i am getting this error please help me to solve this error as soon as possible.

    1. This is Tuple unpacking in Python.
      Basically, you have a function f (cv2.findContours) which do some job and as result returns multiple values (x,y,z…n) . In current case this function returns two values (x, y)
      in order to catch this values and do something with them, you are assigning variables to the function output, pairing variables(_ , cnts , _) with output values (x, y) trough “=” sign .
      This means that, when above code is processed
      _ , cnts , _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
      it is processed like this :
      1. function is executed and returns some values (x,y) so above becomes
      _ , cnts , _ = x, y
      2. afterwards “_” is assigned value of x , “cnts” is assigned value of y and than you are trying to assign non existing value to the “_” again, which is no possible.
      so you should use either
      _ , cnts = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
      or cnts , _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
      It is more Pythonic if variables are understandable so I would suggest to use some other word instead of “_”
      Cheers!

  2. Traceback (most recent call last):
    File “C:\Users\user\Desktop\888.py”, line 11, in
    _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    ValueError: need more than 2 values to unpack
    >>>

  3. hi first realy nice video but I have the same problem as James. can someone tell me how to fix this problem ?
    Traceback (most recent call last):
    File “C:/Users/user/.PyCharmCE2018.2/config/scratches/Formen.py”, line 35, in
    _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    ValueError: not enough values to unpack (expected 3, got 2)

  4. Thank you for your lessons.
    I used this code for an image(not video) but added user`s input for color criteria.
    It finds contours properly. Each time user enters color, it draws new contour, but previous remain.
    Is it possible to clear previous contours?

  5. Hİ,
    cv2.drawContours(frame, [contour], -1, (0, 255, 0), 3)
    cv2.error: OpenCV(4.1.1) C:\projects\opencv-python\opencv\modules\imgproc\src\drawing.cpp:2509: error: (-215:Assertion failed) npoints > 0 in function ‘cv::drawContours’

    [ WARN:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (674) SourceReaderCB::~SourceReaderCB terminating async callback

  6. Hi Sergio.
    I have jpg or bmp image showing a multimeter non color lcd display. The goal is to apply all the reprocessing on the image and print out the actual digits of the multimeter lcd display, using pycharm + openCV.

    So far, I have applied resizing, grayscale, blurring and canny edge. All fine and it works (pycharm + openCV)
    Now I want to apply contours, make box and then find the actual digits and extract the numbers of what the acutal lcd display shows.

    Can you help me?

    1. You can shake the pixel value like this:
      image[y,x]=[B,G,R]
      where y and x are the y and x coordinates of the pixel and B,G,R are the blue,green and Red values of the pixel so if all channels are 255 that means it is a white pixel. In a nutshell you can access a pixel value using its x and y coordinates,by using two loops you should be able to scan through every pixel value to check their values. It’s all hypothetical as a solution sorry I didn’t try it but I guess it should work.All the best

Join the discussion