How to use `cv2.findContours` in different OpenCV versions?

15,483

An alternative to work with 2.x 、3.x、4.x is:

cnts, hiers = cv2.findContours(...)[-2:]

Notice:

cv2.findContours has changed since OpenCV 3.x, but in OpenCV 4.0 it changes back!!!

In OpenCV 3.4:

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

enter image description here

In OpenCV 4.0:

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

enter image description here

Share:
15,483
DSmith
Author by

DSmith

Updated on June 17, 2022

Comments

  • DSmith
    DSmith about 2 years

    I am trying to use OpenCV with Python in order to detect squares in a live video feed from a Raspberry Pi camera. However, the cv2.GaussianBlur and cv2.Canny functions in the code below are causing the following error: "TypeError: numpy.ndarray' object is not callable".

    I cannot seem to resolve the error. Any help is appreciated.

    Code taken from https://www.pyimagesearch.com/2015/05/04/target-acquired-finding-targets-in-drone-and-quadcopter-video-streams-using-python-and-opencv/#comment-446639

    import cv2
    
    # load the video
    camera = cv2.VideoCapture(0)
    
    # keep looping
    while True:
      # grab the current frame and initialize the status text
      (grabbed, frame) = camera.read()
      status = "No Targets"
    
      # check to see if we have reached the end of the
      # video
      if not grabbed:
         break
    
      # convert the frame to grayscale, blur it, and detect edges
      gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
      blurred = cv2.GaussianBlur(gray, (7, 7), 0)
      edged = cv2.Canny(blurred, 50, 150)
    
      # find contours in the edge map
      (cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
         cv2.CHAIN_APPROX_SIMPLE)
    
      # loop over the contours
      for c in cnts:
        # approximate the contour
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.01 * peri, True)
    
        # ensure that the approximated contour is "roughly" rectangular
        if len(approx) >= 4 and len(approx) <= 6:
            # compute the bounding box of the approximated contour and
            # use the bounding box to compute the aspect ratio
            (x, y, w, h) = cv2.boundingRect(approx)
            aspectRatio = w / float(h)
    
            # compute the solidity of the original contour
            area = cv2.contourArea(c)
            hullArea = cv2.contourArea(cv2.convexHull(c))
            solidity = area / float(hullArea)
    
            # compute whether or not the width and height, solidity, and
            # aspect ratio of the contour falls within appropriate bounds
            keepDims = w > 25 and h > 25
            keepSolidity = solidity > 0.9
            keepAspectRatio = aspectRatio >= 0.8 and aspectRatio <= 1.2
    
            # ensure that the contour passes all our tests
            if keepDims and keepSolidity and keepAspectRatio:
                # draw an outline around the target and update the status
                # text
                cv2.drawContours(frame, [approx], -1, (0, 0, 255), 4)
                status = "Target(s) Acquired"
    
            # draw the status text on the frame
        cv2.putText(frame, status, (20, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
        (0, 0, 255), 2)
    
      # show the frame and record if a key is pressed
      cv2.imshow("Frame", frame)
      key = cv2.waitKey(1) & 0xFF
    
      # if the 'q' key is pressed, stop the loop
      if key == ord("q"):
         break
    
    # cleanup the camera and close any open windows
    camera.release()
    cv2.destroyAllWindows()