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