64

My simple Python code is this

import cv2

img=cv2.imread('Materials/shapes.png')

blur=cv2.GaussianBlur(img,(3,3),0)
gray=cv2.cvtColor(blur,cv2.COLOR_BGR2GRAY)
returns,thresh=cv2.threshold(gray,80,255,cv2.THRESH_BINARY)

ret,contours,hierachy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

for cnt in contours:

    area=cv2.contourArea(cnt) #contour area
    
    if (area>1220):
        cv2.drawContours(img,[cnt],-1,(0,255,0),2)
        cv2.imshow('RGB',img)
        cv2.waitKey(1000)
        print(len(cnt))

import numpy as np

contours=np.array(contours)

print(contours)

This worked fine. But recently without me even making any changes. This was throwed to me

ret,contours,hierachy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

ValueError: not enough values to unpack (expected 3, got 2)

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Indunil Aravinda
  • 793
  • 1
  • 5
  • 11
  • Does this answer your question? [too many values to unpack calling cv2.findContours](https://stackoverflow.com/questions/43960257/too-many-values-to-unpack-calling-cv2-findcontours) – Dan Mašek Feb 11 '21 at 12:52

2 Answers2

140

the function cv2.findContours() has been changed to return only the contours and the hierarchy and not ret

you should change it to:

contours,hierachy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
Aaron_ab
  • 3,450
  • 3
  • 28
  • 42
Rami Isam
  • 1,412
  • 1
  • 7
  • 6
  • 3
    Thanks, but in what version was this change introduced? – Osman-pasha Jan 28 '19 at 17:05
  • 6
    so, they've broken compatibility again, but python module is still cv2. – Osman-pasha Mar 19 '19 at 08:56
  • 1
    @Osman-pasha who is "they" in this context? Also the 2 in `cv2` is just a namespace and has nothing to do with the actual version. They, as in the developers of OpenCV do in fact follow semantic versioning, and this change was introduced when changing major version from 3.x to 4.x, which is fine. The tone you set in "broken compatibility again" suggests you might not appreciate the correct way in which it was handled. So to answer your question, it was introduced in version 4.0, and yes, it still uses the `cv2` namespace. – swalog Nov 05 '20 at 18:55
  • 4
    @swalog Yes, you get my point well. You see, a lot of examples on the internet do not mention what OpenCV version is used and just tell you to `pip install opencv` (or say nothing at all). And all of a sudden, the examples don't work because the API has changed. Had they (yes, OpenCV developers) used cv2 for OpenCV 2, cv3 for OpenCV 3, etc, there would be no such confusion, because it would be clear from code what major version to use. I'm sure they had their reasons to keep cv2 and it's more related to C++ API then to major version, but retrospectively to me this seems to be a bad descision. – Osman-pasha Dec 23 '20 at 12:26
15

Well explained in this python code example, the best way to make your code version-proof is with this following syntax:

# check OpenCV version
major = cv2.__version__.split('.')[0]
if major == '3':
    ret, contours, hierarchy = cv2.findContours(im.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
else:
    contours, hierarchy = cv2.findContours(im.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

This provides you with a code that could run on either last or older version of OpenCV.

Thomas Di Martino
  • 380
  • 1
  • 4
  • 10