如何在不同版本的OpenCV中使用`cv2.findContours`?

6
我想使用Python中的OpenCV来检测树莓派相机的实时视频中的正方形。 然而,下面代码中的cv2.GaussianBlurcv2.Canny函数会导致以下错误:"TypeError:numpy.ndarray' object is not callable"
我无法解决这个错误。 希望能得到任何帮助。
代码取自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()
3个回答

21

与 2.x、3.x、4.x 一起使用的替代方案是:

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

注意:

cv2.findContoursOpenCV 3.x 版本中有所改变,但在 OpenCV 4.0 中又改回来了!

在 OpenCV 3.4 中:

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

enter image description here

在OpenCV 4.0中:

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

在此输入图片描述


0

这里有另一种方法可以存储从cv2.findContours()返回的所有元组,而不管您的系统/环境中安装的OpenCV版本:

首先,获取已安装的OpenCV版本(我们不需要整个版本,只需要主要数字3或4):

import cv2
major_number = cv2.__version__[0]

根据版本,将执行以下两个语句之一,并填充相应的变量:
if major_number == '4':
    contours, hierarchy = cv2.findContours(img_binary, cv2.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

elif major_number == '3':
    img, contours, hierarchy = cv2.findContours(img_binary, cv2.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

函数返回的轮廓将在任一情况下存储在contours中。 3.X.X 版本: 文档 4.X.X 版本: 文档

0

这里有一个自动化的方法,我是从 @nathancy 那里学到的。if 三元运算符测试确定有多少返回值,并选择适当的值用于轮廓。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接