Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV version 4.1.0 drawContours

I have the following code that worked well with OpenCV 3.4.1 and now is not working with OpenCV 4.1.0 and gives an error. I do not know how to adapt the code with the newer version, can you help me with that? Thanks a lot

def ImageProcessing(image):
    image = cv2.absdiff(image, background)
    h, gray = cv2.threshold(image, 65, 255, cv2.THRESH_BINARY_INV);
    gray = cv2.medianBlur(gray,5)

    kernel = np.ones((3,3), np.uint8)

    gray = cv2.erode(gray, kernel, iterations=1)#1

    des = cv2.bitwise_not(gray)
    tmp = cv2.findContours(des,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
    contour, hier = tmp[1], tmp[0]

    for cnt in contour:
        cv2.drawContours(des,[cnt],0,255,-1)

    gray = cv2.bitwise_not(des)

    gray = cv2.dilate(gray, kernel, iterations=1)#1

    return gray

The error is

cv2.error: OpenCV(4.1.0) /io/opencv/modules/imgproc/src/drawing.cpp:2509: error: (-215:Assertion failed) npoints > 0 in function 'drawContours'

like image 557
user8224662 Avatar asked Jan 26 '23 09:01

user8224662


2 Answers

Depending on the OpenCV version, cv2.findContours() has varying return signatures.

In OpenCV 3.4.X, cv2.findContours() returns 3 items

image, contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])

In OpenCV 4.1.X, cv2.findContours() returns 2 items

contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])

You can easily obtain the contours regardless of the version like this:

cnts = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

Since the last two values are always the same, we can further condense it into a single line using [-2:] to extract the contours from the tuple returned by cv2.findContours()

cnts, _ = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2:]
like image 54
nathancy Avatar answered Jan 28 '23 23:01

nathancy


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.

First, get the version of OpenCV installed (we don't want the entire version just the major number either 3 or 4) :

import cv2
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 version == str(4):
    contours, hierarchy = cv2.findContours(binary_img, cv2.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

elif version == str(3):
    im, contours, hierarchy = cv2.findContours(binary_img, cv2.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

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

Note: the above snippet is written assuming either version 3 or 4 of OpenCV is installed. For older versions, please refer to the documentation or update to the latest.

like image 29
Jeru Luke Avatar answered Jan 29 '23 00:01

Jeru Luke