'cv2.findContours function is not working in both versions

I am new to computer vision and haven't really went through any tutorials on thresholding or blurring or other filters. I am using the below two piece of codes which finds out the contours in an image. On one hand the method is working but on the other it is not. I would need help in understanding the reason this is happening so as to convince myself what is happening in the background.

Working code snippet:

    img=cv2.imread('path.jpg')
    imgBlurred = cv2.GaussianBlur(img, (5, 5), 0)
    gray = cv2.cvtColor(imgBlurred, cv2.COLOR_BGR2GRAY)

    sobelx = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize=3)
    cv2.imshow("Sobel",sobelx)
    cv2.waitKey(0)
    ret2, threshold_img = cv2.threshold(sobelx, 120, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)


    im2, contours, hierarchy = cv2.findContours(threshold_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

Not working code snippet

# read image
    src = cv2.imread(file_path, 1)

    # show source image
    cv2.imshow("Source", src)

    # convert image to gray scale
    gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)

    # blur the image
    blur = cv2.blur(gray, (3, 3))

    # binary thresholding of the image
    ret, thresh = cv2.threshold(blur, 200, 255, cv2.THRESH_BINARY)

    # find contours
    im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

I would really appreciate if anyone can find out the reason for the wrong which is happening here.

The error that i am facing is:

Traceback (most recent call last): File "convexhull.py", line 27, in im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) ValueError: not enough values to unpack (expected 3, got 2)

Let me know if any other information is also required.



Solution 1:[1]

This is due to a change in openCV. Since version 4.0 findContours returns only 2 values: the contours and the hierarchy. Before, in version 3.x, it returned 3 values. You can use the documentation to compare the different versions.

The second code snippet should work when you change your code to:

# find contours
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

Why the first snippet picks a different openCV version can't be determined from the information given.

Solution 2:[2]

The following snippet will work irrespective of the OpenCV version installed in your system/environment and will also store all the tuples in individual variables that can be used later in the code.

Store the major version of OpenCV installed:

import cv2
major_version = cv2.__version__[0]

Based on the version either of the following two statements will be executed and the corresponding variables will be populated:

if major_version == '4':
    contours, hierarchy = cv2.findContours(image_binary, cv2.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

elif major_version == '3':
    image, contours, hierarchy = cv2.findContours(image_binary, cv2.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

The contours returned from the function in either scenarios will be stored in contours.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 J.D.
Solution 2 Jeru Luke