2

I am a python beginner . I was trying to run this code :

#applying closing function 
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
closed = cv2.morphologyEx(th3, cv2.MORPH_CLOSE, kernel)

#finding_contours 
(cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    cv2.drawContours(frame, [approx], -1, (0, 255, 0), 2)

when I summon the mask.py I got this ValueError :

Traceback (most recent call last):
  File "mask.py", line 22, in <module>
    (cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
ValueError: too many values to unpack

what is wrong with this code ?

Dan Mašek
  • 17,852
  • 6
  • 57
  • 85
aku putri
  • 101
  • 1
  • 7
  • have you tried removing the parentheses? cnts, heir = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) – user1269942 May 14 '17 at 04:12
  • Which version of OpenCV? I assume you're using 3.x, but writing code meant for the 2.x branch. There were some API changes -- one of those being that `findContours` returns 3, instead of the original 2 values. Read the documentation! – Dan Mašek May 14 '17 at 04:13
  • Possible duplicate of http://stackoverflow.com/questions/39598724/convert-knn-train-from-opencv-3-to-2 – ivan_pozdeev May 14 '17 at 04:28
  • 1
    Possible duplicate of [compatibility issue with contourArea in openCV 3](http://stackoverflow.com/questions/39475125/compatibility-issue-with-contourarea-in-opencv-3) – ZdaR May 14 '17 at 07:16

2 Answers2

11

It appears that you're using OpenCV version 3.x, while writing code intended for the 2.x branch. There were some API changes between those two branches. Since you're using Python, you have a handy help available -- make sure to use it, along with the documentation.

OpenCV 2.x:

>>> import cv2
>>> help(cv2.findContours)
Help on built-in function findContours in module cv2:

findContours(...)
    findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy

OpenCV 3.x:

>>> import cv2
>>> help(cv2.findContours)
Help on built-in function findContours:

findContours(...)
    findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> image, contours, hierarchy

This means that in your script the correct way to call findContours when using OpenCV 3.x would be something like

(_, cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

UPDATE (Dec 2018)

In OpenCV 4.x, findContours returns 2 values only.

>>> help(cv2.findContours)
Help on built-in function findContours:

findContours(...)
    findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy
    .   @brief Finds contours in a binary image.
Dan Mašek
  • 17,852
  • 6
  • 57
  • 85
2

You can use cv2.findContours() irrespective of the version with following code snippet:

import cv2 as cv
version = cv.__version__
version = version[0]

if version == '4' or version == '2':
    contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
elif version == '3':
    im2, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

OpenCV 2.x and 4.x returns 2 variables, while 3.x return 3 variables

Dan Mašek
  • 17,852
  • 6
  • 57
  • 85
Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
  • I got `TypeError: unsupported operand type(s) for |: 'str' and 'str'` Added another `elif` instead. – Dave Jan 13 '23 at 01:26