OpenCV图像处理应用(面向Python)之图像轮廓
Posted OpenCV小课堂
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV图像处理应用(面向Python)之图像轮廓相关的知识,希望对你有一定的参考价值。
OpenCV图像处理应用(面向Python)
欢迎来到梁老湿课堂
版权声明:
作者:OpenCV小课堂
导师:Fu Xianjun
本文版权归作者导师共有,欢迎转载,但未经作者同意必须在文章页面注明来源及原作者或原文链接,否则保留追究法律责任的权利。
1.图像轮廓基本概念
边缘检测虽然能够检测出边缘,但边缘是不连续的,检测到的边缘并不是一个整体。图像轮廓是指将边缘连接起来形成的一个整体,用于后续的计算。图像轮廓是图像中非常重要的一个特征信息,通过对图像轮廓的操作,我们能够获取目标图像的大小、位置、方向等信息。
轮廓是一些列相连的点组成的曲线,代表了物体的基本外形,相对于边缘,轮廓是连续的,边缘并不全是连续的。
重要的是逻辑思维:1.导入相对应所需要的包;2.读取要处理的原始图像;3进行二值化,阈值与平滑处理,如果没有学过可以查看往期教程;4.边缘检测,图像梯度与Canny边缘检测;5.轮廓查找绘制。
2.轮廓查找与绘制
2.1 OpenCV提供了 cv2.findContours()函数,实现图像轮廓的查找:
contoours,hierarchy=cv2.findContours(img,mode,method)
1.img: 输入原始图。8位单通道。
2.contours: 返回的轮廓,例如contours[i]表示第i个轮廓。
3.hierarchy: 图像的拓扑信息(轮廓层次)。
4.mode: 轮廓检 索模式,决定了轮廓的提取方式。
4.1 cv2.RETR_EXTERNAL 只检测外轮廓
4.2 cv2.RETR_LIST检测的轮廓不建立等级关系
4.3 cv2.RETR_CCOMP建立两个等级的轮廓
4.4 cv2.RETR_TREE建立一个等级树结构的轮廓
5.method: 轮廓的近似方法,决定了如何表达轮廓。
5.1 cv2.CHAIN_APPROX_NONE存储所有的轮廓点
5.2 cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息。
寻找轮廓的操作一般用于二值化图,所以通常会使用阈值分割或Canny边缘检测先得到二值图。
显示下面这张图有几个轮廓并且绘制出轮廓
显示有几个轮廓以及轮廓大小
import cv2
import numpy as np
img = cv2.imread('qwer.png') #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,220,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\\
cv2.CHAIN_APPROX_NONE) #寻找轮廓
n=len(contours) #轮廓个数
print(n)
print(len(contours[0])) #轮廓0像素数目
print(len(contours[1])) #轮廓1像素数目
print(len(contours[2])) #轮廓2像素数目
#显示有几个轮廓并且显示轮廓大小详情见图1
图1:
2.2 OpenCV提供了 cv2.drawContours()函数,实现图像轮廓的绘制:
img=cv2.drawContours(img, contours, contourIdx, color, thickness=None,\\
lineType=None, hierarchy=None, maxLevel=None, offset=None)
1.img: 待绘制轮廓的图像。
2.contours: 需要绘制的轮廓。
3.contourIdx: 需要绘制的边缘索引,如果为-1,则表示绘制全部轮廓。
4.color: 绘制的颜色,opencv中使用的是BGR格式,不是我们平时说的RGB。色彩空间转换。
5.thickness: 可选参数,表示绘制轮廓时使用画笔粗细,如果为-1,则表示填充,画出实心轮廓。
6.line Type: 可选参数,表示绘制轮廓时所使用的线型。
7.hierarchy: 对应函数cv2.findContours()所输出的层次信息。
8.maxLevel: 绘制轮廓层次的深度。
9.offset: 偏移参数,该参数使轮廓偏移到不同的位置展示出来。
例如我们要在一张图片中用绿色画出重点我们可以这么写
img=cv2.drawContours(img,contours,-1,(0,255,0),5)
#(0,255,0)表示颜色为绿色;5表示的是线条粗细(若为-1,则会将轮廓内部进行填充);img表示是在img这张图上画;-1表示的是画出所有轮廓
绘制所有轮廓
import cv2
import numpy as np
img = cv2.imread('qwer.png') #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,220,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\\
cv2.CHAIN_APPROX_NONE) #寻找轮廓
cv2.imshow("img",img) #显示原图像
img2 = cv2.drawContours(img,contours,-1,(0,255,0),5) #绘制轮廓,1表示绘制第几个轮廓
cv2.imshow("contours",img2) #显示轮廓
cv2.waitKey()
cv2.destroyAllWindows()
#详情见图2效果图
图2
显示图像边缘信息
import cv2
import numpy as np
img = cv2.imread('qwer.png') #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,220,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\\
cv2.CHAIN_APPROX_NONE) #寻找轮廓
n=len(contours) #轮廓个数
contoursImg=[]
for i in range(n):
temp=np.zeros(img.shape,np.uint8) #生成黑背景
contoursImg.append(temp)
contoursImg[i]=cv2.drawContours(contoursImg[i],contours,i,(0,255,0), 3) #绘制轮廓
cv2.imshow("contours[" + str(i)+"]",contoursImg[i]) #显示轮廓
cv2.waitKey()
cv2.destroyAllWindows()
一个一个画出图像中的轮廓边缘
图3
开打开打
#实战演练
import cv2
import numpy as np
img = cv2.imread('hmbb.png')
cv2.imshow("img",img) #显示原图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度图
ret, binary = cv2.threshold(gray,200,255,cv2.THRESH_BINARY_INV) #转为二值图
cv2.imshow("binary" ,binary) #显示二值化结果
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)#寻找轮廓
mask=np.zeros(img.shape,np.uint8) #生成黑背景,即全为0
mask=cv2.drawContours(mask,contours,-1,(255,255,255),-1) #绘制轮廓,形成掩膜
cv2.imshow("mask" ,mask) #显示掩膜
result=cv2.bitwise_and(img,mask) #按位与操作,得到掩膜区域
cv2.imshow("result" ,result) #显示图像中提取掩膜区域
cv2.waitKey()
cv2.destroyAllWindows()
#详情看效果图4
图4
3.计算 轮廓的面积及长度
3.1 矩特征,OpenCV提供了cv2.moments()函数来进行实现:
比较两个轮廓最简单的方法是比较二者的轮廓矩。轮廓矩代表了一个轮廓、一幅图像、一组点集的全局特征。矩信息包含了对应对象不同类型的几何特征,例如大小、位置、角度、形状等。矩特征被广泛地应用在模式识别、图像识别等方面。
retval=cv2.moments(array[,binaryImage])
1. array: 可以是点集,也可以是灰度图像或者二值图像。
2. binaryImage: 当为True时,array内所有的非零值都会被处理为1。
使用上面函数提取出图5的特征
图5
import cv2
import numpy as np
img = cv2.imread('hmbb.png') #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,200,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\\
cv2.CHAIN_APPROX_NONE) #寻找轮廓
n=len(contours) #轮廓个数
contoursImg=[]
for i in range(n):
temp=np.zeros(img.shape,np.uint8) #生成黑背景
contoursImg.append(temp)
contoursImg[i]=cv2.drawContours(contoursImg[i],contours,i,(255,255,255), 3) #绘制轮廓
cv2.imshow("contours[" + str(i)+"]",contoursImg[i]) #显示轮廓
print("计算图像的矩特征:")
for i in range(n):
moment=cv2.moments(contours[i])
print(f"轮廓i的矩:\\nmoment")
cv2.waitKey()
cv2.destroyAllWindows()
以下三张图就是图5的所有轮廓
这张图为每个轮廓矩的大小
3.2 图像轮廓的面积计算,OpenCV提供了cv2.contourArea()函数来进行实现:
1.contour : 轮廓。
2.oriented: 布尔值,当为True时,表示顺时针或逆时针计算。
计算轮廓面积
import cv2
import numpy as np
img = cv2.imread('qwer.png') #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,220,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\\
cv2.CHAIN_APPROX_NONE) #寻找轮廓
n=len(contours) #轮廓个数
contoursImg=[]
for i in range(n):
area = cv2.contourArea(contours[i])
temp = np.zeros(img.shape, np.uint8) # 生成黑背景
contoursImg.append(temp)
contoursImg[i] = cv2.drawContours(contoursImg[i], contours, i, (0, 255, 0), 3) # 绘制轮廓
cv2.imshow("contours[" + str(i) + "]", contoursImg[i])#显示轮廓
print(f"轮廓i的面积:\\narea")
cv2.waitKey()
cv2.destroyAllWindows()
图6
显示面积小于20000的轮廓
import cv2
import numpy as np
img = cv2.imread('qwer.png') #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,220,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\\
cv2.CHAIN_APPROX_NONE) #寻找轮廓
n=len(contours) #轮廓个数
contoursImg=[]
for i in range(n):
area = cv2.contourArea(contours[i])
temp=np.zeros(img.shape,np.uint8)
contoursImg.append(temp)
contoursImg[i]=cv2.drawContours(contoursImg[i],\\
contours,i,(0,255,0),3)
if area<20000:#此处为新加代码
cv2.imshow("contours["+str(i)+"]",contoursImg[i])
print(f"轮廓i的面积:\\narea")
cv2.waitKey()
cv2.destroyAllWindows()
#看下面效果图7
图7
3.3 .图像轮廓的长度计算,OpenCv提供了cv2.arcLength()函数来进行实现:
1. curve : 轮廓。
2. closed : 布尔值,当为True时,表示闭合。
计算论轮廓长度
后续有待补充
多练多学多坚持,我们下期再见。
以上是关于OpenCV图像处理应用(面向Python)之图像轮廓的主要内容,如果未能解决你的问题,请参考以下文章