opencv找轮廓findContours版本问题

713 阅读1分钟

使用opencv的找轮廓函数时,可能会因为opencv的版本不一样,程序会有一些不兼容。opencv3 与opencv2 opencv4 版本的findContours函数返回值不一样,如下所示:

# image,contours,hierarchy = cv2.findContours(thresh, 1, 2)  # opencv3
# contours,hierarchy = cv2.findContours(thresh, 1, 2)  # opencv2  opencv4

在使用时需要判断opencv的版本,进行调用。 开源包imutil提供了版本判断的函数以及调用的封装包。 源码 github.com/PyImageSear…

版本判断可以使用imutils中的is_cv2、is_cv3、is_cv4
imutils.grab_contours可返回cnts中的countors(轮廓),不区分opencv2或opencv3
获取oencv版本
'''
def get_opencv_major_version(lib=None):
    # if the supplied library is None, import OpenCV
    if lib is None:
        import cv2 as lib

    # return the major version number
    return int(lib.__version__.split(".")[0])
major = get_opencv_major_version()
print('opencv version ',major)


def grab_contours(cnts):
    # if the length the contours tuple returned by cv2.findContours
    # is '2' then we are using either OpenCV v2.4, v4-beta, or
    # v4-official
    if len(cnts) == 2:
        cnts = cnts[0]

    # if the length of the contours tuple is '3' then we are using
    # either OpenCV v3, v4-pre, or v4-alpha
    elif len(cnts) == 3:
        cnts = cnts[1]

    # otherwise OpenCV has changed their cv2.findContours return
    # signature yet again and I have no idea WTH is going on
    else:
        raise Exception(("Contours tuple must have length 2 or 3, "
            "otherwise OpenCV changed their cv2.findContours return "
            "signature yet again. Refer to OpenCV's documentation "
            "in that case"))

    # return the actual contours array
    return cnts

def is_cv3(or_better=False):
    # grab the OpenCV major version number
    major = get_opencv_major_version()

    # check to see if we are using *at least* OpenCV 3
    if or_better:
        return major >= 3

    # otherwise we want to check for *strictly* OpenCV 3
    return major == 3



img = cv2.imread('test.png',0)
ret,thresh = cv2.threshold(img,127,255,0)
# image,contours,hierarchy = cv2.findContours(thresh, 1, 2)  # opencv3
# contours,hierarchy = cv2.findContours(thresh, 1, 2)  # opencv2  opencv4
contours  = cv2.findContours(thresh, 1, 2)   
# 轮廓周长用cv2.arcLength()函数得到。第二个参数指定形状是否是闭合的轮廓(如果传True)
cnts = imutils.grab_contours(contours)
for contour in cnts :
    perimeter = cv2.arcLength(contour, True)
    print('perimeter ',perimeter)
    break

思考: 遇到版本不一致问题,可以从源头查阅一些函数的定义变化,并通过封装一个通用函数来解决这种变化的问题。