轮廓
轮廓可以简单地解释为连接具有相同颜色或强度的所有连续点(沿边界)的曲线。轮廓是用于形状分析以及对象检测和识别的有用工具。
findContours()
findcontour()函数中有三个参数,第一个是源图像,第二个是轮廓检索模式,第三个是轮廓逼近方法。然后输出等高线和层次结构。轮廓是图像中所有轮廓的Python列表。每个单独的轮廓是一个(x,y)坐标的Numpy数组的边界点的对象。
轮廓检索模式:
代码 | 方法 |
---|---|
cv2.RETR_LIST | 检测的轮廓不建立等级关系 |
cv2.RETR_TREE | L建立一个等级树结构的轮廓。 |
cv2.RETR_CCOMP | 建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。 |
cv2.RETR_EXTERNAL | 表示只检测外轮廓 |
轮廓逼近方法:
代码 | 方法 |
---|---|
cv2.CHAIN_APPROX_NONE | 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1 |
cv2.CHAIN_APPROX_SIMPLE | 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息 |
cv2.CHAIN_APPROX_TC89_L1 | 使用teh-C轮廓逼近方法 |
CV_CHAIN_APPROX_TC89_KCOS | 使用teh-C轮廓逼近方法 |
drawContours()
cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])
第一个参数是指明在哪幅图像上绘制轮廓;
第二个参数是轮廓本身,在Python中是一个list。
第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。
第四个参数指定绘制出来的轮廓是什么颜色
第五个参数thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。
绘制轮廓代码例子:
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\gk.jpg')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cv.drawContours(img, contours, -1, (0,255,0), 3)
cv.namedWindow('a',cv.WINDOW_NORMAL)
cv.resizeWindow('a',640,480)
cv.imshow('a',img)
cv.waitKey(1000000)
cv.destroyAllWindows()
boundingRect()
函数可以获取轮廓的范围,即左上角原点,以及他的高和宽。
该函数的输入是找到的轮廓,输出是轮廓的左上角的(x,y)坐标,还有轮廓的宽还有高。后用cv2.rectangle()方法画出矩形轮廓。
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\gk.jpg')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
x, y, w, h = cv.boundingRect(contours[0])
cv.rectangle(img, (x,y), (x+w,y+h), (255,255,255), 5)
cv.namedWindow('a',cv.WINDOW_NORMAL)
cv.resizeWindow('a',640,480)
cv.imshow('a',img)
cv.waitKey(1000000)
cv.destroyAllWindows()
轮廓特征
输出轮廓特征矩代码
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\gk.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
contours,hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
M = cv.moments(cnt)
print( M )
'm00': 4.0, 'm10': 936.0, 'm01': 3442.0, 'm20': 219025.0, 'm11': 805428.0, 'm02': 2961842.6666666665, 'm30': 51252318.0, 'm21': 188471012.5, 'm12': 693071184.0, 'm03': 2548668483.0, 'mu20': 1.0, 'mu11': 0.0, 'mu02': 1.6666666665114462, 'mu30': 0.0, 'mu21': 0.0, 'mu12': 3.632158041000366e-08, 'mu03': 4.76837158203125e-07, 'nu20': 0.0625, 'nu11': 0.0, 'nu02': 0.10416666665696539, 'nu30': 0.0, 'nu21': 0.0, 'nu12': 1.1350493878126144e-09, 'nu03': 1.4901161193847656e-08}
轮廓面积
轮廓区域由函数cv.contourArea()或从特征矩M[‘m00’] 中给出
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\gk.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
contours,hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
area = cv.contourArea(cnt)
print( area )
轮廓周长
可以使用cv.arcLength()函数找到它。第二个参数指定形状是闭合轮廓( True )还是
曲线。
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\gk.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
contours,hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
perimeter = cv.arcLength(cnt,True)
print(perimeter)
轮廓近似
使用cv2.approxPolyDP()函数,根据我们指定的精度,它可以将轮廓形状近似为顶点数量较少的其他形状。他有三个参数,第一个参数是轮廓的点集,第二个参数epsilon它是从轮廓到近似轮廓的最大距离。它是一个精度参数,第三个参数指示新产生的轮廓是否闭合。返回的是一些列点组成的多边形。
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\xi.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cv.drawContours(img, contours, -1, (0,255,0), 3)
cnt=contours[0]
perimeter = cv.arcLength(cnt,True)
epsilon = 0.01*cv.arcLength(cnt,True)
approx = cv.approxPolyDP(cnt,epsilon,True)
cv.polylines(img, [approx], True, (255, 255, 255), 5)
cv.namedWindow('image',cv.WINDOW_NORMAL)
cv.resizeWindow('image',640,480)
cv.imshow('image',img)#轮廓图
cv.waitKey(0)
cv.destroyAllWindows()
轮廓凸包
使用cv.convexHull()函数
hull = cv.convexHull(points[, hull[, clockwise[, returnPoints]]
pints[]是传递的轮廓
hull是输出的凸包
clockwise方向标记。如果为True,则输出凸包为顺时针方向。否则,其方向为逆时针方向
返回值也是凸包
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\gk.jpg')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cnt=contours[6]
hull = cv.convexHull(cnt,clockwise=False)
cv.polylines(img, [hull], True, (255, 0, 255), 5)
cv.namedWindow('image',cv.WINDOW_NORMAL)
cv.resizeWindow('image',640,480)
cv.imshow('image',img)#轮廓图
cv.waitKey(0)
cv.destroyAllWindows()
检查凸度
cv.isContourConvex()具有检查曲线是否凸出的功能。它输入轮廓然后返回True或False。
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\gk.jpg')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cnt=contours[6]
flag=cv.isContourConvex(cnt)
print(flag)
轮廓的边界矩形
分为直角矩形和旋转矩形
直角矩形它是一个矩形,不考虑物体的旋转。所以边界矩形的面积不是最小的。它是由函数cv.boundingRect()找到的。函数cv.boundingRect()的介绍在上面
边界矩形是用最小面积绘制的,所以它也考虑了旋转。使用的函数是cv.minAreaRect()。它返回一个Box2D结构,其中包含以下细节 -(中心(x,y),(宽度,高度),旋转角度)。但要画出这个矩形,我们需要矩形的四个角。它由函数cv.boxPoints()获得
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shanw.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cnt=contours[2]
x,y,w,h = cv.boundingRect(cnt)
cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
rect = cv.minAreaRect(cnt)
box = cv.boxPoints(rect)
box = np.int0(box)
print(box)
cv.drawContours(img,[box],0,(0,0,255),2)
cv.namedWindow('image',cv.WINDOW_NORMAL)
cv.resizeWindow('image',640,480)
cv.imshow('image',img)#轮廓图
cv.waitKey(0)
cv.destroyAllWindows()
轮廓的最小闭合圆
使用函数cv.minEnclosingCircle(()查找对象的圆周。它是一个以最小面积完全覆盖物体的圆。该函数的输入是轮廓,输出是最小圆的圆心和半径。
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shanw.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cnt=contours[2]
(x,y),radius = cv.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
cv.circle(img,center,radius,(0,255,0),2)
cv.namedWindow('image',cv.WINDOW_NORMAL)
cv.resizeWindow('image',640,480)
cv.imshow('image',img)#轮廓图
cv.waitKey(0)
cv.destroyAllWindows()
轮廓的拟合椭圆
cv.fitEllipse()函数的输入是轮廓,输出是该轮廓的旋转椭圆
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shanw.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cnt=contours[2]
ellipse = cv.fitEllipse(cnt)
cv.ellipse(img,ellipse,(0,255,0),2)
cv.namedWindow('image',cv.WINDOW_NORMAL)
cv.resizeWindow('image',640,480)
cv.imshow('image',img)#轮廓图
cv.waitKey(0)
cv.destroyAllWindows()
轮廓的拟合直线
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shanw.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cnt=contours[2]
rows,cols = img.shape[:2]
[vx,vy,x,y] = cv.fitLine(cnt, cv.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
cv.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)
cv.namedWindow('image',cv.WINDOW_NORMAL)
cv.resizeWindow('image',640,480)
cv.imshow('image',img)#轮廓图
cv.waitKey(0)
cv.destroyAllWindows()
轮廓属性
长宽比
长宽比是对象边界矩形的宽度与高度的比值。
x,y,w,h = cv.boundingRect(cnt)
aspect_ratio = float(w)/h
范围
范围是轮廓区域与边界矩形区域的比值。
area = cv.contourArea(cnt) x,y,w,h = cv.boundingRect(cnt)
rect_area = w*h
extent = float(area)/rect_area
坚实度
坚实度是等高线面积与其凸包面积之比。
area = cv.contourArea(cnt)
hull = cv.convexHull(cnt)
hull_area = cv.contourArea(hull)
solidity = float(area)/hull_area
等效直径
等效直径是面积与轮廓面积相同的圆的直径
area = cv.contourArea(cnt)
equi_diameter = np.sqrt(4*area/np.pi)
取向
取向是物体指向的角度,利用了轮廓的拟合椭圆函数。(x,y)是椭圆的重心,Ma是长半轴,ma是短半轴,angle是旋转椭圆的旋转角度,即物体的指向。
(x,y),(MA,ma),angle = cv.fitEllipse(cnt)
掩码和像素点
构成该对象的所有点
这里提供了两个方法,一个使用Numpy函数,另一个使用OpenCV函数(最后的注释行)。结果也是一样的,只是略有不同。Numpy给出的坐标是 (行、列) 格式,而OpenCV给出的坐标是 (x,y) 格式。所以基本上答案是可以互换的。
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shanw.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh,cv.RETR_TREE ,
cv.CHAIN_APPROX_NONE )
cv.drawContours(img, contours, 2, (0,255,0), 3)
cnt=contours[2]
mask = np.zeros(imgray.shape,np.uint8)
cv.drawContours(mask,[cnt],0,255,-1)
pixelpoints = np.transpose(np.nonzero(mask))
#pixelpoints = cv.findNonZero(mask)
cv.polylines(img, [pixelpoints], True, (255, 255, 255), 5)
cv.namedWindow('a',cv.WINDOW_NORMAL)
cv.resizeWindow('a',640,480)
cv.imshow('a',img)
cv.waitKey(1000000)
cv.destroyAllWindows()
平均颜色或平均强度
我们可以找到对象的平均颜色。或者可以是灰度模式下物体的平均强度。
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shanw.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh,cv.RETR_TREE ,
cv.CHAIN_APPROX_NONE )
cv.drawContours(img, contours, 2, (0,255,0), 3)
cnt=contours[2]
mask = np.zeros(imgray.shape,np.uint8)
cv.drawContours(mask,[cnt],0,255,3)
pixelpoints = cv.findNonZero(mask)
mean_val = cv.mean(img,mask = mask)
极端点
极点是指对象的最顶部,最底部,最右侧和最左侧的点。
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shanw.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh,cv.RETR_TREE ,
cv.CHAIN_APPROX_NONE )
cv.drawContours(img, contours, 2, (0,255,0), 3)
cnt=contours[2]
mask = np.zeros(imgray.shape,np.uint8)
cv.drawContours(mask,[cnt],0,255,3)
pixelpoints = cv.findNonZero(mask)
leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])
rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])
cv.line(img,leftmost,leftmost,(255,0,0),5)
cv.line(img,rightmost,rightmost,(255,0,0),5)
cv.line(img,topmost,topmost,(255,0,0),5)
cv.line(img,bottommost,bottommost,(255,0,0),5)
凸性缺陷
这里需要用到convexityDefects函数
convexityDefects(InputArray contour, InputArray convexhull, OutputArrayconvexityDefects)
coutour: 输入参数,检测到的轮廓
convexhull: 输入参数,检测到的凸包,可以调用convexHull函数得到。注意,convexHull函数可以得到vector<vector>和vector<vector>两种类型结果,这里的convexhull应该为vector<vector>类型,否则通不过ASSERT检查
convexityDefects:输出应为vector<vector>类型,Vec4i存储了起始点(startPoint),结束点(endPoint),距离convexity hull的最远点(farPoint)以及最远点到convexity hull的距离(depth)
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shanw.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh,cv.RETR_TREE ,
cv.CHAIN_APPROX_NONE )
cv.drawContours(img, contours, 2, (0,255,0), 3)
cnt=contours[2]
hull = cv.convexHull(cnt,returnPoints = False)
defects = cv.convexityDefects(cnt,hull)
for i in range(defects.shape[0]):
s,e,f,d = defects[i,0]
start = tuple(cnt[s][0])
end = tuple(cnt[e][0])
far = tuple(cnt[f][0])
cv.line(img,start,end,[0,255,0],2)
cv.circle(img,far,5,[0,0,255],-1)
cv.namedWindow('a',cv.WINDOW_NORMAL)
cv.resizeWindow('a',640,480)
cv.imshow('a',img)
cv.waitKey(1000000)
cv.destroyAllWindows()
点多边形测试
该函数可以找出图像中一点到轮廓线的最短距离。它返回的距离,点在轮廓线外时为负,点在轮廓线内时为正,点在轮廓线上时为零。
dist = cv.pointPolygonTest(cnt,(50,50),True)
第一个参数是轮廓
第二个参数是该点
第三个参数是measureDist。如果它是真的,它会找到有符号的距离。如果为假,则查找该点是在轮廓线内部还是外部(分别返回+1、-1和0)。如果您不想找到距离,请确保第三个参数为False,因为这是一个耗时的过程。因此,将其设置为False可使速度提高2-3倍。
形状匹配
OpenCV附带一个函数cv.matchShapes(),该函数使我们能够比较两个形状或两个轮廓,并返回一个显示相似性的度量。结果越低,匹配越好。
double cvMatchShapes(const void* object1, const void* object2, int method, double parameter = 0);
第一个参数是待匹配的物体1,第二个是待匹配的物体2
第三个参数method有三种输入:CV_CONTOURS_MATCH_I1、CV_CONTOURS_MATCH_I2、CV_CONTOURS_MATCH_I3
返回值是一个double类型的数字
import cv2 as cv
import numpy as np
img1 = cv.imread('star.jpg',0)
img2 = cv.imread('star2.jpg',0)
ret, thresh = cv.threshold(img1, 127, 255,0)
ret, thresh2 = cv.threshold(img2, 127, 255,0)
contours,hierarchy = cv.findContours(thresh,2,1)
cnt1 = contours[0]
contours,hierarchy = cv.findContours(thresh2,2,1)
cnt2 = contours[0]
ret = cv.matchShapes(cnt1,cnt2,1,0.0)
print( ret )
练习
检查文档中的cv.pointPolygonTest(),您可以找到红色和蓝色的漂亮图像。它表示从所有像素到白色曲线的距离。曲线内的所有像素都是蓝色的,这取决于距离。外面的点也是红色的。轮廓边缘用白色标记。所以问题很简单。编写一个代码来创建这样的距离表示。
import numpy as np
import cv2 as cv
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shanw.png')
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cnt=contours[2]
rows,cols,channel = img.shape
for i in range(0,rows-1):
for j in range(0,cols-1):
flag = cv.pointPolygonTest(cnt,(i,j),False)
if flag==1:
img[i][j]=(0,0,255)
elif flag==0:
img[i][j]=(255,255,255)
elif flag==-1:
img[i][j]=(255,0,0)
cv.namedWindow('image',cv.WINDOW_NORMAL)
cv.resizeWindow('image',640,480)
cv.imshow('image',img)#轮廓图
cv.waitKey(0)
cv.destroyAllWindows()
使用cv.matchShapes()比较数字或字母的图像。
import cv2 as cv
import numpy as np
def cha(img,cnts=[]):
ret, thresh = cv.threshold(img, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cnt=contours[1]
min=100
for i in range(0,10):
ret = cv.matchShapes(cnt, cnts[i], 1, 0.0)
print(i,'对应的相似度是',ret)
if ret<min:
min=ret
flag=i
if min==100:
return False
else:
return flag
img = cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\shu.jpg',0)
shi=cv.imread('C:\\Users\\Administrator\\Desktop\\pic\\4d.png',0)
ret, thresh = cv.threshold(img, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,
cv.CHAIN_APPROX_SIMPLE)
cv.drawContours(img, contours, 15, (255,0,0), 3)
cnt9=contours[1]#9
cnt8=contours[3]#8
cnt7=contours[6]#7
cnt6=contours[7]#6
cnt5=contours[9]#5
cnt4=contours[10]#4
cnt3=contours[12]#6
cnt2=contours[13]#5
cnt1=contours[14]#4
cnt0=contours[15]#0
cnts=list([cnt0,cnt1,cnt2,cnt3,cnt4,cnt5,cnt6,cnt7,cnt8,cnt9])
flag=cha(shi,cnts)
print('这是个',flag)
cv.destroyAllWindows()
轮廓分层
每个轮廓都有它自己的信息关于它是什么层次,谁是它的孩子,谁是它的父母等。
[Next, Previous, First_Child, Parent]
轮廓检索模式
RETR_LIST
它只是检索所有的轮廓,但不创建任何亲子关系。在这个规则下,父轮廓和子轮廓是平等的,他们只是轮廓。他们都属于同一层级。第3和第4项总是-1。
RETR_EXTERNAL
该模式只检索最外部轮廓,其余所有子轮廓都被遗弃。因此也就同样不存在亲子关系。第3和第4项总是-1。
RETR_CCOMP
该模式会检索所有轮廓,并且将所有轮廓分为2级层次结构。物体的外部轮廓(它的边界)被设置为第1级层级结构,物体内部空洞轮廓被设置为第2级层级结构。如果空洞中也有物体存在,那么它的轮廓就被设置为第1级层级结构,而它的内部空洞则被设置为第2级层级结构。
序号 | next | previous | first-child | parents |
---|---|---|---|---|
0 | 3 | -1 | 1 | -1 |
1 | 2 | -1 | -1 | 0 |
2 | -1 | 1 | -1 | 0 |
3 | 5 | 0 | 4 | -1 |
4 | -1 | -1 | -1 | 3 |
5 | 7 | 3 | 6 | -1 |
6 | -1 | -1 | -1 | 5 |
7 | 8 | 5 | -1 | -1 |
8 | -1 | 7 | - 1 | -1 |
RETR_TREE
该模式会检索所有轮廓,并且创建完整的层次结构。
图中的轮廓5和轮廓6是一个层次的
序号 | next | previous | first-child | parents |
---|---|---|---|---|
0 | 7 | -1 | 1 | -1 |
1 | -1 | -1 | 2 | 0 |
2 | -1 | -1 | 3 | 1 |
3 | -1 | -1 | 4 | 2 |
4 | -1 | -1 | 5 | 3 |
5 | 6 | -1 | -1 | 4 |
6 | -1 | 5 | -1 | 4 |
7 | 8 | 0 | -1 | -1 |
8 | -1 | 7 | -1 | -1 |