提示:本专栏所用版本仅供参考,其他版本也可
库 | 版本 |
---|---|
python | Python 3.9.3 |
opencv | 4.5.5 |
matplotlib | 3.4.3 |
numpy | 1.19.5 |
QQ学习群 | 点击加群:928357277 |
- 提问环节
- 1:什么是图像轮廓
- 2:图像轮廓和边缘检测的区别
- 3:如何进行图像检测
- 查找轮廓
- 参数mode表
- 参数method表
- 代码演示
- 轮廓绘制
- 代码演示
- 轮廓矩特征
- 使用零阶矩计算轮廓面积
- 使用函数计算轮廓周长面积
- Hu矩:
- 基于Hu矩的形状匹配
- 图表:比较方法参数
- 计算俩个图像不同的匹配度
- 轮廓拟合
- 绘制矩形包围框
- 绘制最小包围矩形框
- 绘制最小包围圆形
- 绘制最优拟合圆
- 绘制最优拟合直线
- 图表:距离类型参数![在这里插入图片描述](http://www.kaotop.com/file/tupian/20220506/01f5fda63868449b830fb4224a90ed6f.png#pic_center)
- 绘制最小外包三角形
- 绘制逼近多边形
答:是图像中非常重要个一个特征信息,通过对图像的检测,我们能够获得图像的大小,位置,方向等。
2:图像轮廓和边缘检测的区别答:图像轮廓可以检测到完整的,连续的边缘信息,同时还能获得图像的各种特征信息,如大小,位置,方向等
3:如何进行图像检测答:为了检测完整的,连续的边缘信息,openCv提供了findContours()轮廓查找函数,和drawContours()轮廓绘制函数
查找轮廓c,h = cv2.findContours(image,mode,method)
注意:在opencv4之前该函数有三个返回值:image,c,h
返回值为轮廓信息c,和图像的拓扑信息h
参数Mode为轮廓的检索模式
参数method为轮廓的近似方法
参数 | 说明 |
---|---|
cv2.RETR_LIST | 检测到的轮廓不建立等级关系 |
cv2.RETR_EXTERNA | 检测所有外轮廓 |
cv2.RETR_CCOMP | 检索素有轮廓并组织为两级层次结构 |
cv2.RETR_TAEE | 建立等级数结构的轮廓 |
参数 | 说明 |
---|---|
cv2.CHAIN_APPROX_NONE | 存储所有轮廓点,两点位置差不超过1 |
cv2.CHAIN_APPROX_SIMPLE | 只保留该方向的终点坐标 |
cv2.CHAIN_APPROX_TC89_L1 | ten_chinl chain近似算法风格 |
cv2.CHAIN_APPROX_TC89_KCOS | ten_chinl chain近似算法风格 |
import matplotlib.pyplot as plt #导入模块
import cv2
import numpy as np
轮廓获取
img = cv2.imread('1.jpg',0)
#对图像进行二值化处理
r,img = cv2.threshold(img,180,255,cv2.THRESH_BINARY)
# print(data.shape)
#返回轮廓信息,拓扑信息,检测轮廓的模式为只检测外轮廓,方式为存储所有的轮廓蒂娜
c,h = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
a = len(c)
print(a)#打印轮廓数量
print(c[a-1].shape)#打印最后一个轮廓的信息
for X in range(a):#打印每个轮廓的拓扑信息
"""Next , Previous , First_Child , Parent"""
print(X,":",h[X])
运行结果:
07\exercise> python .\opencv3.py
轮廓数量 1
(2300, 1, 2)
0 : [[-1 -1 -1 -1]]
第一行为轮廓数量,第二行为当前轮廓信息,第三行为当前的轮廓拓扑信息
轮廓绘制image = cv2.drawContours(image,contours,contourIdx,color[,thickness[,lineType[,hierachy[,maxlevel[,offset]]]]])
参数依次为:原始图像,轮廓信息,边缘索引,绘制颜色,画笔粗细,线形,层次信息,轮廓深度,偏移位置
参数依次为:原始图像,轮廓信息,边缘索引,绘制颜色,画笔粗细,线形,层次信息,轮廓深度,偏移位置
代码演示import matplotlib.pyplot as plt #导入模块
import cv2
import numpy as np
img = cv2.imread('1.jpg',0)
#对图像进行二值化处理
r,img = cv2.threshold(img,180,255,cv2.THRESH_BINARY_INV)
# print(data.shape)
#返回轮廓信息,拓扑信息,检测轮廓的模式为只检测外轮廓,方式为存储所有的轮廓蒂娜
c,h = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
image = cv2.drawContours(img,c,-1,(255,255,255),-1)#绘制实心轮廓,提取前景色
cv2.imshow('img',image)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
轮廓矩特征:moments()
语法格式:cv2.moments(array[,binaryImage])
参数为:点集array,图像二值化处理标志
返回值为轮廓矩:
轮廓矩包括:
1、空间矩(零阶矩(m00),一阶矩(m10,m01),二阶矩(m20,m11,m02),三阶矩)
2、中心矩(二阶中心矩(mu20,mu11,mu02),三阶中心矩)
3、归一化中心矩(二阶Hu矩(nu20,nu11,nu02),三阶Hu矩)
各矩阵都有自己独特的用法,比如说m00矩可以用来比较面积大小,归一化中心矩可以描述平移,缩放不变性。
import matplotlib.pyplot as plt #导入模块
import cv2
import numpy as np
img = cv2.imread('1.jpg',0)
#对图像进行二值化处理
r,img = cv2.threshold(img,180,255,cv2.THRESH_BINARY_INV)
# print(data.shape)
#返回轮廓信息,拓扑信息,检测轮廓的模式为只检测外轮廓,方式为存储所有的轮廓蒂娜
c,h = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
#计算轮廓的面积
a = len(c)
for X in range(a):
print(X,"的面积:%d" %cv2.moments(c[X])['m00'])
image = cv2.drawContours(img,c,-1,(255,255,255),-1)#绘制实心轮廓,提取前景色
cv2.imshow('img',image)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
0 的面积:1914
1 的面积:2455
2 的面积:3662
3 的面积:2882
4 的面积:3104
5 的面积:6100
6 的面积:23765
7 的面积:23287
8 的面积:9
9 的面积:23680
使用函数计算轮廓周长面积
当然,我们还可以通过openCv提供的其他函数来进行面积计算
计算面积:retval = cv2.contourAera(contour[,oriented])
计算长度:retcal = cv2.arcLength(contour,colsed)
Hu矩:
HU矩是归一化中心矩的线性组合。Hu矩阵在图像旋转,缩放,平移等 *** 作后,仍能保持矩阵的不变特性,经常被用来识别图像的特征
在OpenCV中使用HuMomente()得到Hu矩,返回值为monments()函数的返回值作为参数,返回7个Hu矩值
== hu = cv2.HuMoments(m) ==
关于得到7个矩值的计算方式,有想了解的可以自行百度
函数支持:cv2.matchShapes(contour1,contour2,method,parameter)
参数为:第一个轮廓或者灰度图像,第二个轮廓或者灰度图像,比较方法,扩展参数(扩展参数仅支持opencv4.1.0及之后版本)
img1 = cv2.imread('1.jpg',cv2.IMREAD_GRAYSCALE)
#二值化处理
rt,img1 = cv2.threshold(img1,150,255,cv2.THRESH_BINARY)
#做出第二章图片
img2 = img1
c1,h2 = cv2.findContours(img1,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
c2,h2 = cv2.findContours(img2,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
c11 = c1[0]
c22 = c2[0]
#形状匹配
r1 = cv2.matchShapes(c11,c22,cv2.CONTOURS_MATCH_I1,0.0)
print("形状匹配度 ", r1)
运行结果:
形状匹配度 0.0
轮廓拟合
为了方便计算得到一个接近于轮廓的多边形,我们需要对轮廓进行轮廓拟合 *** 作
绘制矩形包围框函数:retval = cv2.boundingRect(array)
返回值为边界左上角顶点的坐标值及矩形边界的宽度和高度,参数为灰度图像或者轮廓
还可以写作四个返回值的形式:x,y,w,h = cv2.boundingRect
代码:
import matplotlib.pyplot as plt #导入模块
import cv2
import numpy as np
img = cv2.imread('1.jpg')
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
r,imgGray = cv2.threshold(imgGray,180,255,cv2.THRESH_BINARY_INV)
c,h = cv2.findContours(imgGray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
#构造矩形边框
print(len(c))
x,y,w,h = cv2.boundingRect(c[10])
#矩形边框点集
rect = np.array([[[x,y]],[[x+w,y]],[[x+w,y+h]],[[x,y+h]]])
#绘制
# cv2.rectangle(imgGray,(x,y),(x+w,y+h),(255,255,255),2)
cv2.drawContours(imgGray,[rect],-1,(255,255,255),2)
cv2.imshow('imgGray',imgGray)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
绘制最小包围矩形框retval = minAreaRect(points)
返回值为矩形特征信息(最小外接矩形的中心,(宽度,高度),旋转角度)
参数为轮廓
代码:
import matplotlib.pyplot as plt #导入模块
import cv2
import numpy as np
img = cv2.imread('1.jpg')
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
r,imgGray = cv2.threshold(imgGray,180,255,cv2.THRESH_BINARY_INV)
c,h = cv2.findContours(imgGray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
#构造矩形边框
print(len(c))
#矩形边框点集
rect = cv2.minAreaRect(c[10])
points = cv2.boxPoints(rect)#返回值转换函数
points = np.int0(points)# 结果取整数
#绘制
# cv2.rectangle(imgGray,(x,y),(x+w,y+h),(255,255,255),2)
cv2.drawContours(imgGray,[points],-1,(255,255,255),2)
cv2.imshow('imgGray',imgGray)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
center,radius = cv2.minEnclosingCircle(points)
返回值为圆形中心,圆形半径
retval = cv2.fitEllipse(points)
返回值为RotateRect类型的值,包含外接矩形的质心、宽、高、旋转角度等参数信息,对应椭圆的中心点,轴长度,旋转角度
参数为轮廓信息
使用代码:
#使用下面代码代码替换绘制部分即可
ellipse = cv2.fitEllipse(c[10])
cv2.ellipse(img,ellipse,(1,255,1),3)
绘制最优拟合直线
line = cv2.fitLine(points,disType,param,reps,aeps)
返回值为最优拟合直线参数
参数为轮廓,距离类型,距离参数,用于拟合直线所需要的的径向精度【0.01】,用于拟合直线所需要的的角度精度【0.01】
使用代码:
import matplotlib.pyplot as plt #导入模块
import cv2
import numpy as np
img = cv2.imread('1.jpg')
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
r,imgGray = cv2.threshold(imgGray,180,255,cv2.THRESH_BINARY_INV)
c,h = cv2.findContours(imgGray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
#构造矩形边框
print(len(c))
#矩形边框点集
rows,cols = imgGray.shape[:2]
[vx,vy,x,y] = cv2.fitLine(c[10],cv2.DIST_L2,0,0.01,0.01)
#计算左右距离
lefty = int((-x*vy/vx)+y)
righty = int(((cols-x)*vy/vx)+y)
#绘制直线
cv2.line(imgGray,(cols-1,righty),(0,lefty),(0,255,0),2)
cv2.imshow('imgGray',imgGray)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
retval,triangle = minEnclosingTriangle(points)
返回值为:最小外包三角形的面积retval、最小外包三角形的三个顶点集triangle
参数为轮廓信息
使用代码:
import matplotlib.pyplot as plt #导入模块
import cv2
import numpy as np
img = cv2.imread('1.jpg')
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
r,imgGray = cv2.threshold(imgGray,180,255,cv2.THRESH_BINARY_INV)
c,h = cv2.findContours(imgGray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
#构造矩形边框
print(len(c))
#获取三角形信息,最小外包面积和三个顶点集
area,trgl = cv2.minEnclosingTriangle(c[10])
#绘制三角形
for i in range(3):
cv2.line(imgGray,tuple([int(trgl[i][0][0]),int(trgl[i][0][1])]),
tuple([int(trgl[(i + 1 )% 3][0][0]),int(trgl[(i + 1 )% 3][0][1])]),(255,255,255),2)
#显示图片
cv2.imshow('imgGray',imgGray)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
approxCurve = cv2.approxPolyDp(curve,epsilon,colsed)
返回值为逼近多边形的点集
参数为:轮廓curve、精度epsilon[原始轮廓的边界点与逼近多边形边界之间的最大距离]、是否封闭标志colsed
使用代码:
import matplotlib.pyplot as plt #导入模块
import cv2
import numpy as np
img = cv2.imread('1.jpg')
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
r,imgGray = cv2.threshold(imgGray,180,255,cv2.THRESH_BINARY_INV)
c,h = cv2.findContours(imgGray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
#构造矩形边框
print(len(c))
# 设置epsilon = 0.1为周长
imgGrayL = imgGray.copy()#复制一个矩阵
epslion = 0.1*cv2.arcLength(c[10],True)
approx = cv2.approxPolyDP(c[10],epslion,True)
imgGrayL = cv2.drawContours(imgGrayL,[approx],0,(0,255,255),2)
# 设置epsilon = 0.05为周长
imgGrayL2 = imgGray.copy()#复制一个矩阵
epslion = 0.05*cv2.arcLength(c[10],True)
approx = cv2.approxPolyDP(c[10],epslion,True)
imgGrayL2 = cv2.drawContours(imgGrayL2,[approx],0,(0,0,255),2)
imgcom = np.hstack((imgGrayL,imgGrayL2))
#显示图片
cv2.imshow('imgGrayL',imgcom)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
如果你也喜欢编程,点击群号加入我们的QQ大家庭 928357277吧!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)