目录
定义
轮廓与边缘不同,主要区别在于轮廓是连续的一个整体,边缘是可以离散的线段。
函数方法
cv2.findContours(img,mode,method)
- mode:轮廓检索模式
RETR_EXTERNAL:只检索最外围的轮廓
RWTR_LIST:检索所有轮廓,并将其存到一条链表中
RETR_CCOMP:检索所有的轮廓,并将它们组织为两层,顶层为各部分的外部边界,第二层是空洞的边界
RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次(常用,遇事不决就用这个)
- method:轮廓逼近方法
CHAIN_APPROX_NONE:以freeman链码的方式输出轮廓,所有其他方法输出多边形
CHAIN_APPROX_SIMPLE:压缩水平的垂直的和斜的部分,也就是函数只保留他们的终点部分。
cv2.drawContours(img,contours,contoursInlineColor,lineSize)
- contours:轮廓信息
- contoursIndex:轮廓索引,-1表示全部轮廓
- lineColor:线条颜色(BGR)
- lineSize:线条粗细
案例
代码解析
为了提高准确率 采取二值图像
我用的是OTSU来获取最佳阈值,也可以通过Tangle来获取最佳阈值
只用Binary也是可以的 阈值取为min=127,max=255
注意在此处如果直接执行cv2.IMREAD_GRAYSCALE那么在最后的drawContours的线条颜色不会显示
lena = cv2.imread('Picture/Lena.png')
lena_Gray = cv2.cvtColor(lena,cv2.COLOR_BGR2GRAY)
ret,lena_otsu = cv2.threshold(lena_Gray,0,255,cv2.THRESH_OTSU+cv2.THRESH_BINARY)
使用findcontours来获取轮廓
contours,hierarchy = cv2.findContours(lena_otsu,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
返回的两个参数 contours是边界的信息可以用np.array来转换出来看,hierarchy则是层级信息。
接下来通过drawcontours绘制轮廓
但drawContours是绘制在img上,所以需要先对img创建一个副本
drawlena = lena.copy()
res = cv2.drawContours(drawlena,contours,-1,color=(255,0,0),thickness=2)
cv2.imshow('Contours',res)
cv2.waitKey(0)
cv2.destroyAllWindows()
轮廓特征
案例
代码解析
cnt=contours[3]
如图所取的就是第四个轮廓
#求面积
print(cv2.contourArea(cnt))
#求周长 True表示闭合的
print(cv2.arcLength(cnt,True))
轮廓近似(逼近)
定义
将不规则的轮廓,近似为一个规则的轮廓
案例
#轮廓近似
#epsilon的系数越小离原轮廓就越接近
drawlena1 = lena.copy()
epsilon = 0.1 * cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
drawapprox = cv2.drawContours(drawlena1,[approx],-1,(0,0,255),3)
cv2.imshow('drawApprox',drawapprox)
cv2.waitKey(0)
cv2.destroyAllWindows()
轮廓应用
边界矩阵
案例
x,y,w,h = cv2.boundingRect(cnt)
tangle = cv2.rectangle(drawlena,(x,y),(x+w,y+h),(0,255,0),3)
还有一些别的应用 比如外接圆啊,抠图啊
感兴趣的可以看OpenCV 中的轮廓应用 - 知乎 (zhihu.com)
此处主要是入门教程