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

文章版权归作者所有,未经允许请勿转载。

免费节点实时更新

热门文章

最新文章

归档