【opencv图像处理】-- 6.图像轮廓(面积周长)、多边形逼近、外接矩形、查找/绘制轮廓

希望有能力的朋友还是拿C++做。

本节讨论查找、绘制图像轮廓,轮廓的面积,周长,多边形逼近,多边形凸包,轮廓的外接矩形

1. 图形轮廓(contours)

具有相同颜色或灰度的连续点的曲线,轮廓是形状分析和物体的检测和识别中很有用

  • 图形分析
  • 物体的识别和检测
  • 注意:
    • 为了检测的准确性,首先要二值化或canny操作
    • 画轮廓时会修改输入的图像,如果之后想继续使用原始图像,应该先将原始图像储存到其他变量

1.1 查找轮廓

  • cv2.findContours(image, mode, method…)
    • mode:查找轮廓模式
      • RETR_EXTERNAL=0 只检测外围轮廓
      • RETR_LIST=1 检测的轮廓不建立等级关系,检测所有轮廓
      • RETR_CCOMP=2 每层最多两级,从小到大,从里到外
      • RETR_TREE = 3 按照树形储存轮廓,从大到小,从右到左
    • method轮廓近似方法
      • CHAIN_APPROX_NONE 保存轮廓上的所有点
      • CHAIN_APPROX_SIMPLE 只保存焦点,比如四边形只存储四个角,常用
    • 返回值:contour和hierachy即轮廓和等级
import cv2
import numpy as np

cat = cv2.imread('cat.jpeg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)

#二值化,有两个返回值,阈值,结果
ret, binary = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)

cv2.imshow('img', img)
# cv2.imshow('img2', binary)

contours, hierarchy = cv2.findContours(binary, mode = cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE)

print(contours)
cv2.waitKey(0)
cv2.destroyAllWindows()

1.2 绘制轮廓

  • drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
    • image 要绘制的轮廓图像
    • contours: 轮廓点
    • contouridx 要绘制的轮廓编号 -1表示绘制所有轮廓
    • color 轮廓的颜色 (0,0,255)表示红色
    • thickness 线宽 -1 表示全部填充
import cv2
import numpy as np

cat = cv2.imread('cat.jpeg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)

#二值化,有两个返回值,阈值,结果
ret, binary = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)
cat_cp = cat.copy()

contours, hierarchy = cv2.findContours(binary, mode = cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE)

cv2.drawContours(cat_cp, contours, -1, (0, 0, 255), 2)

cv2.imshow('cat', cat)
cv2.imshow('contours', cat_cp)

cv2.waitKey(0)
cv2.destroyAllWindows()

1.3 轮廓的面积和周长

单位为像素,再找到轮廓后,会有很多细小的轮廓,可以通过轮廓面积进行过滤

  • 轮廓面积 contourArea(contour)
  • 轮廓周长 arcLengh(curve, closed)
    • curve即轮廓
    • closed是否是闭合的轮廓
import cv2
import numpy as np

cat = cv2.imread('cat.jpeg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)

#二值化,有两个返回值,阈值,结果
ret, binary = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)
cat_cp = cat.copy()

contours, hierarchby = cv2.findContours(binary, mode = cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE)

#一个轮廓的面积
area = cv2.contourArea(contours[0])
print(area)

#一个轮廓周长
perimeter = cv2.arcLength(contours[1], closed=True)
print(perimeter)

2. 多边形逼近

findContours后的轮廓信息contours可能过于复杂不平花,可以用approxPolyDP函数对该多边形曲线近似,这就是轮廓的多边形逼近。

  • approxPolyDP就是以多边形去逼近轮廓,采用的是Douglas-Peucker算法(DP)
  • DP算法简单,就是不断找多边形最远的点加入形成新的多边形,指导最短距离小于指定精度。
    • approxPolyDP(curbe, epsilon, closed[])
      • curve就是要近似逼近的轮廓
      • epsilon 即DP算法使用的阈值,偏差值5分半开始有详解
      • closed轮廓是否闭合

import cv2
import numpy as np

hand = cv2.imread('hand.jpg')
img = cv2.cvtColor(hand, cv2.COLOR_BGR2GRAY)

#二值化,有两个返回值,阈值,结果
ret, binary = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)
#hand_cp = img.copy()
hand_cp2 = img.copy()
contours, hierarchy = cv2.findContours(binary, mode = cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE)

#cv2.drawContours(hand_cp, contours, -1, (0, 0, 255), 2)

#cv2.imshow('cat', hand)
#cv2.imshow('contours', hand_cp)
print(len(contours))
#使用多边形逼近,近似模拟手的轮廓
#阈值给20,阈值越大,逼近效果越粗糙
approx = cv2.approxPolyDP(contours[0], 20, closed=True)
#本质还是一个轮廓数据

cv2.drawContours(hand_cp2, [approx], 0, (0, 0, 255), 2)
cv2.imshow('moni', hand_cp)


cv2.waitKey(0)
cv2.destroyAllWindows()

3. 多边形凸包

多边形逼近是高度近似,凸包和多边形逼近很像,只不过它是物体最外层的凸多边形,凸包是指完全包含所有轮廓,并且仅由轮廓上的点构成的多边形。

  • 完全包含所有轮廓
  • 凸包的每一处都是凸的,在凸包内,任意三个连续点的内角小于180°
  • convexHull(points[, hull[, clockwise[r, eturnPoints[]]]])
    • points 轮廓
    • clockwise 顺时针绘制
import cv2
import numpy as np

hand = cv2.imread('hand.jpg')
img = cv2.cvtColor(hand, cv2.COLOR_BGR2GRAY)

#二值化
ret, binary = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)

hand_cp2 = img.copy()
contours, hierarchy = cv2.findContours(binary, mode = cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE)

#计算凸包
hull = cv2.convexHull(contours[0])

cv2.namedWindow('moni', cv2.WINDOW_NORMAL)
cv2.resizeWindow('moni', 640, 480)
cv2.drawContours(hand_cp2, [hull], 0, (0, 0, 255), 2)
cv2.imshow('moni', hand_cp2)


cv2.waitKey(0)
cv2.destroyAllWindows()

4. 外接矩形

  • 最小外接矩形 minAreaRect(points):有可能会有旋转
  • 最大外接矩形 boundingRect(points):没有旋转,方方正正,返回4点坐标
import cv2
import numpy as np

cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.resizeWindow('img', 640, 480)
hand = cv2.imread('hand.jpg')

img = cv2.cvtColor(hand, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)
hand_cp2 = img.copy()

contours, hierarchy = cv2.findContours(binary, mode = cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE)

# rect是一个rotated 的矩形,包含起始坐标(x,y),长宽,旋转角度
# 最小外接矩形
rect = cv2.minAreaRect(contours[540])
print(rect)

# 最大外接矩形,方方正正,返回四个点x,y  w,h
x,y,w,h = cv2.boundingRect(contours[540])
cv2.rectangle(hand_cp2, (x,y), (x+w, y+h), (0,0,255), 2)




#画出矩形,画旋转矩形有用的
#帮我们计算出旋转矩形的4个坐标点
#坐标为整数
box = cv2.boxPoints(rect)
#四舍五入,再取整
box = np.round(box).astype('int')

cv2.drawContours(hand_cp2, [box], 0, (255,0,0), 2)

cv2.imshow('img', hand_cp2)

cv2.waitKey(0)
cv2.destroyAllWindows()
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值