1.通过OpenCV的findContours可以很方便的找到图片中内容的轮廓。
2.为了提取轮廓有更高的准确率,在提取轮廓前,需要对图片进行预处理(二值+阈值),只保留感兴趣的图像。
3.通过计算轮廓面积与外接矩形或外接圆的面积,可以找到轮廓特征,进一步筛选出感兴趣的轮廓。
语法:cv2.findContours(img,mode,method)
mode:轮廓检索模式
RETR_EXTERNAL:只检最外面的轮廊
RETR_LIST:检索所有的轮廊,并将其保存到一条链表当中
RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部份的外部边界,第二层是空洞的边界
RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次(常用这个)
method:轮廓逼近方法
CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部,也就是,函数只保留他们的终点部分。
为了更高的准确率,使用二值图像
示例代码
import cv2
import math
import numpy as np
#图像轮廓
#语法:cv2.findContours(img,mode,method)
# mode:轮廓检索模式
#RETR_EXTERNAL:只检最外面的轮廊
#RETR_LIST:检索所有的轮廊,并将其保存到一条链表当中
#RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部份的外部边界,第二层是空洞的边界
#RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次
# method:轮廓逼近方法
#CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
#CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部,也就是,函数只保留他们的终点部分。
#为了更高的准确率,使用二值图像
def cv_show(name, img):
cv2.imshow(name, img) # 显示图像
cv2.waitKey(0) # 等待时间,单位毫秒,0表示任意键终止
cv2.destroyAllWindows()
#1.读取图像
image = cv2.imread("C:\\Users\\zhangqs\\Desktop\\cv.png")
#2.预处理
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) #灰度图
ret,threshold=cv2.threshold(gray,160,255,cv2.THRESH_BINARY) #阈值处理
#3.查找轮廓
contours,hierarchy=cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
print('共找到',len(contours),'个轮廓')
#4.绘制轮廓
#在原图上绘制轮廓
draw2=image.copy() #注意:需要copy一下,否则将会改动原图
drawed2=cv2.drawContours(draw2,contours,-1,(0,0,255),2) #图像,轮廓,轮廓索引,颜色模式,线条厚度
cv_show('draw_contours',draw2)
#在灰度图上绘制轮廓(下面的np.hstack函数要求数组维度一致,才能比较显示)
draw=gray.copy() #注意:需要copy一下,否则将会改动原图
drawed=cv2.drawContours(draw,contours,-1,(0,0,255),2) #图像,轮廓,轮廓索引,颜色模式,线条厚度
#5.轮廓近似
#外接矩形(绿色线)
cnt=contours[12]
# epsilon=0.1*cv2.arcLength(cnt,True)
# approx=cv2.approxPolyDP(cnt,epsilon,True)
x,y,w,h=cv2.boundingRect(cnt)
imgRectangle=cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
cv_show('Rectangle',imgRectangle)
area=cv2.contourArea(cnt) #轮廓面积
rectArea=w*h #外接矩形面积
rate=float(area)/rectArea
print('轮廓面积/外接矩形面积比:',rate)
#外接圆(蓝色线)
cnt2=contours[11]
(x,y),radius=cv2.minEnclosingCircle(cnt2)
center=(int(x),int(y))
radius=int(radius)
imgCircle=cv2.circle(image,center,radius,(255,0,0),2)
cv_show('Circle',imgCircle)
areaCircle=cv2.contourArea(cnt) #轮廓面积
rectArea=math.pi*radius*radius #外接圆面积
rateCircle=float(areaCircle)/areaCircle
print('轮廓面积/外接圆面积比:',rateCircle)
# #合并显示
# res=np.hstack((gray,threshold,drawed)) #注意:两层括号
# cv2.imshow('all',res)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
运行结果
原图
轮廓图
外接矩形(绿色线条)
外接圆(蓝色线条)
遍历轮廓,通过计算面积比,就可以找到轮廓特征,也就筛选出我们感兴趣的轮廓了。