OpenCV_9 图像轮廓

前言

本节主要是OpenCV中轮廓查找的基本知识,以及API的使用。


一、轮廓查找基础

1.轮廓基础知识

  • 轮廓怎么定义?
    具有相同颜色或强度的连续点的曲线
  • 轮廓作用
    图形分析
    物体的识别与检测
  • 注意事项
    为了检测的准确性,需要先对图像进行二值化或Canny操作
    画轮廓时会修改输入的图像

2.轮廓查找API

findContours()
声明:void findContours( InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point());
参数:
   image:图像
   mode:模式
   method:
返回值:
   contours:所有轮廓的列表
   hierarchy:轮廓间的层级关系

mode:
   RETR_EXTERNAL = 0 仅检索最外部轮廓。
   RETR_LIST = 1 检索所有轮廓,而不建立任何层次关系。
   RETR_CCOMP = 2 检索所有轮廓并将其组织为两级层次结构。在顶层,存在组件的外部边界。在第二层,存在孔的边界。如果连接组件的孔内有另一个轮廓,则它仍位于顶层。
   RETR_TREE = 3 检索所有轮廓并按树形存储

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

method
   CHAIN_APPROX_NONE = 1 保存所有轮廓上的点
   CHAIN_APPROX_SIMPLE = 2 只保存角点

contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

3.轮廓绘制

轮廓API

drawContours()
声明:void drawContours( InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness = 1, int lineType = LINE_8, InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point() );
参数:
   image:图像
   contours:轮廓查找返回的点集
   contourIdx:轮廓顺序号,-1绘制所有轮廓
   color:颜色
   thickness:线宽

代码案例:

import cv2
import numpy as np 

img = cv2.imread('./picture/star.jpg')
img = cv2.resize(img, None, fx = 0.4, fy = 0.4)

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(img_gray, 150, 255, cv2.THRESH_BINARY)

contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 绘制轮廓
cv2.drawContours(img, contours, -1, (0,0,255))
cv2.imshow('star', img)
cv2.waitKey(0)

结果展示:
请添加图片描述

轮廓的面积和周长

面积:

contourArea()
声明:double contourArea( InputArray contour, bool oriented = false );
参数:
   contours:轮廓查找返回的点集
   oriented:定向区域标志如果为真,函数将根据轮廓方向(顺时针或逆时针)返回带符号区域值。使用此功能,您可以通过获取区域的符号来确定轮廓的方向。默认情况下,参数为false,这意味着返回绝对值。

周长:

contourArea()
声明:double arcLength( InputArray curve, bool closed );
参数:
   curve:一个曲线,轮廓就可以
   closed:轮廓是否闭合

代码示例:

#计算面积
area = cv2.contourArea(contours[1])
print("area = %d "%(area))

# 计算周长
len = cv2.arcLength(contours[1], True)
print("len = %d "%(len))

二、其他框选图像方法

1.多边形逼近与凸包

轮廓查找会将所有轮廓的点都保存,占用大量空间,而很多时候并不需要这么精确的轮廓,这时候就可以使用多边形逼近与凸包
在这里插入图片描述
上图中左边为多边形逼近,右边为凸包。

approxPolyDP()
声明:void approxPolyDP( InputArray curve, OutputArray approxCurve, double epsilon, bool closed );
参数:
   curve:一个曲线,轮廓就可以
   epsilon:精度
   closed:轮廓是否闭合

convexHull()
声明:void convexHull( InputArray points, OutputArray hull, bool clockwise = false, bool returnPoints = true );
参数:
   points:点,轮廓就可以
   clockwise:顺时针绘制

代码示例:

import cv2
import numpy as np 

def drawshape(src, points):
    i = 0
    while i < len(points):
        if i == len(points) - 1:
            x, y = points[i][0]
            x1, y1 = points[0][0]    
            cv2.line(src, (x, y), (x1, y1), (0, 0, 255), 2)
        else:
            x, y = points[i][0]
            x1, y1 = points[i+1][0]
            cv2.line(src, (x, y), (x1, y1), (0, 0, 255), 2)
        i += 1 

img = cv2.imread('./picture/hand.png')
img = cv2.resize(img, None, fx = 0.4, fy = 0.4)

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(img_gray, 120, 255, cv2.THRESH_BINARY)

contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 多边形逼近
approx = cv2.approxPolyDP(contours[0], 20, True)
drawshape(img, approx)

# 凸包
hull = cv2.convexHull(contours[0])
drawshape(img, hull)

cv2.imshow('hand', img)
cv2.waitKey(0)

结果展示:
请添加图片描述

2.外接矩形

在这里插入图片描述
图中红色矩形为最小外接矩形,绿色矩形为最大外接矩形

minAreaRect()
声明:RotatedRect minAreaRect( InputArray points );
参数:
   points:点,轮廓就可以
返回值:
   RotatedRect:带旋转角度的矩形,可以通过这个将图形放正
     x,y:起始点
     width,height:宽和高
     angle:旋转角度

boundingRect()
声明:Rect boundingRect( InputArray array );
参数:
   array:轮廓
返回值:
   Rect:矩形
     x,y:起始点
     width,height:宽和高

代码示例:

import cv2
import numpy as np 

img = cv2.imread('./picture/hand.png')
img = cv2.resize(img, None, fx = 0.4, fy = 0.4)

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(img_gray, 120, 255, cv2.THRESH_BINARY)

contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 最小外接矩形 红色
r = cv2.minAreaRect(contours[0])
box = cv2.boxPoints(r)
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0, 0, 255), 2)

# 最大外接矩形 绿色
x, y, w, h = cv2.boundingRect(contours[0])
cv2.rectangle(img, (x, y), (x+w, y+h),  (0, 255, 0), 2)


cv2.imshow('hand', img)
cv2.waitKey(0)

代码中函数boxPoints(),用来查找旋转矩形的四个顶点,绘制旋转矩形。

boxPoints()
声明:void boxPoints(RotatedRect box, OutputArray points);
参数:
   box:输入旋转矩形

结果展示:
请添加图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值