findContours、minAreaRect、boxPoints、boundingRect与drawContours使用说明

findContoursminAreaRectboxPointsboundingRect与drawContours使用说明

一、findContours查找轮廓函数

用法:cnt, hierarchy = cv2.findContours( , 检索模式 , 轮廓近似办法 )

  1. 检索模式:
  • cv2.RETR_EXTERNAL:

    只检测外轮廓

  • cv2.RETR_LIST:

    检测的轮廓建立等级关系:

    ​ 外轮廓为同一层级 ,同一外轮廓的内轮廓为同一层级
    ​ 双层轮廓顺序基于外轮廓最上像素点Y坐标从大到小排序(图 片的从下到上),若存在Y坐标相同情况下 根据X坐标从大到 小排序(图片的从右到左)
    ​ 若有多个内轮廓,内轮廓排序基于内轮廓最上像素点Y坐标从 大到小排序(图片的从下到上),若存在Y 坐标相同情况下根 据X坐标从大到小排序(图片的从右到左)

  • cv2.RETR_TREE :

    不同层级的轮廓顺序从里到外:

    ​ 同级轮廓根据轮廓最上像素点Y坐标从大到小排序(图片的从 下到上),若存在Y坐标相同情况下根据X坐 标从大到小排序 (图片的从右到左)

    ​ 若一个轮廓内有子轮廓,回先查找该轮廓的所有子轮廓后才会 继续同级轮廓的查找。(有点像深搜)

2.轮廓近似办法:

  • cv2.CHAIN_APPROX_NONE:

    存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1

  • cv2.CHAIN_APPROX_SIMPLE:

    压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息

3.CNT:

  • 一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray(数组)表示。

4.hierarchy:

  • 各轮廓之间的关系

  • 下面具体解释下hierarchy输出的矩阵参数的意义

    其输出矩矩阵大小为NXM, 其中N为轮廓的个数,M恒等于4,也就是说每一行的4个数,能够表示出轮廓间的相互关系,那么具体是怎样表示的呢

    第一个数:表示同一级轮廓的下个轮廓的编号,如果这一级轮廓没有下一个轮廓,一般是这一级轮廓的最后一个的时候,则为-1

    第二个数:表示同一级轮廓的上个轮廓的编号,如果这一级轮廓没有上一个轮廓,一般是这一级轮廓的第一个的时候,则为-1

    第三个数:表示该轮廓包含的下一级轮廓的第一个的编号,假如没有,则为-1

    第四个数: 表示该轮廓的上一级轮廓的编号,假如没有上一级,则为-1

常用:

from cv2 import cv2
import numpy as np

img = cv2.imread('D:/xxx.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)		#findContours只能检测二值化后的图片

contours,Hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
print (type(contours))  
print (type(contours[0])) 

>>> <class 'list'>				# 第一个返回值类型为list
	<class 'numpy.ndarray'>		# list 的中的每个元素是numpy中的ndarray

二、minAreaRect最小外接矩形函数:

用法:rect = cv2.minAreaRect(cnt)

  1. 其中cnt要求最小外接矩形的点集数组或向量,这个点集不定个数。

  2. 返回一个Box2D结构rect:

    rect [0] : 矩形中点坐标

    rect [1] [0] : 宽度width

    rect [1] [1] :长度heith

    rect [2] : 旋转角度

其中旋转角度θ是水平轴(x轴)逆时针旋转,与碰到的矩形的第一条边的夹角,且width与height不是按照长短来定义的,而是将这第一条边作为width。

在这里插入图片描述

当使用findContours返回的轮廓不止一个时,使用循环得到每个轮廓的最小外接矩形:

for cnt in contours:      
    rect = cv2.minAreaRect(cnt)
	print("中心坐标:", rect[0])
    print("宽度:", rect[1][0])
    print("长度:", rect[1][1])
    print("旋转角度:", rect[2])
    
>>> 中心坐标: ( x1 , y1 )
	宽度: width1
	长度: heith1
	旋转角度: θ1
    中心坐标: ( x2 , y2 )
	宽度: width2
	长度: heith2
	旋转角度: θ2
    ······
    

三、boxPoints获取矩形的四个顶点坐标函数

用法:box = cv2.boxPoints(rect) # 获取矩形四个顶点,浮点型

box = np.int0(box) # 取整

但这四个坐标的对应点我们并不明确,对此,可从坐标值的大小特征入手,将四个坐标与矩形的四个顶点匹配:

​ 在opencv的坐标体系下,纵坐标最小的是top_point,纵坐标最大的是bottom_point, 横坐标最小的是 left_point,横坐标最大的是right_point。

box = cv2.boxPoints(rect)
box = np.int0(box)

left_point_x = np.min(box[:, 0])	# 获取四个顶点坐标
right_point_x = np.max(box[:, 0])
top_point_y = np.min(box[:, 1])
bottom_point_y = np.max(box[:, 1])
     
left_point_y = box[:, 1][np.where(box[:, 0] == left_point_x)][0]
right_point_y = box[:, 1][np.where(box[:, 0] == right_point_x)][0]
top_point_x = box[:, 0][np.where(box[:, 1] == top_point_y)][0]
bottom_point_x = box[:, 0][np.where(box[:, 1] == bottom_point_y)][0]
# 上下左右四个点坐标

vertices = np.array([[top_point_x, top_point_y], [bottom_point_x, bottom_point_y], [left_point_x, left_point_y], [right_point_x, right_point_y]])

四、boundingRect最小正矩形函数

用法:x, y, w, h = cv2.boundingRect(cnt)

​ 其中 x,y 为矩形左上角顶点的坐标

​ w,h为矩形的宽和长

for cnt in contours
	x, y, w, h = cv2.boundingRect(cnt)
    print(x)
    print(y)
    print(w)
    print(h)
>>> x1
    y1
    
    w1
    h1
·······

五、drawContours轮廓描绘函数

用法:cv2.drawContours(img , list , a , ( b , g , r ) , thickness )

  1. list:表示轮廓的list
  2. a :需要绘制的轮廓号, -1 为全部绘制
  3. thickness : 厚度,-1 为填充

六、contourArea图像轮廓面积函数

用法:contourArea(contours[cnt],oriented = False)

1.contour:输入二维的向量。

此处可代入中findContours函数找到的轮廓contours[cnt]

2.oriented:有方向的区域标志。可省略

  • true:此函数依赖轮廓的方向(顺时针或逆时针)返回一个已标记区域的值。
  • false:默认值。意味着返回不带方向的绝对值。
area = cv2.contourArea(contours[cnt])

print("面积:", rect[0])

>>> 面积:area

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值