OpenCV-图像轮廓处理(opencv图像轮廓提取)
各位同学好,今天和大家分享一下opencv中如何获取图像轮廓,以及对轮廓的一些其他操作。内容有:
(1)轮廓检测:cv2.findContours();(2)轮廓绘制:cv2.drawContours();(3)轮廓近似:cv2.approxPolyDP();(4)面积计算:cv2.contourArea();(5)周长计算:cv2.arcLength();(6)外接矩形:cv2.rectangle();(7)外接圆:cv2.circle()
正文
在开始前,先导入需要用到的库文件以及图像数据,定义一个图像显示函数,方便后续绘图。
import cv2 import numpy as np # 获取图片所在文件夹 filepath = 'C:\\...\\opencv\\img' # 获取文件夹中的某一张图片 img = cv2.imread(filepath+'\\test2.png') # 定义绘图函数 def cv_show(name,img): # 传入自定义图像名,即图像变量 cv2.imshow(name,img) # 图片不会自动消失 cv2.waitKey(0) # 手动关闭窗口 cv2.destroyWindow()
1. 图像轮廓
1.1 获取图像轮廓
方法: contours, hierarchy = cv2.findContours(img, mode, method)
参数:
- img:输入的图像,最好是二值图
- mode:轮廓检索模式,如下
- RETR_EXTERNAL:只检索最外面的轮廓
- RETR_LIST:检索所有的轮廓,并将其保存到一条链表中
- RETR_CCOMP:检索所有的轮廓,并将它们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界
- RETR_TREE:常用,检索所有的轮廓,并重构嵌套轮廓的整个层次。保存了所有的轮廓,用哪个调用哪个
method:轮廓逼近方法,如下
- CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。正常画出所有轮廓
- CHAIN_APPROX_SIMPLE:压缩水平的、垂直的、斜的部分,即函数只保留他们的终点坐标。压缩得到更精简的结果,例如一个矩形轮廓只需4个点来保存轮廓信息
返回值:
- contours:列表,保存轮廓信息。每一个元素都是图像的轮廓
- hierarchy:数组,分层保存轮廓信息。元素数和轮廓数一致
1.2 绘制图像轮廓
方法: cv2.drawContours(img, contours, contourIdx, color, thickness)
参数:
- img:指明在哪幅图像上绘制轮廓;image为三通道才能显示轮廓
- contours:图像轮廓信息,列表形式
- contours:指定绘制轮廓列表中的哪条轮廓。如果是-1,则绘制其中的所有轮廓。
- color:代表绘制轮廓的线条颜色,根据BGR调整,若为(0,0,255)则为红色。
- thickness:线条粗细
1.3 代码演示
首先将读入的图像变成灰度图cv2.cvtColor(),再使用图像阈值处理方法将灰度图转换成二值图cv2.threshold(),像素值超过阈值127的变成255,低于127的像素值变成0,实现二值化。将二值化处理后的图像thresh传入轮廓检测函数。图像阈值处理方法见下文第4节:opencv 图像处理:边界填充、图像融合、图像阈值、数值计算
#(1)图像处理 # 将读入的图像变成灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 图像数值超过127取255,小于127的变成0 ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) # ret接收阈值,thresh接收处理后的图像 #(2)轮廓检测 # 输入图像最好是二值图 contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # 返回值:contours轮廓信息;hierarchy层级,把结果保存在一个层级中 #(3)绘制轮廓 # 注意要将原图(彩色图)复制一份,不然原图会在函数处理完之后改变 draw = img.copy() #draw改变不会导致img改变 # 在draw画板上绘制轮廓;画第几个轮廓,-1代表所有轮廓;BGR分别对应(0,0,255),用红色线画轮廓;线条宽2 res = cv2.drawContours(draw, contours,-1, (0, 0, 255), 2) # 展示图像 cv_show('res',res)
第1张为原始图像,第2张为contourIdx=-1时绘制轮廓后的图像 ,第3张为contourIdx=3时绘制的轮廓。contourIdx中保存了所有的轮廓信息。
2. 轮廓特征
2.1 轮廓计算
轮廓计算有非常多种方法,这里只介绍两个,计算轮廓周长和面积。
在图像轮廓获取函数中cv2.findContours(),我们获取了轮廓信息返回值contours,在计算时,不能将轮廓全部放进去计算,计算时需要选出其中一个。下面使用轮廓信息中的第0个轮廓计算它的面积和周长。
# 获取某一个轮廓用于计算 cnt = contours[0] # ==1== 面积 cv2.contourArea(cnt) # 8500.5 # ==2== 周长 cv2.arcLength(cnt,True) # 437.948
2.2 轮廓近似
方法: cv2.approxPolyDP(curve, epsilon, closed)
参数:
- curve: 需要进行近似的轮廓
- epsilon: 判断点到相对应的线段的距离的阈值,这是原始曲线与其近似值之间的最大距离。阈值越小,折线的形状越接近曲线。
- closed: 若为true,曲线第一个点与最后一个点连接形成闭合曲线,若为false,曲线不闭合。
下面使用的阈值是cv2.arcLength(cnt,True),即轮廓的周长。取轮廓周长的0.1倍来作为contours[0]轮廓的近似。
# 获取图像 img = cv2.imread(filepath+'\\test1.png') # 获取一张图像 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 灰度图 ret,thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 二值化 contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # 轮廓提取 cnt = contours[0] # 获取其中一层轮廓 draw = img.copy() # 绘制轮廓 res = cv2.drawContours(draw, [cnt], -1, (0,0,255), 2) # 在draw图像中绘制cnt轮廓 cv_show('res',res) # 绘图 # 轮廓近似 epsilon = 0.1*cv2.arcLength(cnt,True) # 以周长的百分比作为阈值,指定的越小,得到的轮廓和原来的区别较小 approx = cv2.approxPolyDP(cnt, epsilon, True) # 近似函数,cnt为轮廓,epsilon阈值。返回近似后的轮廓 # 绘图展示 draw = img.copy() res = cv2.drawContours(draw, [approx], -1, (255,0,0), 2) # 将近似后的轮廓approx画在原图上,用蓝色表示,线条粗2 cv_show('res',res)
第一张图为图像轮廓,第二张图为轮廓近似后的结果
2.3 轮廓的外接矩形
首先在轮廓提取函数的返回值contours中,选取一个轮廓信息用于求它的外接矩形。
计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的
x, y, w, h = cv2.boundingRect(轮廓信息)
返回四个值。x,y是矩阵左上点的坐标;w,h是矩阵的宽和高。
外接矩形绘制函数
cv2.rectangle(img, pt1, pt2, color, thickness)
参数:
- img: 原始图片作为画板
- pt1: 长方形框左上角坐标 (x, y)
- pt2: 长方形框右下角坐标 (x+w, y+h)
- color: 线条颜色(B, G, R)
- thickness: 线条粗细
在图片img上画长方形,坐标原点是图片左上角,向右为x轴正方向,向下为y轴正方向。
# 获取轮廓信息 img = cv2.imread(filepath+'\\test1.png') # 读取图像 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 灰度处理 ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) # 二值化处理 contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # 获取轮廓信息 cnt = contours[0] # 指定某一层轮廓 # 轮廓的外接矩形 x,y,w,h = cv2.boundingRect(cnt) # 计算外接矩形,返回矩形的左上坐标点,和一长一宽 rectangle = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) # 根据坐标绘制矩形,绿色线条 cv_show('rectangle',rectangle)
得到矩形的宽和高,接下来就可以计算轮廓面积和外接矩形面积的比值。
area = cv2.contourArea(cnt) # 轮廓面积计算函数 x,y,w,h = cv2.boundingRect(cnt) # 获取坐标点和边长 rect_area = w*h # 计算外接矩形面积 extent = area/rect_area # 计算比值 print('轮廓面积和外接矩形面积之比:',extent)
2.4 轮廓的外接圆
获取轮廓的圆心坐标和半径
(x,y), radius = cv2.minEnclosingCircle(轮廓信息)
轮廓外接圆函数
cv2.circle(img, center, radius, color, thickness, shift)
- img: 输入的图片作为画板
- center: 圆心位置
- radius: 圆的半径
- color: 圆的颜色
- thickness: 正数表示圆形轮廓的粗细。负数表示要绘制实心圆。
- shift: 圆心坐标点和半径值的小数点位数
# 轮廓外接圆 # 返回圆心坐标和半径 (x,y),radius = cv2.minEnclosingCircle(cnt) # 圆心坐标 center = (int(x),int(y)) # 半径 radius = int(radius) # 绘制外接圆,输入整型 circle = cv2.circle(img,center,radius,(255,0,0),2) cv_show('circle',circle)
最后有惊喜(别错过哦)
跻身大厂是每一个程序员的梦想,也希望有机会可以大放异彩,成绩斐然。不过,不积跬步无以至千里,理想和现实的距离是需要努力来不断缩短的。
所以这里我准备了一些礼包,希望能够帮助到各位小伙伴。
★礼包1
如果对学习没有自制力或者没有一起学习交流的动力,欢迎私信或者评论区留言,我会拉你进学习交流群,我们一起交流学习,报团打卡,群内更有众多福利等你来解锁哟,赶快加入我们吧!
★礼包2
?Python全套电子书,200本总共6个G电子书资料,囊括Python各大领域。
?Python练手项目,包括爬虫、数据分析、机器学习、人工智能、小游戏开发。
版权声明:
作者: freeclashnode
链接: https://www.freeclashnode.com/news/article-1403.htm
来源: FreeClashNode
文章版权归作者所有,未经允许请勿转载。
热门文章
- 9月1日|21M/S,Shadowrocket/SSR/V2ray/Clash免费节点订阅链接每天更新
- 8月31日|20.3M/S,V2ray/Shadowrocket/SSR/Clash免费节点订阅链接每天更新
- 8月30日|22.8M/S,SSR/Clash/Shadowrocket/V2ray免费节点订阅链接每天更新
- 9月15日|20.4M/S,Shadowrocket/V2ray/SSR/Clash免费节点订阅链接每天更新
- 8月29日|22.2M/S,V2ray/Clash/SSR/Shadowrocket免费节点订阅链接每天更新
- 8月24日|19.3M/S,Shadowrocket/V2ray/Clash/SSR免费节点订阅链接每天更新
- 8月28日|20.4M/S,SSR/Clash/Shadowrocket/V2ray免费节点订阅链接每天更新
- 9月2日|21.4M/S,SSR/Shadowrocket/Clash/V2ray免费节点订阅链接每天更新
- 8月27日|21.5M/S,Clash/V2ray/SSR/Shadowrocket免费节点订阅链接每天更新
- 9月16日|18M/S,SSR/Shadowrocket/Clash/V2ray免费节点订阅链接每天更新
最新文章
- 9月19日|23M/S,Clash/SSR/Shadowrocket/V2ray免费节点订阅链接每天更新
- 9月18日|22.9M/S,Clash/Shadowrocket/V2ray/SSR免费节点订阅链接每天更新
- 9月17日|21.6M/S,SSR/Shadowrocket/V2ray/Clash免费节点订阅链接每天更新
- 9月16日|18M/S,SSR/Shadowrocket/Clash/V2ray免费节点订阅链接每天更新
- 9月15日|20.4M/S,Shadowrocket/V2ray/SSR/Clash免费节点订阅链接每天更新
- 9月14日|20M/S,Shadowrocket/SSR/Clash/V2ray免费节点订阅链接每天更新
- 9月13日|22.3M/S,Shadowrocket/V2ray/Clash/SSR免费节点订阅链接每天更新
- 9月12日|22.9M/S,Clash/V2ray/Shadowrocket/SSR免费节点订阅链接每天更新
- 9月11日|20.4M/S,Shadowrocket/Clash/SSR/V2ray免费节点订阅链接每天更新
- 9月10日|21.9M/S,V2ray/SSR/Clash/Shadowrocket免费节点订阅链接每天更新